@innovastudio/contentbuilder 1.3.80 → 1.3.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/package.json +1 -1
  2. package/public/contentbuilder/contentbuilder.css +13 -1
  3. package/public/contentbuilder/contentbuilder.esm.js +401 -23
  4. package/public/contentbuilder/contentbuilder.min.js +2 -2
  5. package/public/contentbuilder/lang/en.js +9 -1
  6. package/public/contentbuilder/lang/fr.js +13 -1
  7. package/public/contentbuilder/themes/colored-blue.css +4 -0
  8. package/public/contentbuilder/themes/colored-blue2.css +4 -0
  9. package/public/contentbuilder/themes/colored-blue3.css +4 -0
  10. package/public/contentbuilder/themes/colored-blue4.css +4 -0
  11. package/public/contentbuilder/themes/colored-blue5.css +4 -0
  12. package/public/contentbuilder/themes/colored-blue6.css +4 -0
  13. package/public/contentbuilder/themes/colored-blue7.css +4 -0
  14. package/public/contentbuilder/themes/colored-blue8.css +4 -0
  15. package/public/contentbuilder/themes/colored-darkblue.css +4 -0
  16. package/public/contentbuilder/themes/colored-gray.css +4 -0
  17. package/public/contentbuilder/themes/colored-green.css +4 -0
  18. package/public/contentbuilder/themes/colored-green2.css +4 -0
  19. package/public/contentbuilder/themes/colored-green3.css +4 -0
  20. package/public/contentbuilder/themes/colored-green4.css +4 -0
  21. package/public/contentbuilder/themes/colored-green5.css +4 -0
  22. package/public/contentbuilder/themes/colored-magenta.css +4 -0
  23. package/public/contentbuilder/themes/colored-orange.css +4 -0
  24. package/public/contentbuilder/themes/colored-orange2.css +4 -0
  25. package/public/contentbuilder/themes/colored-orange3.css +4 -0
  26. package/public/contentbuilder/themes/colored-pink.css +4 -0
  27. package/public/contentbuilder/themes/colored-pink2.css +4 -0
  28. package/public/contentbuilder/themes/colored-pink3.css +4 -0
  29. package/public/contentbuilder/themes/colored-pink4.css +4 -0
  30. package/public/contentbuilder/themes/colored-purple.css +4 -0
  31. package/public/contentbuilder/themes/colored-purple2.css +4 -0
  32. package/public/contentbuilder/themes/colored-red.css +4 -0
  33. package/public/contentbuilder/themes/colored-red2.css +4 -0
  34. package/public/contentbuilder/themes/colored-red3.css +4 -0
  35. package/public/contentbuilder/themes/colored-red4.css +4 -0
  36. package/public/contentbuilder/themes/colored-red5.css +4 -0
  37. package/public/contentbuilder/themes/colored-yellow.css +4 -0
  38. package/public/contentbuilder/themes/colored-yellow2.css +4 -0
  39. package/public/contentbuilder/themes/dark-blue.css +9 -5
  40. package/public/contentbuilder/themes/dark-blue2.css +9 -5
  41. package/public/contentbuilder/themes/dark-blue3.css +9 -5
  42. package/public/contentbuilder/themes/dark-gray.css +9 -5
  43. package/public/contentbuilder/themes/dark-pink.css +9 -5
  44. package/public/contentbuilder/themes/dark-purple.css +9 -5
  45. package/public/contentbuilder/themes/dark-red.css +9 -5
  46. package/public/contentbuilder/themes/dark.css +9 -5
  47. package/public/contentbuilder/themes/light-blue.css +4 -0
  48. package/public/contentbuilder/themes/light-blue2.css +4 -0
  49. package/public/contentbuilder/themes/light-blue3.css +4 -0
  50. package/public/contentbuilder/themes/light-cyan.css +4 -0
  51. package/public/contentbuilder/themes/light-gray.css +4 -0
  52. package/public/contentbuilder/themes/light-gray2.css +4 -0
  53. package/public/contentbuilder/themes/light-gray3.css +4 -0
  54. package/public/contentbuilder/themes/light-green.css +4 -0
  55. package/public/contentbuilder/themes/light-pink.css +4 -0
  56. package/public/contentbuilder/themes/light-pink2.css +4 -0
  57. package/public/contentbuilder/themes/light-purple.css +4 -0
  58. package/public/contentbuilder/themes/light-purple2.css +4 -0
  59. package/public/contentbuilder/themes/light-red.css +4 -0
  60. package/public/contentbuilder/themes/light-yellow.css +4 -0
  61. package/public/contentbuilder/themes/light-yellow2.css +4 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@innovastudio/contentbuilder",
3
3
  "type": "module",
4
- "version": "1.3.80",
4
+ "version": "1.3.82",
5
5
  "description": "",
6
6
  "main": "public/contentbuilder/contentbuilder.esm.js",
7
7
  "files": [
@@ -107,7 +107,7 @@ button:focus-visible {
107
107
  }
108
108
  }
109
109
 
110
- @media (min-width: 970px) {
110
+ @media (min-width: 971px) {
111
111
  .is-builder > div {
112
112
  display: flex;
113
113
  }
@@ -1884,6 +1884,13 @@ button:focus-visible {
1884
1884
  background: rgba(255, 255, 255, 0.2);
1885
1885
  border: rgba(0, 0, 0, 0.09) 1px solid !important;
1886
1886
  }
1887
+ #_cbhtml .is-modal .is-separator,
1888
+ .is-ui .is-modal .is-separator {
1889
+ width: 100%;
1890
+ border-top: #f0f0f0 1px solid;
1891
+ margin-bottom: 10px;
1892
+ margin-top: 10px;
1893
+ }
1887
1894
  #_cbhtml .is-modal .form-upload-larger.please-wait svg,
1888
1895
  .is-ui .is-modal .form-upload-larger.please-wait svg {
1889
1896
  transform: scale(1, 1);
@@ -1979,6 +1986,11 @@ button:focus-visible {
1979
1986
  padding: 0;
1980
1987
  border: none;
1981
1988
  }
1989
+ #_cbhtml .is-modal div.is-draggable > span,
1990
+ .is-ui .is-modal div.is-draggable > span {
1991
+ pointer-events: none;
1992
+ user-select: none;
1993
+ }
1982
1994
  #_cbhtml .is-modal div.is-modal-bar,
1983
1995
  .is-ui .is-modal div.is-modal-bar {
1984
1996
  position: absolute;
@@ -4508,6 +4508,7 @@ class Util {
4508
4508
  Array.prototype.forEach.call(subblocks, subblock => {
4509
4509
  if (col.getAttribute('data-html-' + i)) {
4510
4510
  subblock.innerHTML = decodeURIComponent(col.getAttribute('data-html-' + i));
4511
+ subblock.contentEditable = true;
4511
4512
  }
4512
4513
 
4513
4514
  i++;
@@ -14996,6 +14997,7 @@ class HtmlUtil {
14996
14997
  let index = 1;
14997
14998
  let subblocks = block.querySelectorAll('[data-subblock]');
14998
14999
  Array.prototype.forEach.call(subblocks, subblock => {
15000
+ if (subblock.closest('.glide__slide--clone')) return;
14999
15001
  let html = subblock.innerHTML;
15000
15002
  block.setAttribute('data-html-' + index, encodeURIComponent(html));
15001
15003
  index++;
@@ -15046,6 +15048,79 @@ class HtmlUtil {
15046
15048
  block.getAttribute('data-settings', uniqueID);
15047
15049
  }
15048
15050
  });
15051
+ } //Make absolute (for Export/Download)
15052
+
15053
+
15054
+ if (this.builder.makeAbsolute) {
15055
+ const convertMediaUrl = imgUrl => {
15056
+ // make absolute
15057
+ let img = document.createElement('img');
15058
+ img.src = imgUrl;
15059
+ img.setAttribute('data-absoluteurl', img.src);
15060
+ imgUrl = img.getAttribute('data-absoluteurl');
15061
+ return imgUrl;
15062
+ };
15063
+
15064
+ const convertBgUrl = imgUrl => {
15065
+ // make absolute
15066
+ let img = document.createElement('img');
15067
+ img.src = imgUrl;
15068
+ img.setAttribute('data-absoluteurl', img.src);
15069
+ imgUrl = img.getAttribute('data-absoluteurl'); // Do not use imgUrl directly, change base to [%PATH%] instead
15070
+ // (to prevent auto converting back to relative path)
15071
+
15072
+ let urlBase = location.href.substring(0, location.href.lastIndexOf('/'));
15073
+ return imgUrl.replace(urlBase, '[%PATH%]'); // Example:
15074
+ // url = http://localhost:8080/uploads/image.jpg
15075
+ // urlBase = http://localhost:8080
15076
+ // become: [%PATH%]/uploads/image.jpg
15077
+ };
15078
+
15079
+ const convertMedia = (elm, attrName) => {
15080
+ if (elm.hasAttribute(attrName)) {
15081
+ if (!(elm.parentNode.tagName.toLowerCase() === 'video' || elm.parentNode.tagName.toLowerCase() === 'audio')) return;
15082
+ let imgUrl = elm.getAttribute(attrName);
15083
+ imgUrl = convertMediaUrl(imgUrl);
15084
+ elm.setAttribute(attrName, `${imgUrl}`);
15085
+ }
15086
+ };
15087
+
15088
+ let imgs = tmp.querySelectorAll('img');
15089
+ Array.prototype.forEach.call(imgs, img => {
15090
+ let src = img.src;
15091
+ img.setAttribute('src', src);
15092
+ });
15093
+ let elms = tmp.querySelectorAll('*');
15094
+ elms.forEach(elm => {
15095
+ if (elm.style.backgroundImage) {
15096
+ let s = elm.style.backgroundImage;
15097
+
15098
+ if (s.indexOf('url(') !== -1) {
15099
+ let imgUrl = s.slice(4, -1).replace(/["']/g, '');
15100
+ imgUrl = convertBgUrl(imgUrl);
15101
+ elm.style.backgroundImage = `url(${imgUrl})`;
15102
+ }
15103
+ }
15104
+
15105
+ convertMedia(elm, 'src');
15106
+ convertMedia(elm, 'data-default');
15107
+ convertMedia(elm, 'data-240');
15108
+ convertMedia(elm, 'data-360');
15109
+ convertMedia(elm, 'data-480');
15110
+ convertMedia(elm, 'data-540');
15111
+ convertMedia(elm, 'data-720');
15112
+ convertMedia(elm, 'data-1080');
15113
+ convertMedia(elm, 'data-1440');
15114
+ convertMedia(elm, 'data-2160');
15115
+
15116
+ if (elm.hasAttribute('href')) {
15117
+ if (elm.tagName.toLowerCase() === 'link') {
15118
+ let imgUrl = elm.getAttribute('href');
15119
+ imgUrl = convertMediaUrl(imgUrl);
15120
+ elm.setAttribute('href', `${imgUrl}`);
15121
+ }
15122
+ }
15123
+ });
15049
15124
  } //Cleaning
15050
15125
 
15051
15126
 
@@ -15314,6 +15389,13 @@ class HtmlUtil {
15314
15389
  return html;
15315
15390
  }
15316
15391
 
15392
+ beautify(html) {
15393
+ let beautify = JsBeautify.html;
15394
+ html = beautify(html);
15395
+ html = html.replace(/(\r\n|\r|\n){3,}/g, '$1\n');
15396
+ return html;
15397
+ }
15398
+
15317
15399
  }
15318
15400
 
15319
15401
  class UndoRedo {
@@ -15823,6 +15905,55 @@ const prepareSvgIcons = builder => {
15823
15905
  <symbol viewBox="0 0 512 512" id="ion-volume-medium">
15824
15906
  <path d="M270 407.7V104.4L175.3 192H71v128h104.3zm56.3-52.1c20.5-27.8 32.8-62.3 32.8-99.6 0-37.4-12.3-71.8-32.8-99.6l-20.4 15.3c17.4 23.6 27.8 52.7 27.8 84.3 0 31.6-10.4 60.7-27.8 84.3l20.4 15.3zm66.5 46c30-40.7 48-91 48-145.6s-18-104.9-48-145.6l-20.4 15.3c26.9 36.4 43 81.4 43 130.3 0 48.9-16.1 93.8-43 130.3l20.4 15.3z"/>
15825
15907
  </symbol>
15908
+
15909
+
15910
+
15911
+ <symbol id="icon-devices" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15912
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15913
+ <rect x="13" y="8" width="8" height="12" rx="1"></rect>
15914
+ <path d="M18 8v-3a1 1 0 0 0 -1 -1h-13a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h9"></path>
15915
+ <line x1="16" y1="9" x2="18" y2="9"></line>
15916
+ </symbol>
15917
+ <symbol id="icon-device-desktop" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15918
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15919
+ <rect x="3" y="4" width="18" height="12" rx="1"></rect>
15920
+ <line x1="7" y1="20" x2="17" y2="20"></line>
15921
+ <line x1="9" y1="16" x2="9" y2="20"></line>
15922
+ <line x1="15" y1="16" x2="15" y2="20"></line>
15923
+ </symbol>
15924
+ <symbol id="icon-device-mobile" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15925
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15926
+ <rect x="6" y="3" width="12" height="18" rx="2"></rect>
15927
+ <line x1="11" y1="4" x2="13" y2="4"></line>
15928
+ <line x1="12" y1="17" x2="12" y2="17.01"></line>
15929
+ </symbol>
15930
+ <symbol id="icon-device-laptop" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15931
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15932
+ <line x1="3" y1="19" x2="21" y2="19"></line>
15933
+ <rect x="5" y="6" width="14" height="10" rx="1"></rect>
15934
+ </symbol>
15935
+ <symbol id="icon-device-tablet" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15936
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15937
+ <rect x="5" y="3" width="14" height="18" rx="1"></rect>
15938
+ <circle cx="12" cy="17" r="1"></circle>
15939
+ </symbol>
15940
+
15941
+ <symbol id="icon-eye" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15942
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15943
+ <path d="M12 12m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0m13 0c-2.667 4.667 -6 7 -10 7s-7.333 -2.333 -10 -7c2.667 -4.667 6 -7 10 -7s7.333 2.333 10 7"></path>
15944
+ </symbol>
15945
+ <symbol id="icon-eye-off" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15946
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15947
+ <path d="M9.88 9.878a3 3 0 1 0 4.243 4.242m.581 -3.42a3.012 3.012 0 0 0 -1.45 -1.426m-3.877 -3.913a9.469 9.469 0 0 1 2.623 -.361c4 0 7.333 2.333 10 7c-.778 1.362 -1.613 2.524 -2.504 3.489m-2.138 1.859c-1.629 1.101 -3.415 1.652 -5.358 1.652c-4 0 -7.333 -2.333 -10 -7c1.374 -2.404 2.924 -4.189 4.652 -5.354m-3.652 -3.646l18 18"></path>
15948
+ </symbol>
15949
+
15950
+ <symbol id="icon-download" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
15951
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
15952
+ <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2"></path>
15953
+ <path d="M7 11l5 5l5 -5"></path>
15954
+ <path d="M12 4l0 12"></path>
15955
+ </symbol>
15956
+
15826
15957
  </defs>
15827
15958
  </svg>`;
15828
15959
  builder.dom.appendHtml(builder.builderStuff, html);
@@ -22860,7 +22991,7 @@ function getOffset(element) {
22860
22991
  top: box.top + (window.pageYOffset - document.documentElement.clientTop)
22861
22992
  };
22862
22993
  }
22863
- var location = WINDOW.location;
22994
+ var location$1 = WINDOW.location;
22864
22995
  var REGEXP_ORIGINS = /^(\w+:)\/\/([^:/?#]*):?(\d*)/i;
22865
22996
  /**
22866
22997
  * Check if the given URL is a cross origin URL.
@@ -22870,7 +23001,7 @@ var REGEXP_ORIGINS = /^(\w+:)\/\/([^:/?#]*):?(\d*)/i;
22870
23001
 
22871
23002
  function isCrossOriginURL(url) {
22872
23003
  var parts = url.match(REGEXP_ORIGINS);
22873
- return parts !== null && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port);
23004
+ return parts !== null && (parts[1] !== location$1.protocol || parts[2] !== location$1.hostname || parts[3] !== location$1.port);
22874
23005
  }
22875
23006
  /**
22876
23007
  * Add timestamp to the given URL.
@@ -53282,7 +53413,7 @@ class Module {
53282
53413
  var moduleDesc = module.getAttribute('data-module-desc');
53283
53414
 
53284
53415
  if (moduleDesc) {
53285
- moduleModal.querySelector('.is-modal-bar').innerHTML = moduleDesc + `<button class="is-modal-close" tabindex="-1" title="${util.out('Close')}">
53416
+ moduleModal.querySelector('.is-modal-bar').innerHTML = this.util.out(moduleDesc) + `<button class="is-modal-close" tabindex="-1" title="${util.out('Close')}">
53286
53417
  <svg class="is-icon-flex" style="width:30px;height:30px;"><use xlink:href="#ion-ios-close-empty"></use></svg>
53287
53418
  </button>`;
53288
53419
  } else {
@@ -53611,9 +53742,12 @@ class Code {
53611
53742
  viewhtml = this.builderStuff.querySelector('.viewhtml');
53612
53743
  }
53613
53744
 
53614
- let textarea = viewhtml.querySelector('textarea');
53745
+ let textarea = viewhtml.querySelector('textarea'); // Prevent {id} get formatted.
53746
+
53747
+ html = html.replaceAll('{id}', '__id__');
53615
53748
  let beautify = JsBeautify.html;
53616
53749
  html = beautify(html);
53750
+ html = html.replaceAll('__id__', '{id}');
53617
53751
  textarea.value = html;
53618
53752
  this.htmlUtil.view('code');
53619
53753
  });
@@ -57450,13 +57584,39 @@ class ColumnTool {
57450
57584
  <button title="${util.out('Clear')}" class="input-cell-textcolor" data-command=""><svg class="is-icon-flex" style="flex:none;width:18px;height:18px;margin-top: 2px;"><use xlink:href="#ion-ios-close-empty"></use></svg></button>
57451
57585
  </div>
57452
57586
 
57453
- <div style="padding-top:30px;">
57587
+ <div style="padding:30px 0 10px;">
57454
57588
  <label class="label-cell-grayscale label-checkbox" for="chkCellGrayscale"><input id="chkCellGrayscale" class="chk-cell-grayscale" type="checkbox" /> ${util.out('Grayscale')}</label>
57455
57589
  </div>
57456
57590
 
57457
- <div style="padding:20px 0 10px;">
57591
+ <div style="display:none;padding:20px 0 10px;">
57458
57592
  <label class="label-cell-hideonmobile label-checkbox" for="chkHideColumnOnMobile"><input id="chkHideColumnOnMobile" class="chk-cell-hideonmobile" type="checkbox" /> ${util.out('Hide Column on Mobile')}</label>
57459
57593
  </div>
57594
+
57595
+ <div class="is-separator"></div>
57596
+
57597
+ <div class="div-target" style="display: flex;justify-content: flex-end;padding: 5px 0 0;">
57598
+ <button title="${util.out('Desktop')}" class="input-device on" data-value="" style="width:40px;height:25px;">
57599
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-device-desktop"></use></svg>
57600
+ </button>
57601
+ <button title="${util.out('Tablet')}" class="input-device" data-value="sm" style="width:40px;height:25px;">
57602
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-device-tablet"></use></svg>
57603
+ </button>
57604
+ <button title="${util.out('Mobile')}" class="input-device" data-value="xs" style="width:40px;height:25px;">
57605
+ <svg class="is-icon-flex" style="width:13px;height:13px"><use xlink:href="#icon-device-mobile"></use></svg>
57606
+ </button>
57607
+ </div>
57608
+
57609
+ <div style="padding-top:0;padding-bottom:3px;">${util.out('Visibility')}:</div>
57610
+ <div class="div-visibility" style="display:flex;">
57611
+ <button title="${util.out('Visible')}" class="input-visible on" data-value="sm" style="width:100px;height:34px;">
57612
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-eye"></use></svg>
57613
+ <span>${util.out('Visible')}</span>
57614
+ </button>
57615
+ <button title="${util.out('Hidden')}" class="input-hidden" data-value="xs" style="width:100px;height:34px;">
57616
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-eye-off"></use></svg>
57617
+ <span>${util.out('Hidden')}</span>
57618
+ </button>
57619
+ </div>
57460
57620
 
57461
57621
  <!--
57462
57622
  <div style="display:none;padding-top:20px;padding-bottom:3px;">${util.out('Enlarge Row')}:</div>
@@ -59066,6 +59226,58 @@ class ColumnTool {
59066
59226
  if (!cell) return;
59067
59227
  if (inpClickSrc.value === '') return;
59068
59228
  this.builder.openMedia(cell);
59229
+ }); // Responsive Visibility
59230
+
59231
+ let btns = this.cellSettings.querySelectorAll('.input-device');
59232
+ btns.forEach(btn => {
59233
+ btn.addEventListener('click', () => {
59234
+ let cell = this.util.cellSelected();
59235
+ if (!cell) return;
59236
+ let elms = this.cellSettings.querySelectorAll('.input-device');
59237
+ elms.forEach(elm => {
59238
+ elm.classList.remove('on');
59239
+ });
59240
+ btn.classList.add('on');
59241
+ this.realtimeVisibility(cell);
59242
+ });
59243
+ });
59244
+ let btnVisible = this.cellSettings.querySelector('.input-visible');
59245
+ let btnHidden = this.cellSettings.querySelector('.input-hidden');
59246
+ btnVisible.addEventListener('click', () => {
59247
+ let cell = this.util.cellSelected();
59248
+ if (!cell) return;
59249
+ cell.classList.remove('hideonmobile');
59250
+ let divTarget = this.cellSettings.querySelector('.div-target');
59251
+ let target = this.builder.responsive.readTarget(divTarget);
59252
+
59253
+ if (target === 'xs') {
59254
+ cell.classList.remove('xs-hidden');
59255
+ } else if (target === 'sm') {
59256
+ cell.classList.remove('sm-hidden');
59257
+ } else if (target === '') {
59258
+ cell.classList.remove('desktop-hidden');
59259
+ }
59260
+
59261
+ btnVisible.classList.add('on');
59262
+ btnHidden.classList.remove('on');
59263
+ });
59264
+ btnHidden.addEventListener('click', () => {
59265
+ let cell = this.util.cellSelected();
59266
+ if (!cell) return;
59267
+ cell.classList.remove('hideonmobile');
59268
+ let divTarget = this.cellSettings.querySelector('.div-target');
59269
+ let target = this.builder.responsive.readTarget(divTarget);
59270
+
59271
+ if (target === 'xs') {
59272
+ cell.classList.add('xs-hidden');
59273
+ } else if (target === 'sm') {
59274
+ cell.classList.add('sm-hidden');
59275
+ } else if (target === '') {
59276
+ cell.classList.add('desktop-hidden');
59277
+ }
59278
+
59279
+ btnVisible.classList.remove('on');
59280
+ btnHidden.classList.add('on');
59069
59281
  });
59070
59282
  }
59071
59283
 
@@ -59256,6 +59468,16 @@ class ColumnTool {
59256
59468
  let btn = this.cellSettings.querySelector('.cmd-content-pos[data-pos="bottomright"');
59257
59469
  dom.addClass(btn, 'on');
59258
59470
  }
59471
+
59472
+ this.realtimeVisibility(cell);
59473
+ }
59474
+
59475
+ realtimeVisibility(cell) {
59476
+ let divTarget = this.cellSettings.querySelector('.div-target');
59477
+ let divVisibility = this.cellSettings.querySelector('.div-visibility');
59478
+ let target = this.builder.responsive.readTarget(divTarget);
59479
+ let valVisibility = this.builder.responsive.getVisibility(cell, target);
59480
+ this.builder.responsive.showVisibility(divVisibility, valVisibility);
59259
59481
  }
59260
59482
 
59261
59483
  openImagePicker(currentUrl, callback, btn) {
@@ -60671,17 +60893,19 @@ class ElementSpacingStyles {
60671
60893
  </select>
60672
60894
  </div>
60673
60895
  </div>
60674
-
60675
- <div style="margin-top: 25px;font-weight: bold;width:100%">${util.out('Responsive Positioning')}:</div>
60676
-
60677
- <div class="is-settings" style="width:100%;">
60678
- <div>
60679
- <label for="chkResetMarginLeft" style="letter-spacing: 0.5px;"><input type="checkbox" id="chkResetMarginLeft" value="" /> ${util.out('Reset margin left on small screen')} </label>
60896
+
60897
+ <div style="display:none">
60898
+ <div style="margin-top: 25px;font-weight: bold;width:100%">${util.out('Responsive Positioning')}:</div>
60899
+
60900
+ <div class="is-settings" style="width:100%;">
60901
+ <div>
60902
+ <label for="chkResetMarginLeft" style="letter-spacing: 0.5px;"><input type="checkbox" id="chkResetMarginLeft" value="" /> ${util.out('Reset margin left on small screen')} </label>
60903
+ </div>
60680
60904
  </div>
60681
- </div>
60682
- <div class="is-settings" style="margin-top:0;width:100%;">
60683
- <div>
60684
- <label for="chkResetMarginRight" style="letter-spacing: 0.5px;"><input type="checkbox" id="chkResetMarginRight" value="" /> ${util.out('Reset margin right on small screen')} </label>
60905
+ <div class="is-settings" style="margin-top:0;width:100%;">
60906
+ <div>
60907
+ <label for="chkResetMarginRight" style="letter-spacing: 0.5px;"><input type="checkbox" id="chkResetMarginRight" value="" /> ${util.out('Reset margin right on small screen')} </label>
60908
+ </div>
60685
60909
  </div>
60686
60910
  </div>
60687
60911
  `;
@@ -64781,6 +65005,11 @@ class ElementTool {
64781
65005
  if (ok) {
64782
65006
  this.builder.uo.saveForUndo();
64783
65007
  let elm = this.builder.activeElement;
65008
+ let subblock = false;
65009
+
65010
+ if (elm.closest('.is-subblock')) {
65011
+ subblock = true;
65012
+ }
64784
65013
  /*
64785
65014
  if(dom.hasClass(elm.parentNode, 'cell-active') || elm.parentNode.hasAttribute('data-subblock')) {
64786
65015
  // Level 1
@@ -64806,6 +65035,7 @@ class ElementTool {
64806
65035
  }
64807
65036
  */
64808
65037
 
65038
+
64809
65039
  elm.parentNode.removeChild(elm);
64810
65040
  this.elementTool.style.display = 'none';
64811
65041
  let cell = this.builder.activeCol;
@@ -64836,7 +65066,21 @@ class ElementTool {
64836
65066
  subblock.innerHTML = '<div class="spacer height-40" contentEditable="false"></div>';
64837
65067
  }
64838
65068
  });
64839
- util.clearControls(); //Trigger Change event
65069
+ util.clearControls();
65070
+
65071
+ if (subblock) {
65072
+ let block = this.builder.activeCol;
65073
+ let subblocks = block.querySelectorAll('[data-subblock]');
65074
+ var index = 1;
65075
+ Array.prototype.forEach.call(subblocks, subblock => {
65076
+ if (subblock.closest('.glide__slide--clone')) return;
65077
+ let html = subblock.innerHTML;
65078
+ block.setAttribute('data-html-' + index, encodeURIComponent(html));
65079
+ index++;
65080
+ });
65081
+ util.refreshModuleLayout(block);
65082
+ } //Trigger Change event
65083
+
64840
65084
 
64841
65085
  this.builder.opts.onChange();
64842
65086
  }
@@ -69676,7 +69920,8 @@ class Rte {
69676
69920
  // Column contains custom code.
69677
69921
  customcode = true;
69678
69922
 
69679
- if (dom.parentsHasAttribute(elm, 'data-subblock')) {
69923
+ if (elm.closest('.is-subblock')) {
69924
+ // dom.parentsHasAttribute(elm, 'data-subblock')
69680
69925
  subblock = true;
69681
69926
  }
69682
69927
  }
@@ -69702,7 +69947,7 @@ class Rte {
69702
69947
  this.showAlignButtons();
69703
69948
  this.positionToolbar();
69704
69949
  }
69705
- } else if (dom.hasClass(elm, 'spacer') || elm.tagName.toLowerCase() === 'video' || dom.hasClass(elm, 'ovl') || col.getAttribute('data-html')) {
69950
+ } else if (dom.hasClass(elm, 'spacer') || elm.tagName.toLowerCase() === 'video' || dom.hasClass(elm, 'ovl') || col.getAttribute('data-html') && !subblock) {
69706
69951
  //|| col===elm
69707
69952
  if (this.elementRteTool.style.display === 'none' || this.elementRteTool.style.display === '') {
69708
69953
  this.elementRteTool.style.display = 'flex';
@@ -73139,6 +73384,7 @@ class Resizeable {
73139
73384
 
73140
73385
  const onDown = e => {
73141
73386
  calc(e);
73387
+ if (e.target.closest('.glide__arrows')) return false;
73142
73388
  const isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;
73143
73389
  clicked = {
73144
73390
  x: x,
@@ -74828,6 +75074,54 @@ class MediaPicker {
74828
75074
 
74829
75075
  }
74830
75076
 
75077
+ class Responsive {
75078
+ constructor(builder) {
75079
+ this.builder = builder;
75080
+ const util = this.builder.util;
75081
+ const builderStuff = this.builder.builderStuff;
75082
+ this.util = util;
75083
+ this.builderStuff = builderStuff;
75084
+ const dom = this.builder.dom;
75085
+ this.dom = dom;
75086
+ }
75087
+
75088
+ getVisibility(elm, target) {
75089
+ if (target === 'xs') return !elm.classList.contains('xs-hidden');
75090
+ if (target === 'sm') return !elm.classList.contains('sm-hidden');
75091
+ if (target === '') return !elm.classList.contains('desktop-hidden');
75092
+ }
75093
+
75094
+ setVisibility(visibility, elm, target) {
75095
+ if (target === 'xs') {
75096
+ if (visibility) elm.classList.remove('xs-hidden');else elm.classList.add('xs-hidden');
75097
+ }
75098
+
75099
+ if (target === 'sm') {
75100
+ if (visibility) elm.classList.remove('sm-hidden');else elm.classList.add('sm-hidden');
75101
+ }
75102
+
75103
+ if (target === '') {
75104
+ if (visibility) elm.classList.remove('desktop-hidden');else elm.classList.add('desktop-hidden');
75105
+ }
75106
+ }
75107
+
75108
+ readTarget(area) {
75109
+ const inp = area.querySelector('.input-device.on');
75110
+ return inp.getAttribute('data-value');
75111
+ }
75112
+
75113
+ showVisibility(area, visibility) {
75114
+ if (visibility) {
75115
+ area.querySelector('.input-visible').classList.add('on');
75116
+ area.querySelector('.input-hidden').classList.remove('on');
75117
+ } else {
75118
+ area.querySelector('.input-visible').classList.remove('on');
75119
+ area.querySelector('.input-hidden').classList.add('on');
75120
+ }
75121
+ }
75122
+
75123
+ }
75124
+
74831
75125
  class ContentBuilder {
74832
75126
  constructor(opts = {}) {
74833
75127
  let defaults = {
@@ -75037,6 +75331,39 @@ class ContentBuilder {
75037
75331
  </div>
75038
75332
  </div>
75039
75333
  `,
75334
+ pageTemplate: `<!DOCTYPE html>
75335
+ <html lang="en">
75336
+ <head>
75337
+ <meta charset="utf-8">
75338
+ <title>Page</title>
75339
+ <meta name="viewport" content="width=device-width, initial-scale=1">
75340
+ <meta name="description" content="">
75341
+ <link rel="shortcut icon" href="#" />
75342
+
75343
+ <link href="[%PATH%]/assets/minimalist-blocks/content.css" rel="stylesheet" type="text/css" />
75344
+
75345
+ <link href="[%PATH%]/assets/scripts/glide/css/glide.core.css" rel="stylesheet" type="text/css" />
75346
+ <link href="[%PATH%]/assets/scripts/glide/css/glide.theme.css" rel="stylesheet" type="text/css" />
75347
+ <script src="[%PATH%]/assets/scripts/glide/glide.js" type="text/javascript"></script>
75348
+
75349
+ <style>
75350
+ .container {
75351
+ margin: 150px auto 0;
75352
+ max-width: 800px;
75353
+ width: 100%;
75354
+ padding: 0 20px;
75355
+ box-sizing: border-box;
75356
+ }
75357
+ </style>
75358
+ </head>
75359
+ <body>
75360
+
75361
+ <div class="container">
75362
+ [%CONTENT%]
75363
+ </div>
75364
+
75365
+ </body>
75366
+ </html>`,
75040
75367
 
75041
75368
  /*
75042
75369
  onZoomStart: () => {
@@ -75546,11 +75873,15 @@ class ContentBuilder {
75546
75873
 
75547
75874
  this.win = win;
75548
75875
  this.doc = doc;
75876
+ this.doc.body.classList.add('data-editor');
75549
75877
  const dom = new Dom(this);
75550
75878
  this.dom = dom;
75551
75879
  const util = new Util(this); // General utilities
75552
75880
 
75553
- this.util = util; // Content stuff
75881
+ this.util = util;
75882
+ const responsive = new Responsive(this); // General utilities
75883
+
75884
+ this.responsive = responsive; // Content stuff
75554
75885
 
75555
75886
  if (this.iframe) {
75556
75887
  let contentStuff = doc.querySelector('.content-stuff');
@@ -75712,7 +76043,8 @@ class ContentBuilder {
75712
76043
  k = false;
75713
76044
  let m = false,
75714
76045
  n = false,
75715
- o = false;
76046
+ o = false,
76047
+ p = false;
75716
76048
  let isSpecialElement = false;
75717
76049
  let element = target;
75718
76050
 
@@ -75720,6 +76052,7 @@ class ContentBuilder {
75720
76052
  if (!element.tagName) break;
75721
76053
  if (element.tagName === 'BODY' || element.tagName === 'HTML') break;
75722
76054
  if (this.dom.hasClass(element, 'is-builder')) a = true;
76055
+ if (this.dom.hasClass(element, 'is-subblock')) p = true;
75723
76056
  if (this.dom.hasClass(element, 'is-modal')) b = true;
75724
76057
  if (this.dom.hasClass(element, 'is-side') || this.dom.hasClass(element, 'is-sidebar')) c = true;
75725
76058
  if (this.dom.hasClass(element, 'is-pop')) d = true;
@@ -75786,7 +76119,7 @@ class ContentBuilder {
75786
76119
  }
75787
76120
  }
75788
76121
 
75789
- if (!(a || b || c || d || f || g || h || i || j || o || isSpecialElement) || rowClicked && !i || containerClicked) {
76122
+ if (!(a || p || b || c || d || f || g || h || i || j || o || isSpecialElement) || rowClicked && !i || containerClicked) {
75790
76123
  // Click anywhere but is not inside builder area, modal, popup, tool or rte, then clear row/column (cell) selection
75791
76124
  if (!this.dom.getSelected()) {
75792
76125
  // if(!document.querySelector('.is-modal.active')) { // Additional (to prevent lost focus)
@@ -76508,6 +76841,7 @@ class ContentBuilder {
76508
76841
  }
76509
76842
 
76510
76843
  destroy() {
76844
+ this.doc.body.classList.remove('data-editor');
76511
76845
  document.removeEventListener('click', this.doDocumentClick, false);
76512
76846
  document.removeEventListener('keydown', this.doDocumentKeydown, false);
76513
76847
  document.removeEventListener('mousedown', this.doDocumentMousedown, false);
@@ -76541,7 +76875,11 @@ class ContentBuilder {
76541
76875
 
76542
76876
  const builders = this.doc.querySelectorAll(this.opts.container);
76543
76877
  Array.prototype.forEach.call(builders, builder => {
76544
- builder.innerHTML = htmlutil.readHtml(builder, true);
76878
+ // builder.innerHTML = htmlutil.readHtml(builder, true);
76879
+ let html = htmlutil.readHtml(builder, false);
76880
+ let range = this.doc.createRange();
76881
+ builder.innerHTML = '';
76882
+ builder.appendChild(range.createContextualFragment(html)); // Use createContextualFragment so that embedded javascript code (code block) will be executed
76545
76883
  });
76546
76884
  Array.prototype.forEach.call(builders, builder => {
76547
76885
  builder.removeAttribute('data-sort');
@@ -76868,6 +77206,46 @@ class ContentBuilder {
76868
77206
 
76869
77207
  saveForUndo(checkLater) {
76870
77208
  this.uo.saveForUndo(checkLater);
77209
+ }
77210
+
77211
+ download(options = {}) {
77212
+ let pageTemplate = this.pageTemplate;
77213
+ let output = ''; // [%CONTENT%]
77214
+
77215
+ this.makeAbsolute = true; //To make absolute (for Export/Download)
77216
+
77217
+ let html = this.html();
77218
+ this.makeAbsolute = false;
77219
+ output = pageTemplate.replace('[%CONTENT%]', html); // Custom
77220
+
77221
+ if (options.replace) {
77222
+ options.replace.forEach(rule => {
77223
+ output = output.replaceAll(`${rule[0]}`, rule[1]);
77224
+ });
77225
+ } // [%PATH%]
77226
+
77227
+
77228
+ if (options.path) {
77229
+ output = output.replaceAll('[%PATH%]', options.path);
77230
+ } else {
77231
+ let urlBase;
77232
+ urlBase = location.href.substring(0, location.href.lastIndexOf('/'));
77233
+ output = output.replaceAll('[%PATH%]', urlBase);
77234
+ } // Beautify
77235
+
77236
+
77237
+ output = this.beautify(output);
77238
+ const a = document.createElement('a');
77239
+ a.href = window.URL.createObjectURL(new Blob([output], {
77240
+ type: 'text/plain'
77241
+ }));
77242
+ a.download = 'page.html';
77243
+ a.click();
77244
+ }
77245
+
77246
+ beautify(html) {
77247
+ const htmlutil = new HtmlUtil(this);
77248
+ return htmlutil.beautify(html);
76871
77249
  } // Module related
76872
77250
 
76873
77251