@innovastudio/contentbuilder 1.5.15 → 1.5.16

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.
@@ -11527,7 +11527,7 @@ class HtmlUtil {
11527
11527
  elm.removeAttribute('grideditor');
11528
11528
  elm.removeAttribute('gridoutline');
11529
11529
  });
11530
- elms = tmp.querySelectorAll('.is-row-tool,.is-col-tool,.is-rowadd-tool,.is-canvas-tool,.is-canvasadd-tool');
11530
+ elms = tmp.querySelectorAll('.is-row-tool,.is-col-tool,.is-rowadd-tool,.is-canvas-tool,.is-canvasadd-tool,.h-ruler,.v-ruler');
11531
11531
  elms.forEach(elm => {
11532
11532
  if (elm.previousSibling && elm.previousSibling.nodeType === Node.TEXT_NODE) {
11533
11533
  elm.previousSibling.remove();
@@ -11904,6 +11904,8 @@ class UndoRedo {
11904
11904
  dom.removeElements(tmp.querySelectorAll('.is-canvasadd-tool'));
11905
11905
  dom.removeElements(tmp.querySelectorAll('.ovl'));
11906
11906
  dom.removeElements(tmp.querySelectorAll('.row-add-initial'));
11907
+ dom.removeElements(tmp.querySelectorAll('.h-ruler'));
11908
+ dom.removeElements(tmp.querySelectorAll('.v-ruler'));
11907
11909
 
11908
11910
  // freeform
11909
11911
  elms = tmp.querySelectorAll('.is-block .handle, .is-block .rotate-handle');
@@ -12562,11 +12564,11 @@ const prepareSvgIcons = builder => {
12562
12564
  <path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 16.572v2.42a2.01 2.01 0 0 1 -2.009 2.008h-7.981a2.01 2.01 0 0 1 -2.01 -2.009v-7.981a2.01 2.01 0 0 1 2.009 -2.01h2.954" /><path d="M9.167 4.511a2.04 2.04 0 0 1 2.496 -1.441l7.826 2.097a2.04 2.04 0 0 1 1.441 2.496l-2.097 7.826a2.04 2.04 0 0 1 -2.496 1.441l-7.827 -2.097a2.04 2.04 0 0 1 -1.441 -2.496l2.098 -7.827z" />
12563
12565
  </symbol>
12564
12566
 
12565
- <symbol id="icon-duplicate" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
12567
+ <symbol id="icon-duplicate2" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
12566
12568
  <path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 16.572v2.42a2.01 2.01 0 0 1 -2.009 2.008h-7.981a2.01 2.01 0 0 1 -2.01 -2.009v-7.981a2.01 2.01 0 0 1 2.009 -2.01h2.954" /><path d="M9.167 4.511a2.04 2.04 0 0 1 2.496 -1.441l7.826 2.097a2.04 2.04 0 0 1 1.441 2.496l-2.097 7.826a2.04 2.04 0 0 1 -2.496 1.441l-7.827 -2.097a2.04 2.04 0 0 1 -1.441 -2.496l2.098 -7.827z" />
12567
12569
  </symbol>
12568
- <symbol id="icon-duplicate2" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
12569
- <path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 3m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z" /><path d="M17 17v2a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h2" />
12570
+ <symbol id="icon-duplicate" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
12571
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" /><path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />
12570
12572
  </symbol>
12571
12573
 
12572
12574
  <symbol id="icon-trash" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
@@ -64525,7 +64527,7 @@ class Rte {
64525
64527
  let html_elementrte = '';
64526
64528
  for (j = 0; j < builder.opts.elementButtons.length; j++) {
64527
64529
  btn = builder.opts.elementButtons[j].toLowerCase();
64528
- if (btn === 'left') html_elementrte += `<button tabindex="-1" title="${util.out('Align Left')}" data-align="left"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-left"></use></svg></button>`;else if (btn === 'center') html_elementrte += `<button tabindex="-1" title="${util.out('Align Center')}" data-align="center"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-center"></use></svg></button>`;else if (btn === 'right') html_elementrte += `<button tabindex="-1" title="${util.out('Align Right')}" data-align="right"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-right"></use></svg></button>`;else if (btn === 'full') html_elementrte += `<button tabindex="-1" title="${util.out('Align Full')}" data-align="justify"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-full"></use></svg></button>`;else if (btn === 'gridtool') html_elementrte += `<button tabindex="-1" title="${util.out('Grid Tool')}" class="rte-grideditor"><svg class="is-icon-flex" style="margin-right:-3px;width:17px;height:17px;"><use xlink:href="#ion-grid"></use></svg></button>`;else if (btn === 'html') html_elementrte += `<button tabindex="-1" title="${util.out('HTML')}" class="rte-html"><svg class="is-icon-flex" style="margin-right:-3px;width:14px;height:14px;"><use xlink:href="#ion-ios-arrow-left"></use></svg><svg class="is-icon-flex" style="margin-left:-2px;width:14px;height:14px;"><use xlink:href="#ion-ios-arrow-right"></use></svg></button>`;else if (btn === 'preferences') html_elementrte += `<button tabindex="-1" title="${util.out('Preferences')}" class="rte-preferences"><svg class="is-icon-flex" style="width:13px;height:13px;"><use xlink:href="#ion-wrench"></use></svg></button>`;else if (btn === 'addsnippet') html_elementrte += `<button tabindex="-1" title="${util.out('Add Snippet')}" class="rte-addsnippet"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#ion-ios-plus-empty"></use></svg></button>`;else if (btn === 'group') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Group')}" class="rte-group"><svg class="is-icon-flex" style="width:20px;height:20px;margin-top:-1px;"><use xlink:href="#icon-group"></use></svg></button>`;else if (btn === 'ungroup') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Ungroup')}" class="rte-ungroup"><svg class="is-icon-flex" style="width:20px;height:20px;margin-top:-1px;"><use xlink:href="#icon-ungroup"></use></svg></button>`;else if (btn === 'duplicate') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Duplicate')}" class="rte-duplicate"><svg class="is-icon-flex" style="width:20px;height:20px;margin-top:-1px;"><use xlink:href="#icon-duplicate"></use></svg></button>`;else if (btn === 'front') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Bring to Front')}" class="rte-front"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-stack-forward"></use></svg></button>`;else if (btn === 'backward') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Send to Back')}" class="rte-backward"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-stack-backward"></use></svg></button>`;else if (btn === 'moveup') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Move Up')}" class="rte-moveup"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-arrow-up"></use></svg></button>`;else if (btn === 'movedown') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Move Down')}" class="rte-movedown"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-arrow-down"></use></svg></button>`;else if (btn === 'delete') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Delete')}" class="rte-delete"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-trash"></use></svg></button>`;else if (btn === 'blocksettings' && this.builder.canvas) html_elementrte += `<button tabindex="-1" title="${util.out('Block Settings')}" class="rte-blocksettings"><svg class="is-icon-flex"><use xlink:href="#icon-settings"></use></svg></button>`;else if (btn === 'undo') html_elementrte += `<button tabindex="-1" title="${util.out('Undo')}" class="rte-undo"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#ion-ios-undo"></use></svg></button>`;else if (btn === 'redo') html_elementrte += `<button tabindex="-1" title="${util.out('Redo')}" class="rte-redo"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#ion-ios-redo"></use></svg></button>`;else if (btn === 'aiassistant') html_elementrte += `<button tabindex="-1" title="${util.out('AI Assistant')}" class="rte-ai"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#icon-message"></use></svg></button>`;else if (btn === 'snippets') html_elementrte += `<button tabindex="-1" title="${util.out('Snippets')}" class="rte-snippets"><svg class="is-icon-flex" style="width:19px;height:19px;"><use xlink:href="#icon-snippets"></use></svg></button>`;else if (btn === 'more' && html_elementrtemore !== '') html_elementrte += `<button tabindex="-1" title="${util.out('More')}" class="rte-more"><svg class="is-icon-flex" style="width:13px;height:13px;"><use xlink:href="#ion-more"></use></svg></button>`;else if (btn === 'pageoptions') html_elementrte += `<button tabindex="-1" title="${util.out('Page Options')}" class="rte-pageoptions"><svg class="is-icon-flex"><use xlink:href="#icon-pagesize"></use></svg></button>`;else if (btn === 'print') html_elementrte += `<button tabindex="-1" title="${util.out('Print')}" class="rte-print"><svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-print"></use></svg></button>`;else if (btn === 'zoom') html_elementrte += `<button tabindex="-1" title="${util.out('Zoom')}" class="rte-zoom"><svg class="is-icon-flex" style="margin-top:1px;width:15px;height:15px;"><use xlink:href="#icon-zoom-in"></use></svg></button>`;else if (btn === 'livepreview') html_elementrte += `<button tabindex="-1" title="${util.out('Live Preview')}" class="rte-livepreview"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#icon-device-desktop"></use></svg></button>`;else if (btn === '|') {
64530
+ if (btn === 'left') html_elementrte += `<button tabindex="-1" title="${util.out('Align Left')}" data-align="left"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-left"></use></svg></button>`;else if (btn === 'center') html_elementrte += `<button tabindex="-1" title="${util.out('Align Center')}" data-align="center"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-center"></use></svg></button>`;else if (btn === 'right') html_elementrte += `<button tabindex="-1" title="${util.out('Align Right')}" data-align="right"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-right"></use></svg></button>`;else if (btn === 'full') html_elementrte += `<button tabindex="-1" title="${util.out('Align Full')}" data-align="justify"><svg class="is-icon-flex" style="width:14px;height:14px;"><use xlink:href="#icon-align-full"></use></svg></button>`;else if (btn === 'gridtool') html_elementrte += `<button tabindex="-1" title="${util.out('Grid Tool')}" class="rte-grideditor"><svg class="is-icon-flex" style="margin-right:-3px;width:17px;height:17px;"><use xlink:href="#ion-grid"></use></svg></button>`;else if (btn === 'html') html_elementrte += `<button tabindex="-1" title="${util.out('HTML')}" class="rte-html"><svg class="is-icon-flex" style="margin-right:-3px;width:14px;height:14px;"><use xlink:href="#ion-ios-arrow-left"></use></svg><svg class="is-icon-flex" style="margin-left:-2px;width:14px;height:14px;"><use xlink:href="#ion-ios-arrow-right"></use></svg></button>`;else if (btn === 'preferences') html_elementrte += `<button tabindex="-1" title="${util.out('Preferences')}" class="rte-preferences"><svg class="is-icon-flex" style="width:13px;height:13px;"><use xlink:href="#ion-wrench"></use></svg></button>`;else if (btn === 'addsnippet') html_elementrte += `<button tabindex="-1" title="${util.out('Add Snippet')}" class="rte-addsnippet"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#ion-ios-plus-empty"></use></svg></button>`;else if (btn === 'group') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Group')}" class="rte-group"><svg class="is-icon-flex" style="width:20px;height:20px;margin-top:-1px;"><use xlink:href="#icon-group"></use></svg></button>`;else if (btn === 'ungroup') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Ungroup')}" class="rte-ungroup"><svg class="is-icon-flex" style="width:20px;height:20px;margin-top:-1px;"><use xlink:href="#icon-ungroup"></use></svg></button>`;else if (btn === 'duplicate') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Duplicate')}" class="rte-duplicate"><svg class="is-icon-flex" style="width:16px;height:16px;margin-top:-1px;"><use xlink:href="#icon-duplicate"></use></svg></button>`;else if (btn === 'front') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Bring to Front')}" class="rte-front"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-stack-forward"></use></svg></button>`;else if (btn === 'backward') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Send to Back')}" class="rte-backward"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-stack-backward"></use></svg></button>`;else if (btn === 'moveup') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Move Up')}" class="rte-moveup"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-arrow-up"></use></svg></button>`;else if (btn === 'movedown') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Move Down')}" class="rte-movedown"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-arrow-down"></use></svg></button>`;else if (btn === 'delete') html_elementrte += `<button style="display:none" tabindex="-1" title="${util.out('Delete')}" class="rte-delete"><svg class="is-icon-flex" style="width:18px;height:18px;margin-top:-1px;"><use xlink:href="#icon-trash"></use></svg></button>`;else if (btn === 'blocksettings' && this.builder.canvas) html_elementrte += `<button tabindex="-1" title="${util.out('Block Settings')}" class="rte-blocksettings"><svg class="is-icon-flex"><use xlink:href="#icon-settings"></use></svg></button>`;else if (btn === 'undo') html_elementrte += `<button tabindex="-1" title="${util.out('Undo')}" class="rte-undo"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#ion-ios-undo"></use></svg></button>`;else if (btn === 'redo') html_elementrte += `<button tabindex="-1" title="${util.out('Redo')}" class="rte-redo"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#ion-ios-redo"></use></svg></button>`;else if (btn === 'aiassistant') html_elementrte += `<button tabindex="-1" title="${util.out('AI Assistant')}" class="rte-ai"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#icon-message"></use></svg></button>`;else if (btn === 'snippets') html_elementrte += `<button tabindex="-1" title="${util.out('Snippets')}" class="rte-snippets"><svg class="is-icon-flex" style="width:19px;height:19px;"><use xlink:href="#icon-snippets"></use></svg></button>`;else if (btn === 'more' && html_elementrtemore !== '') html_elementrte += `<button tabindex="-1" title="${util.out('More')}" class="rte-more"><svg class="is-icon-flex" style="width:13px;height:13px;"><use xlink:href="#ion-more"></use></svg></button>`;else if (btn === 'pageoptions') html_elementrte += `<button tabindex="-1" title="${util.out('Page Options')}" class="rte-pageoptions"><svg class="is-icon-flex"><use xlink:href="#icon-pagesize"></use></svg></button>`;else if (btn === 'print') html_elementrte += `<button tabindex="-1" title="${util.out('Print')}" class="rte-print"><svg class="is-icon-flex" style="width:15px;height:15px;"><use xlink:href="#icon-print"></use></svg></button>`;else if (btn === 'zoom') html_elementrte += `<button tabindex="-1" title="${util.out('Zoom')}" class="rte-zoom"><svg class="is-icon-flex" style="margin-top:1px;width:15px;height:15px;"><use xlink:href="#icon-zoom-in"></use></svg></button>`;else if (btn === 'livepreview') html_elementrte += `<button tabindex="-1" title="${util.out('Live Preview')}" class="rte-livepreview"><svg class="is-icon-flex" style="margin-top:2px;width:15px;height:15px;"><use xlink:href="#icon-device-desktop"></use></svg></button>`;else if (btn === '|') {
64529
64531
  html_elementrte += '<div class="rte-separator"></div>';
64530
64532
  } else {
64531
64533
  html_elementrte += `<button tabindex="-1" title="button not found" data-plugin="${btn}"></button>`; //temporary (later will be replaced with plugin button)
@@ -64701,6 +64703,9 @@ class Rte {
64701
64703
  <div style="padding-top:4px">
64702
64704
  <input type="range" min="50" max="${zoomMax}" value="1" class="rte-zoom-slider is-rangeslider">
64703
64705
  </div>
64706
+ <div style="display:flex;justify-content:flex-end">
64707
+ <button title="${util.out('Reset')}" class="reset-zoom" style="background:transparent;padding:0;height:27px;text-decoration:underline">${util.out('Reset')}</button>
64708
+ </div>
64704
64709
  </div>
64705
64710
  </div>
64706
64711
 
@@ -65879,6 +65884,16 @@ class Rte {
65879
65884
  showTools();
65880
65885
  });
65881
65886
 
65887
+ // Reset Zoom
65888
+ const btnResetZoom = builderStuff.querySelector('.reset-zoom');
65889
+ btnResetZoom.addEventListener('click', () => {
65890
+ this.builder.opts.zoom = 1;
65891
+ localStorage.setItem('_zoom', 1); // Save
65892
+
65893
+ // setZoomOnArea
65894
+ this.builder.setZoomOnArea();
65895
+ });
65896
+
65882
65897
  // Zoom Modal
65883
65898
  this.inpZoomSlider.onfocus = () => {
65884
65899
  if (this.builder.onZoomStart) {
@@ -73397,7 +73412,6 @@ class ContentStuff {
73397
73412
  <button title="${util.out('Settings')}" data-title="${util.out('Settings')}" style="width:37px;height:37px;background:none;"><svg class="is-icon-flex"><use xlink:href="#ion-ios-gear"></use></svg></button>
73398
73413
  </div>
73399
73414
 
73400
-
73401
73415
  <div class="is-locked-indicator">
73402
73416
  <svg class="is-icon-flex"><use xlink:href="#icon-lock"></use></svg>
73403
73417
  </div>
@@ -73891,6 +73905,35 @@ class ContentStuff {
73891
73905
  }
73892
73906
  .is-tool.is-element-tool .elm-settings { display: none; }
73893
73907
 
73908
+ /* is-block-tool
73909
+
73910
+ .is-tool.is-block-tool {
73911
+ background: rgba(243, 243, 243, 0.9);
73912
+ border-radius: 3px;
73913
+ overflow: hidden;
73914
+ top: 3px;
73915
+ right: 3px;
73916
+ left: auto;
73917
+ width: 25px;
73918
+ }
73919
+ .is-tool.is-block-tool button {
73920
+ width: 25px;
73921
+ height: 25px;
73922
+ background: transparent;
73923
+ display: flex;
73924
+ align-items: center;
73925
+ justify-content: center;
73926
+ }
73927
+ .is-tool.is-block-tool svg {
73928
+ width: 14px;
73929
+ height: 14px;
73930
+ fill: #000;
73931
+ }
73932
+ .is-block.active:not(.multi):not(.editable) .is-block-tool {
73933
+ display:flex;
73934
+ }
73935
+ */
73936
+
73894
73937
  /* is-column-tool */
73895
73938
 
73896
73939
  .is-tool.is-column-tool {
@@ -81759,7 +81802,25 @@ class Common {
81759
81802
  applyPercentage(block) {
81760
81803
  const zoom = this.zoom;
81761
81804
  const rect = this.getRect(block);
81762
- const container = block.parentNode;
81805
+ const container = block.closest('.box-canvas');
81806
+ const containerRect = this.getRect(container); // if container has top/left
81807
+
81808
+ this.horizontalRulerTop = container.querySelector('.h-ruler-top');
81809
+ this.horizontalRulerBottom = container.querySelector('.h-ruler-bottom');
81810
+ this.horizontalRulerMiddle = container.querySelector('.h-ruler-middle');
81811
+ this.verticalRulerLeft = container.querySelector('.v-ruler-left');
81812
+ this.verticalRulerRight = container.querySelector('.v-ruler-right');
81813
+ this.verticalRulerCenter = container.querySelector('.v-ruler-center');
81814
+
81815
+ // Check Edges
81816
+ let topTouched = false;
81817
+ let bottomTouched = false;
81818
+ let leftTouched = false;
81819
+ let rightTouched = false;
81820
+ if (this.horizontalRulerTop.hasAttribute('data-topTouched')) topTouched = true;
81821
+ if (this.horizontalRulerBottom.hasAttribute('data-bottomTouched')) bottomTouched = true;
81822
+ if (this.verticalRulerLeft.hasAttribute('data-leftTouched')) leftTouched = true;
81823
+ if (this.verticalRulerRight.hasAttribute('data-rightTouched')) rightTouched = true;
81763
81824
  let isChildBlock = false;
81764
81825
  if (block.parentNode.matches(this.selector)) {
81765
81826
  // child block
@@ -81767,7 +81828,7 @@ class Common {
81767
81828
  }
81768
81829
 
81769
81830
  // const containerRect = container.getBoundingClientRect(); // if container has top/left
81770
- const containerRect = this.getRect(container); // if container has top/left
81831
+ // const containerRect = this.getRect(container); // if container has top/left
81771
81832
  let left = (rect.left - containerRect.left) / container.offsetWidth * 100;
81772
81833
  let top = (rect.top - containerRect.top) / container.offsetHeight * 100;
81773
81834
  let isBlockFixed = block.classList.contains('block-steady');
@@ -81806,6 +81867,35 @@ class Common {
81806
81867
  block.style.left = left / zoom + '%';
81807
81868
  if (block.classList.contains('height-auto')) block.style.height = '';
81808
81869
  }
81870
+
81871
+ // Check
81872
+
81873
+ block.style.right = ''; //reset
81874
+ block.style.bottom = ''; //reset
81875
+
81876
+ if (topTouched) block.style.top = 0;
81877
+ // if(topTouched && bottomTouched) block.style.height = '100%';
81878
+ if (leftTouched) block.style.left = 0;
81879
+ // if(leftTouched && rightTouched) block.style.width = '100%';
81880
+
81881
+ if (topTouched && bottomTouched) {
81882
+ block.style.top = 0;
81883
+ block.style.bottom = 0;
81884
+ block.style.height = '';
81885
+ }
81886
+ if (leftTouched && rightTouched) {
81887
+ block.style.left = 0;
81888
+ block.style.right = 0;
81889
+ block.style.width = '';
81890
+ }
81891
+ if (bottomTouched && !topTouched) {
81892
+ block.style.bottom = 0;
81893
+ block.style.height = '';
81894
+ }
81895
+ if (rightTouched && !leftTouched) {
81896
+ block.style.right = 0;
81897
+ block.style.width = '';
81898
+ }
81809
81899
  }
81810
81900
  applyPixels(block) {
81811
81901
  const zoom = this.zoom;
@@ -81960,15 +82050,16 @@ class Common {
81960
82050
  right = Math.max(right, blockLeft + blockWidth);
81961
82051
  }
81962
82052
  });
82053
+ const container = blocks[0].parentNode;
82054
+ const containerRect = this.getRect(container);
81963
82055
  const group = this.doc.createElement('div');
81964
82056
  group.classList.add(className);
81965
82057
  group.classList.add(groupClassName);
81966
82058
  group.classList.add('block-steady');
81967
- group.style.top = top + 'px';
81968
- group.style.left = left + 'px';
82059
+ group.style.top = top - containerRect.top + 'px';
82060
+ group.style.left = left - containerRect.left + 'px';
81969
82061
  group.style.width = right + 1 - left + 'px';
81970
82062
  group.style.height = bottom + 1 - top + 'px';
81971
- const container = blocks[0].parentNode;
81972
82063
  container.appendChild(group);
81973
82064
  blocks.forEach(block => {
81974
82065
  if (!block.parentNode.matches(this.selector)) {
@@ -81977,8 +82068,8 @@ class Common {
81977
82068
  let blockLeft = parseFloat(block.style.left) || 0;
81978
82069
 
81979
82070
  // Adjust position relative to the group div
81980
- block.style.top = blockTop - top + 'px';
81981
- block.style.left = blockLeft - left + 'px';
82071
+ block.style.top = blockTop - top + containerRect.top + 'px';
82072
+ block.style.left = blockLeft - left + containerRect.left + 'px';
81982
82073
  group.appendChild(block);
81983
82074
  this.applyPercentage(block);
81984
82075
  }
@@ -82033,14 +82124,15 @@ class Common {
82033
82124
  const top = rect.top;
82034
82125
  const left = rect.left;
82035
82126
  const container = group.parentNode;
82127
+ const containerRect = this.getRect(container);
82036
82128
  group.querySelectorAll(this.selector).forEach(block => {
82037
82129
  this.applyPixels(block);
82038
82130
  let blockTop = parseFloat(block.style.top) || 0;
82039
82131
  let blockLeft = parseFloat(block.style.left) || 0;
82040
82132
 
82041
82133
  // Adjust position relative to the group div
82042
- block.style.top = blockTop + top + 'px';
82043
- block.style.left = blockLeft + left + 'px';
82134
+ block.style.top = blockTop + top - containerRect.top + 'px';
82135
+ block.style.left = blockLeft + left - containerRect.left + 'px';
82044
82136
  container.appendChild(block);
82045
82137
 
82046
82138
  // Remove all breakpoints
@@ -82252,10 +82344,23 @@ class Ruler {
82252
82344
  this.zoom = scale;
82253
82345
  }
82254
82346
  setup() {
82255
- this.elements = this.doc.querySelectorAll(this.selector);
82347
+ // this.elements = this.doc.querySelectorAll(this.selector);
82348
+ this.refresh();
82256
82349
  }
82257
82350
  refresh() {
82258
82351
  this.elements = this.doc.querySelectorAll(this.selector);
82352
+ const rulerHTML = `
82353
+ <div class="ruler h-ruler h-ruler-top""></div>
82354
+ <div class="ruler h-ruler h-ruler-bottom"></div>
82355
+ <div class="ruler h-ruler h-ruler-middle"></div>
82356
+ <div class="ruler v-ruler v-ruler-left"></div>
82357
+ <div class="ruler v-ruler v-ruler-right"></div>
82358
+ <div class="ruler v-ruler v-ruler-center"></div>
82359
+ `;
82360
+ const containers = this.doc.querySelectorAll('.box-canvas');
82361
+ containers.forEach(container => {
82362
+ if (!container.querySelector('.h-ruler-top')) container.insertAdjacentHTML('beforeend', rulerHTML);
82363
+ });
82259
82364
  }
82260
82365
  destroy() {
82261
82366
  [this.horizontalRulerTop, this.horizontalRulerBottom, this.verticalRulerLeft, this.verticalRulerRight].forEach(elm => {
@@ -82263,6 +82368,18 @@ class Ruler {
82263
82368
  });
82264
82369
  }
82265
82370
  hideRulers() {
82371
+ this.horizontalRulerTop.classList.remove('active');
82372
+ this.horizontalRulerBottom.classList.remove('active');
82373
+ this.horizontalRulerMiddle.classList.remove('active');
82374
+ this.verticalRulerLeft.classList.remove('active');
82375
+ this.verticalRulerRight.classList.remove('active');
82376
+ this.verticalRulerCenter.classList.remove('active');
82377
+ this.rulerTop = null;
82378
+ this.rulerBottom = null; //new
82379
+ this.rulerLeft = null;
82380
+ this.rulerRight = null;
82381
+ }
82382
+ hideRulers_bak() {
82266
82383
  this.horizontalRulerTop.style.top = '-1000px';
82267
82384
  this.horizontalRulerBottom.style.top = '-1000px';
82268
82385
  this.horizontalRulerMiddle.style.top = '-1000px';
@@ -82270,10 +82387,207 @@ class Ruler {
82270
82387
  this.verticalRulerRight.style.left = '-1000px';
82271
82388
  this.verticalRulerCenter.style.left = '-1000px';
82272
82389
  this.rulerTop = null;
82390
+ this.rulerBottom = null; //new
82273
82391
  this.rulerLeft = null;
82274
82392
  this.rulerRight = null;
82275
82393
  }
82276
82394
  updateRulers(block) {
82395
+ const container = block.closest('.box-canvas');
82396
+ this.horizontalRulerTop = container.querySelector('.h-ruler-top');
82397
+ this.horizontalRulerBottom = container.querySelector('.h-ruler-bottom');
82398
+ this.horizontalRulerMiddle = container.querySelector('.h-ruler-middle');
82399
+ this.verticalRulerLeft = container.querySelector('.v-ruler-left');
82400
+ this.verticalRulerRight = container.querySelector('.v-ruler-right');
82401
+ this.verticalRulerCenter = container.querySelector('.v-ruler-center');
82402
+ let transform = block.style.transform;
82403
+ if (transform.includes('rotate') || transform.includes('matrix3d')) return;
82404
+ let parentTransform = block.parentNode.style.transform;
82405
+ if (parentTransform.includes('rotate')) return;
82406
+ this.hideRulers();
82407
+ const top = block.offsetTop;
82408
+ const bottom = top + block.offsetHeight;
82409
+ const left = block.offsetLeft;
82410
+ const right = left + block.offsetWidth;
82411
+ const center = left + block.offsetWidth / 2;
82412
+ const middle = top + block.offsetHeight / 2;
82413
+ this.rulerTop = null;
82414
+ this.rulerBottom = null; //new
82415
+ this.rulerLeft = null;
82416
+ this.rulerRight = null;
82417
+ this.elements = container.querySelectorAll(this.selector);
82418
+ this.elements.forEach(element => {
82419
+ if (!this.doc.body.contains(element)) return; // in case element removed (eg. unGroup, block deleted)
82420
+
82421
+ if (block.contains(element)) return; // In case of group moving
82422
+
82423
+ let transform = element.style.transform;
82424
+ let parentTransform = element.parentNode.style.transform;
82425
+ if (!transform.includes('rotate') && !parentTransform.includes('rotate') && !transform.includes('matrix3d') && !parentTransform.includes('matrix3d') && element !== block && !element.classList.contains('cloned')) {
82426
+ const otherTop = element.offsetTop;
82427
+ const otherBottom = otherTop + element.offsetHeight;
82428
+ const otherLeft = element.offsetLeft;
82429
+ const otherRight = otherLeft + element.offsetWidth;
82430
+ const otherMiddle = otherTop + element.offsetHeight / 2;
82431
+ const otherCenter = otherLeft + element.offsetWidth / 2;
82432
+
82433
+ // block top
82434
+ if (otherTop - 4 <= top && top <= otherTop + 4) {
82435
+ this.horizontalRulerTop.style.top = otherTop + 'px';
82436
+ this.horizontalRulerTop.classList.add('active');
82437
+ let val = otherTop;
82438
+ if (this.rulerTop === null) this.rulerTop = val;
82439
+ }
82440
+ if (otherBottom - 4 <= top && top <= otherBottom + 4) {
82441
+ this.horizontalRulerTop.style.top = otherBottom + 'px';
82442
+ this.horizontalRulerTop.classList.add('active');
82443
+ let val = otherBottom;
82444
+ if (this.rulerTop === null) this.rulerTop = val;
82445
+ }
82446
+
82447
+ // block bottom
82448
+ if (otherTop - 4 <= bottom && bottom <= otherTop + 4) {
82449
+ /*
82450
+ _____
82451
+ ___________________|__x__|__ rulerBottom
82452
+ | other |
82453
+ */
82454
+ this.horizontalRulerBottom.style.top = otherTop + 'px';
82455
+ this.horizontalRulerBottom.classList.add('active');
82456
+ if (this.rulerBottom === null) this.rulerBottom = element.offsetTop; // new
82457
+ }
82458
+
82459
+ if (otherBottom - 4 <= bottom && bottom <= otherBottom + 4) {
82460
+ /*
82461
+ _____
82462
+ | other |__________|__x__|__ rulerBottom
82463
+
82464
+ */
82465
+ this.horizontalRulerBottom.style.top = otherBottom + 'px';
82466
+ this.horizontalRulerBottom.classList.add('active');
82467
+ if (this.rulerBottom === null) this.rulerBottom = element.offsetTop + element.offsetHeight; // new
82468
+ }
82469
+
82470
+ // block middle
82471
+ if (this.rulerTop === null && this.rulerBottom === null) {
82472
+ if (otherMiddle - 4 <= middle && middle <= otherMiddle + 4) {
82473
+ this.horizontalRulerMiddle.style.top = otherTop + (element.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82474
+ this.horizontalRulerMiddle.classList.add('active');
82475
+ let val = otherTop + (element.offsetHeight - block.offsetHeight) / 2;
82476
+ if (this.rulerTop === null) this.rulerTop = val;
82477
+ }
82478
+ }
82479
+
82480
+ // block left
82481
+ if (otherLeft - 4 <= left && left <= otherLeft + 4) {
82482
+ this.verticalRulerLeft.style.left = otherLeft + 'px';
82483
+ this.verticalRulerLeft.classList.add('active');
82484
+ let val = otherLeft;
82485
+ if (this.rulerLeft === null) this.rulerLeft = val;
82486
+ }
82487
+ if (otherRight - 4 <= left && left <= otherRight + 4) {
82488
+ this.verticalRulerLeft.style.left = otherRight + 'px';
82489
+ this.verticalRulerLeft.classList.add('active');
82490
+ let val = otherRight;
82491
+ if (this.rulerLeft === null) this.rulerLeft = val;
82492
+ }
82493
+
82494
+ // block right
82495
+ if (otherLeft - 4 <= right && right <= otherLeft + 4) {
82496
+ this.verticalRulerRight.style.left = otherLeft + 'px';
82497
+ this.verticalRulerRight.classList.add('active');
82498
+ let val = otherLeft;
82499
+ if (this.rulerRight === null) this.rulerRight = val;
82500
+ }
82501
+ if (otherRight - 4 <= right && right <= otherRight + 4) {
82502
+ this.verticalRulerRight.style.left = otherRight + 'px';
82503
+ this.verticalRulerRight.classList.add('active');
82504
+ let val = otherRight;
82505
+ if (this.rulerRight === null) this.rulerRight = val;
82506
+ }
82507
+
82508
+ // block center
82509
+ if (this.rulerLeft === null && this.rulerRight === null) {
82510
+ if (otherCenter - 4 <= center && center <= otherCenter + 4) {
82511
+ this.verticalRulerCenter.style.left = otherLeft + (element.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82512
+ this.verticalRulerCenter.classList.add('active');
82513
+ let val = otherLeft + (element.offsetWidth - block.offsetWidth) / 2;
82514
+ if (this.rulerLeft === null) this.rulerLeft = val;
82515
+ }
82516
+ }
82517
+ }
82518
+ });
82519
+
82520
+ // Edges
82521
+ const conTop = 0;
82522
+ const conBottom = container.offsetHeight;
82523
+ const conLeft = 0;
82524
+ const conRight = container.offsetWidth;
82525
+ const conCenter = container.offsetWidth / 2;
82526
+ const conMiddle = container.offsetHeight / 2;
82527
+
82528
+ // block top
82529
+ this.horizontalRulerTop.removeAttribute('data-topTouched');
82530
+ if (conTop - 4 <= top && top <= conTop + 4) {
82531
+ this.horizontalRulerTop.style.top = conTop + 'px';
82532
+ this.horizontalRulerTop.classList.add('active');
82533
+ let val = conTop;
82534
+ if (this.rulerTop === null) this.rulerTop = val;
82535
+ this.topTouched = true;
82536
+ this.horizontalRulerTop.setAttribute('data-topTouched', 1);
82537
+ }
82538
+
82539
+ // block bottom
82540
+ this.horizontalRulerBottom.removeAttribute('data-bottomTouched');
82541
+ if (conBottom - 4 <= bottom && bottom <= conBottom + 4) {
82542
+ this.horizontalRulerBottom.style.top = conBottom - 2 + 'px'; // -2 is an adjustment to make the line visible
82543
+ this.horizontalRulerBottom.classList.add('active');
82544
+ if (this.rulerBottom === null) this.rulerBottom = conBottom; //conRect.height;// or block.parentNode.offsetHeight; // new
82545
+
82546
+ this.bottomTouched = true;
82547
+ this.horizontalRulerBottom.setAttribute('data-bottomTouched', 1);
82548
+ }
82549
+
82550
+ // block middle
82551
+ if (this.rulerTop === null && this.rulerBottom === null) {
82552
+ if (conMiddle - 4 <= middle && middle <= conMiddle + 4) {
82553
+ this.horizontalRulerMiddle.style.top = conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82554
+ this.horizontalRulerMiddle.classList.add('active');
82555
+ let val = conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2;
82556
+ if (this.rulerTop === null) this.rulerTop = val;
82557
+ }
82558
+ }
82559
+
82560
+ // block left
82561
+ this.verticalRulerLeft.removeAttribute('data-leftTouched');
82562
+ if (conLeft - 4 <= left && left <= conLeft + 4) {
82563
+ this.verticalRulerLeft.style.left = conLeft + 0 + 'px'; // +0 is an adjustment
82564
+ this.verticalRulerLeft.classList.add('active');
82565
+ let val = conLeft;
82566
+ if (this.rulerLeft === null) this.rulerLeft = val;
82567
+ this.verticalRulerLeft.setAttribute('data-leftTouched', 1);
82568
+ }
82569
+
82570
+ // block right
82571
+ this.verticalRulerRight.removeAttribute('data-rightTouched');
82572
+ if (conRight - 4 <= right && right <= conRight + 4) {
82573
+ this.verticalRulerRight.style.left = conRight - 2 + 'px'; // -2 is an adjustment
82574
+ this.verticalRulerRight.classList.add('active');
82575
+ let val = conRight;
82576
+ if (this.rulerRight === null) this.rulerRight = val;
82577
+ this.verticalRulerRight.setAttribute('data-rightTouched', 1);
82578
+ }
82579
+
82580
+ // block center
82581
+ if (this.rulerLeft === null && this.rulerRight === null) {
82582
+ if (conCenter - 4 <= center && center <= conCenter + 4) {
82583
+ this.verticalRulerCenter.style.left = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82584
+ this.verticalRulerCenter.classList.add('active');
82585
+ let val = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2;
82586
+ if (this.rulerLeft === null) this.rulerLeft = val;
82587
+ }
82588
+ }
82589
+ }
82590
+ updateRulers_bak(block) {
82277
82591
  // if(block.querySelector(this.selector)) return; // group (because updateRules also calls parent group if child block is dragged)
82278
82592
 
82279
82593
  let transform = block.style.transform;
@@ -82291,6 +82605,7 @@ class Ruler {
82291
82605
  const center = left + block.offsetWidth / 2;
82292
82606
  const middle = top + block.offsetHeight / 2;
82293
82607
  this.rulerTop = null;
82608
+ this.rulerBottom = null; //new
82294
82609
  this.rulerLeft = null;
82295
82610
  this.rulerRight = null;
82296
82611
  let containerTop = 0;
@@ -82314,18 +82629,6 @@ class Ruler {
82314
82629
  const otherRight = rect.left + element.offsetWidth;
82315
82630
  const otherMiddle = rect.top + element.offsetHeight / 2;
82316
82631
  const otherCenter = rect.left + element.offsetWidth / 2;
82317
- if (otherMiddle - 4 <= middle && middle <= otherMiddle + 4) {
82318
- this.horizontalRulerMiddle.style.top = containerTop + otherTop + (element.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82319
- let val = otherTop + (element.offsetHeight - block.offsetHeight) / 2;
82320
- if (this.rulerTop === null) this.rulerTop = val;
82321
- }
82322
- if (otherCenter - 4 <= center && center <= otherCenter + 4) {
82323
- this.verticalRulerCenter.style.left = otherLeft + (element.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82324
- this.verticalRulerCenter.style.top = containerTop + 'px'; // adj
82325
-
82326
- let val = otherLeft + (element.offsetWidth - block.offsetWidth) / 2;
82327
- if (this.rulerLeft === null) this.rulerLeft = val;
82328
- }
82329
82632
 
82330
82633
  // block top
82331
82634
  if (otherTop - 4 <= top && top <= otherTop + 4) {
@@ -82341,14 +82644,38 @@ class Ruler {
82341
82644
 
82342
82645
  // block bottom
82343
82646
  if (otherTop - 4 <= bottom && bottom <= otherTop + 4) {
82647
+ /*
82648
+ _____
82649
+ ___________________|__x__|__ rulerBottom
82650
+ | other |
82651
+ */
82344
82652
  this.horizontalRulerBottom.style.top = containerTop + otherTop + 'px';
82345
- let val = otherTop - block.offsetHeight;
82346
- if (this.rulerTop === null) this.rulerTop = val;
82653
+
82654
+ // let val = otherTop - block.offsetHeight;
82655
+ // if(this.rulerTop===null) this.rulerTop = val;
82656
+ if (this.rulerBottom === null) this.rulerBottom = element.offsetTop; // new
82347
82657
  }
82658
+
82348
82659
  if (otherBottom - 4 <= bottom && bottom <= otherBottom + 4) {
82660
+ /*
82661
+ _____
82662
+ | other |__________|__x__|__ rulerBottom
82663
+
82664
+ */
82349
82665
  this.horizontalRulerBottom.style.top = containerTop + otherBottom + 'px';
82350
- let val = otherBottom - block.offsetHeight;
82351
- if (this.rulerTop === null) this.rulerTop = val;
82666
+
82667
+ // let val = otherBottom - block.offsetHeight;
82668
+ // if(this.rulerTop===null) this.rulerTop = val;
82669
+ if (this.rulerBottom === null) this.rulerBottom = element.offsetTop + element.offsetHeight; // new
82670
+ }
82671
+
82672
+ // block middle
82673
+ if (this.rulerTop === null && this.rulerBottom === null) {
82674
+ if (otherMiddle - 4 <= middle && middle <= otherMiddle + 4) {
82675
+ this.horizontalRulerMiddle.style.top = containerTop + otherTop + (element.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82676
+ let val = otherTop + (element.offsetHeight - block.offsetHeight) / 2;
82677
+ if (this.rulerTop === null) this.rulerTop = val;
82678
+ }
82352
82679
  }
82353
82680
 
82354
82681
  // block left
@@ -82382,6 +82709,17 @@ class Ruler {
82382
82709
  let val = otherRight;
82383
82710
  if (this.rulerRight === null) this.rulerRight = val;
82384
82711
  }
82712
+
82713
+ // block center
82714
+ if (this.rulerLeft === null && this.rulerRight === null) {
82715
+ if (otherCenter - 4 <= center && center <= otherCenter + 4) {
82716
+ this.verticalRulerCenter.style.left = otherLeft + (element.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82717
+ this.verticalRulerCenter.style.top = containerTop + 'px'; // adj
82718
+
82719
+ let val = otherLeft + (element.offsetWidth - block.offsetWidth) / 2;
82720
+ if (this.rulerLeft === null) this.rulerLeft = val;
82721
+ }
82722
+ }
82385
82723
  }
82386
82724
  });
82387
82725
 
@@ -82393,44 +82731,69 @@ class Ruler {
82393
82731
  const conRight = conRect.left + block.parentNode.offsetWidth;
82394
82732
  const conCenter = conRect.left + block.parentNode.offsetWidth / 2;
82395
82733
  const conMiddle = conRect.top + block.parentNode.offsetHeight / 2;
82396
- if (conMiddle - 4 <= middle && middle <= conMiddle + 4) {
82397
- this.horizontalRulerMiddle.style.top = containerTop + conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82398
- let val = conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2;
82399
- if (this.rulerTop === null) this.rulerTop = val;
82400
- }
82401
- if (conCenter - 4 <= center && center <= conCenter + 4) {
82402
- this.verticalRulerCenter.style.left = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82403
- this.verticalRulerCenter.style.top = containerTop + 'px';
82404
- let val = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2;
82405
- if (this.rulerLeft === null) this.rulerLeft = val;
82406
- }
82407
82734
 
82408
82735
  // block top
82736
+ this.horizontalRulerTop.removeAttribute('data-topTouched');
82409
82737
  if (conTop - 4 <= top && top <= conTop + 4) {
82410
82738
  this.horizontalRulerTop.style.top = containerTop + conTop + 'px';
82411
82739
  let val = conTop;
82412
82740
  if (this.rulerTop === null) this.rulerTop = val;
82741
+ this.topTouched = true;
82742
+ this.horizontalRulerTop.setAttribute('data-topTouched', 1);
82413
82743
  }
82744
+
82414
82745
  // block bottom
82746
+ this.horizontalRulerBottom.removeAttribute('data-bottomTouched');
82415
82747
  if (conBottom - 4 <= bottom && bottom <= conBottom + 4) {
82416
- this.horizontalRulerBottom.style.top = containerTop + conBottom - 3 + 'px'; // -3 is an adjustment to make the line visible
82748
+ this.horizontalRulerBottom.style.top = containerTop + conBottom - 2 + 'px'; // -2 is an adjustment to make the line visible
82417
82749
 
82418
- let val = conBottom - block.offsetHeight;
82419
- if (this.rulerTop === null) this.rulerTop = val;
82750
+ // let val = conBottom - block.offsetHeight;
82751
+ // if(this.rulerTop===null) this.rulerTop = val;
82752
+ if (this.rulerBottom === null) this.rulerBottom = conRect.height; // or block.parentNode.offsetHeight; // new
82753
+
82754
+ this.bottomTouched = true;
82755
+ this.horizontalRulerBottom.setAttribute('data-bottomTouched', 1);
82420
82756
  }
82757
+
82758
+ // block middle
82759
+ if (this.rulerTop === null && this.rulerBottom === null) {
82760
+ if (conMiddle - 4 <= middle && middle <= conMiddle + 4) {
82761
+ this.horizontalRulerMiddle.style.top = containerTop + conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2 + block.offsetHeight / 2 + 'px';
82762
+ let val = conTop + (block.parentNode.offsetHeight - block.offsetHeight) / 2;
82763
+ if (this.rulerTop === null) this.rulerTop = val;
82764
+ }
82765
+ }
82766
+
82421
82767
  // block left
82768
+ this.verticalRulerLeft.removeAttribute('data-leftTouched');
82422
82769
  if (conLeft - 4 <= left && left <= conLeft + 4) {
82423
- this.verticalRulerLeft.style.left = conLeft + 2 + 'px'; // +3 is an adjustment
82424
- this.verticalRulerLeft.style.top = containerTop + 'px';
82770
+ this.verticalRulerLeft.style.left = conLeft + 0 + 'px'; // +0 is an adjustment
82771
+ this.verticalRulerLeft.style.top = containerTop + 'px'; // adj
82772
+
82425
82773
  let val = conLeft;
82426
82774
  if (this.rulerLeft === null) this.rulerLeft = val;
82775
+ this.verticalRulerLeft.setAttribute('data-leftTouched', 1);
82427
82776
  }
82777
+
82428
82778
  // block right
82779
+ this.verticalRulerRight.removeAttribute('data-rightTouched');
82429
82780
  if (conRight - 4 <= right && right <= conRight + 4) {
82430
82781
  this.verticalRulerRight.style.left = conRight - 2 + 'px'; // -2 is an adjustment
82431
- this.verticalRulerRight.style.top = containerTop + 'px';
82782
+ this.verticalRulerRight.style.top = containerTop + 'px'; // adj
82783
+
82432
82784
  let val = conRight;
82433
82785
  if (this.rulerRight === null) this.rulerRight = val;
82786
+ this.verticalRulerRight.setAttribute('data-rightTouched', 1);
82787
+ }
82788
+
82789
+ // block center
82790
+ if (this.rulerLeft === null && this.rulerRight === null) {
82791
+ if (conCenter - 4 <= center && center <= conCenter + 4) {
82792
+ this.verticalRulerCenter.style.left = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2 + block.offsetWidth / 2 + 'px';
82793
+ this.verticalRulerCenter.style.top = containerTop + 'px';
82794
+ let val = conLeft + (block.parentNode.offsetWidth - block.offsetWidth) / 2;
82795
+ if (this.rulerLeft === null) this.rulerLeft = val;
82796
+ }
82434
82797
  }
82435
82798
  }
82436
82799
  }
@@ -82905,38 +83268,129 @@ class Resizable {
82905
83268
  }
82906
83269
 
82907
83270
  // Replace with ruler's alignment
82908
- if (this.ruler.rulerTop !== null) {
82909
- target.style.top = this.ruler.rulerTop + 'px';
82910
- // if container has top/left
82911
- if (target.parentNode.matches(this.selector)) {
82912
- const containerRect = target.parentNode.getBoundingClientRect();
82913
- target.style.top = this.ruler.rulerTop - containerRect.top + 'px';
83271
+
83272
+ if (this.resizeHandle.includes('top')) {
83273
+ if (this.ruler.rulerTop !== null) {
83274
+ //bottom fixed
83275
+ let targetBottom = target.offsetTop + target.offsetHeight;
83276
+ target.style.top = this.ruler.rulerTop + 'px';
83277
+ target.style.height = targetBottom - this.ruler.rulerTop + 'px';
82914
83278
  }
82915
83279
  }
82916
-
82917
- // If resizing by dragging the right corners (top or bottom)
82918
- if (this.resizeHandle === 'top-right' || this.resizeHandle === 'bottom-right' || this.resizeHandle === 'right') {
82919
- // Check if vertical right ruler visible (has value)
83280
+ if (this.resizeHandle.includes('bottom')) {
83281
+ if (this.ruler.rulerBottom !== null) {
83282
+ // top fixed
83283
+ target.style.height = this.ruler.rulerBottom - target.offsetTop + 'px';
83284
+ }
83285
+ }
83286
+ if (this.resizeHandle.includes('left')) {
83287
+ if (this.ruler.rulerLeft !== null) {
83288
+ //right fixed
83289
+ let targetRight = target.offsetLeft + target.offsetWidth;
83290
+ target.style.left = this.ruler.rulerLeft + 'px';
83291
+ target.style.width = targetRight - this.ruler.rulerLeft + 'px';
83292
+ }
83293
+ }
83294
+ if (this.resizeHandle.includes('right')) {
82920
83295
  if (this.ruler.rulerRight !== null) {
82921
- // If so, keep the left position
82922
- // target.style.left = newLeft + 'px';
83296
+ //left fixed
83297
+ target.style.width = this.ruler.rulerRight - target.offsetLeft + 'px';
83298
+ }
83299
+ }
82923
83300
 
82924
- // And update the width to align with vertical right ruler
82925
- const rect = target.getBoundingClientRect();
82926
- target.style.width = this.ruler.rulerRight - rect.left + 'px';
83301
+ // Convert px to %
83302
+ this.common.applyPercentage(target);
83303
+ setTimeout(() => {
83304
+ const breakpoint = this.doc.body.getAttribute('data-breakpoint');
83305
+
83306
+ // const screenWidth = window.innerWidth;
83307
+ // let defaultPoint;
83308
+ // if(screenWidth<=1920) {
83309
+ // defaultPoint = 1366;
83310
+ // } else {
83311
+ // defaultPoint = 1900;
83312
+ // }
83313
+
83314
+ let largeScreenBreakpoint = 1280; //1920
83315
+ largeScreenBreakpoint = window.innerWidth - 360; //351
83316
+ if (largeScreenBreakpoint < 1280) largeScreenBreakpoint = 1280;
83317
+ let isPrint = false;
83318
+ let elmBox = target.closest('[data-pagesize]');
83319
+ if (elmBox) {
83320
+ if (elmBox.getAttribute('data-pagesize').includes('web')) ; else {
83321
+ isPrint = true;
83322
+ }
82927
83323
  }
82928
- } else if (this.resizeHandle === 'top-left' || this.resizeHandle === 'bottom-left' || this.resizeHandle === 'left') {
82929
- if (this.ruler.rulerLeft !== null) {
82930
- const currentRight = this.initialLeft + this.initialWidth;
83324
+ if (isPrint) {
83325
+ target.setAttribute('data--t', target.style.top);
83326
+ target.setAttribute('data--l', target.style.left);
83327
+ target.setAttribute('data--b', target.style.bottom);
83328
+ target.setAttribute('data--r', target.style.right);
83329
+ target.setAttribute('data--w', target.style.width);
83330
+ target.setAttribute('data--h', target.style.height);
83331
+ } else {
83332
+ if (breakpoint && breakpoint < largeScreenBreakpoint) {
83333
+ target.setAttribute('data--t-' + breakpoint, target.style.top);
83334
+ target.setAttribute('data--l-' + breakpoint, target.style.left);
83335
+ target.setAttribute('data--b-' + breakpoint, target.style.bottom);
83336
+ target.setAttribute('data--r-' + breakpoint, target.style.right);
83337
+ if (!target.classList.contains('fluid')) target.setAttribute('data--w-' + breakpoint, target.style.width);
83338
+ target.setAttribute('data--h-' + breakpoint, target.style.height);
83339
+ } else {
83340
+ target.setAttribute('data--t', target.style.top);
83341
+ target.setAttribute('data--l', target.style.left);
83342
+ target.setAttribute('data--b', target.style.bottom);
83343
+ target.setAttribute('data--r', target.style.right);
83344
+ target.setAttribute('data--w', target.style.width);
83345
+ target.setAttribute('data--h', target.style.height);
83346
+ }
83347
+ }
83348
+ target.removeAttribute('data-prev'); // reset
83349
+ target.removeAttribute('data-fluid');
83350
+ }, 30); // delay needed since we use updateHeight() previously that has 20ms process
82931
83351
 
82932
- // if container has top/left
82933
- const containerRect = target.parentNode.getBoundingClientRect();
82934
- this.ruler.rulerLeft = this.ruler.rulerLeft - containerRect.left;
83352
+ if (this.onChange) this.onChange();
83353
+ }
83354
+ updateBlockStyle_bak(target) {
83355
+ if (target.querySelector(this.selector)) ; else {
83356
+ // this.common.updateHeight(target);
83357
+ if (target.classList.contains('height-auto')) target.style.height = '';
83358
+ }
82935
83359
 
82936
- // And update the width to align with vertical left ruler
82937
- target.style.left = this.ruler.rulerLeft + 'px';
82938
- let newWidth = currentRight - this.ruler.rulerLeft;
82939
- target.style.width = newWidth + 'px';
83360
+ // Replace with ruler's alignment
83361
+ const containerRect = this.common.getRect(target.parentNode); // if container has top/left
83362
+
83363
+ if (this.resizeHandle.includes('top')) {
83364
+ if (this.ruler.rulerTop !== null) {
83365
+ //bottom fixed
83366
+ const rect = target.getBoundingClientRect();
83367
+ let targetBottom = rect.top + rect.height;
83368
+ target.style.top = this.ruler.rulerTop - containerRect.top + 'px';
83369
+ target.style.height = targetBottom - this.ruler.rulerTop + 'px';
83370
+ }
83371
+ }
83372
+ if (this.resizeHandle.includes('bottom')) {
83373
+ if (this.ruler.rulerBottom !== null) {
83374
+ // top fixed
83375
+ // const rect = target.getBoundingClientRect();
83376
+ // target.style.height = this.ruler.rulerBottom - rect.top + containerRect.top + 'px';
83377
+ target.style.height = this.ruler.rulerBottom - target.offsetTop + 'px';
83378
+ }
83379
+ }
83380
+ if (this.resizeHandle.includes('left')) {
83381
+ if (this.ruler.rulerLeft !== null) {
83382
+ //right fixed
83383
+ const rect = target.getBoundingClientRect();
83384
+ let targetRight = rect.left + rect.width;
83385
+ target.style.left = this.ruler.rulerLeft - containerRect.left + 'px';
83386
+ target.style.width = targetRight - this.ruler.rulerLeft + 'px';
83387
+ }
83388
+ }
83389
+ if (this.resizeHandle.includes('right')) {
83390
+ if (this.ruler.rulerRight !== null) {
83391
+ //left fixed
83392
+ const rect = target.getBoundingClientRect();
83393
+ target.style.width = this.ruler.rulerRight - rect.left + 'px';
82940
83394
  }
82941
83395
  }
82942
83396
 
@@ -83139,6 +83593,10 @@ class Draggable {
83139
83593
  const y = startY - rect.top + containerRect.top;
83140
83594
  target.setAttribute('data-startx', x);
83141
83595
  target.setAttribute('data-starty', y);
83596
+
83597
+ // reset (from applyPercentage bottomTouched)
83598
+ target.style.height = target.offsetHeight + 'px';
83599
+ target.style.bottom = '';
83142
83600
  this.common.applyPixels(target);
83143
83601
  });
83144
83602
  this.clickedBlock = this.common.getSelectedBlock();
@@ -83206,10 +83664,9 @@ class Draggable {
83206
83664
  }
83207
83665
  updateBlockStyle(target) {
83208
83666
  // Replace with ruler's alignment
83209
- const containerRect = this.common.getRect(target.parentNode); // if container has top/left
83210
- const initialWidth = parseFloat(getComputedStyle(target).width);
83211
- if (this.ruler.rulerTop !== null) target.style.top = this.ruler.rulerTop - containerRect.top + 'px';
83212
- if (this.ruler.rulerLeft !== null) target.style.left = this.ruler.rulerLeft - containerRect.left + 'px';else if (this.ruler.rulerRight !== null) target.style.left = this.ruler.rulerRight - initialWidth - containerRect.left + 'px';
83667
+ if (this.ruler.rulerTop !== null) target.style.top = this.ruler.rulerTop + 'px';
83668
+ if (this.ruler.rulerBottom !== null) target.style.top = this.ruler.rulerBottom - target.offsetHeight + 'px'; //new
83669
+ if (this.ruler.rulerLeft !== null) target.style.left = this.ruler.rulerLeft + 'px';else if (this.ruler.rulerRight !== null) target.style.left = this.ruler.rulerRight - target.offsetWidth + 'px';
83213
83670
  this.doc.querySelectorAll('[data-startx]').forEach(elm => elm.removeAttribute('data-startx'));
83214
83671
  this.doc.querySelectorAll('[data-starty]').forEach(elm => elm.removeAttribute('data-starty'));
83215
83672
  this.common.applyPercentage(target);
@@ -83900,6 +84357,9 @@ class EditableBlocks {
83900
84357
  win: this.win,
83901
84358
  onContentClick: this.onContentClick,
83902
84359
  onEditStart: (event, block) => {
84360
+ const container = block.querySelector('.is-container');
84361
+ if (!container) return; // if block is empty, no edit required
84362
+
83903
84363
  if (block.classList.contains('clone')) {
83904
84364
  const clonedTarget = this.doc.querySelector(this.selector + '.cloned');
83905
84365
  this.onEditStart(event, clonedTarget);
@@ -84070,133 +84530,181 @@ class BlockModal {
84070
84530
  </div>
84071
84531
  </div>
84072
84532
 
84533
+ <div class="label-page-grayscale label checkbox grayscale" style="padding:30px 0 10px;">
84534
+ <label class="label-checkbox" for="chkPageGrayscale"><input id="chkPageGrayscale" class="chk-grayscale" type="checkbox" /> ${util.out('Grayscale')}</label>
84535
+ </div>
84536
+
84537
+ <div style="padding-top:30px;padding-bottom:3px;">${util.out('Auto layout on mobile')}:</div>
84538
+
84539
+ <label class="switch"><input id="inpAutoLayout" type="checkbox" checked=""><span class="slider round"></span></label>
84540
+
84073
84541
  </div>
84074
84542
 
84075
- <div class="modal-content">
84543
+ <div class="modal-content" style="padding:0">
84076
84544
 
84077
- <div style="padding-bottom: 3px;">${util.out('Background Color')}:</div>
84078
- <div style="display:flex;">
84079
- <button title="${util.out('Background Color')}" class="input-block-bgcolor is-btn-color" style="margin-right:15px"></button>
84080
- <button title="${util.out('Gradient')}" class="btn-block-gradient classic" data-value="+"> ${util.out('Gradient')} </button>
84545
+ <div class="is-tabs" data-group="blocksettings" style="background-color:transparent">
84546
+ <a title="${util.out('General')}" id="tabBlockGeneral" href="#" data-content="divBlockGeneral" class="active">${util.out('General')}</a>
84547
+ <a title="${util.out('More')}" id="tabBlockMore" href="#" data-content="divBlockMore">${util.out('More')}</a>
84081
84548
  </div>
84082
84549
 
84083
- <div style="padding-top:20px;padding-bottom: 3px;">${util.out('Background Image')}:</div>
84084
- <div>
84085
- <div class="asset-block-preview" style="display:none"></div>
84086
- <div style="display: flex">
84087
- <button title="${util.out('Image')}" class="btn-block-bgimage">
84088
- <svg class="is-icon-flex"><use xlink:href="#ion-image"></use></svg>
84089
- <span>${util.out('Image')}</span>
84550
+ <div id="divBlockMore" class="is-tab-content" data-group="blocksettings" tabindex="-1" style="padding:25px 25px 28px">
84551
+
84552
+ <div class="div-target" style="display: flex;justify-content: flex-end;padding: 5px 0 0;">
84553
+ <button title="${util.out('Desktop')}" class="input-device on" data-value="" style="width:40px;height:25px;">
84554
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-device-desktop"></use></svg>
84555
+ </button>
84556
+ <button title="${util.out('Laptop/Tablet (Landscape)')}" class="input-device" data-value="md" style="width:40px;height:25px;">
84557
+ <svg class="is-icon-flex" style="width:16px;height:16px;transform:rotate(-90deg)"><use xlink:href="#icon-device-tablet"></use></svg>
84558
+ </button>
84559
+ <button title="${util.out('Tablet (Portrait)')}" class="input-device" data-value="sm" style="width:40px;height:25px;">
84560
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-device-tablet"></use></svg>
84561
+ </button>
84562
+ <button title="${util.out('Mobile')}" class="input-device" data-value="xs" style="width:40px;height:25px;">
84563
+ <svg class="is-icon-flex" style="width:13px;height:13px"><use xlink:href="#icon-device-mobile"></use></svg>
84090
84564
  </button>
84091
- <button title="${util.out('Select')}" class="btn-block-asset">${this.builder.opts.selectIcon}</button>
84092
- <button title="${util.out('Remove')}" class="btn-block-clear"><svg class="is-icon-flex" style="width:11px;height:11px;"><use xlink:href="#icon-clean"></use></svg></button>
84093
- <button title="${util.out('Adjust')}" class="btn-block-adjust" style="width:40px"><svg class="is-icon-flex"><use xlink:href="#ion-wrench"></use></svg></button>
84094
84565
  </div>
84095
- </div>
84096
84566
 
84097
- <div class="div-content-textcolor flex flex-col">
84098
- <div style="padding-top:20px;padding-bottom:3px;">${util.out('Text Color')}:</div>
84099
- <div class="flex flex-row">
84100
- <button title="0" data-textcolor="dark">${util.out('Dark')}</button>
84101
- <button title="10" data-textcolor="light">${util.out('Light')}</button>
84102
-
84103
- <button title="${util.out('Clear')}" data-textcolor=""><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>
84567
+ <div style="padding-top:0;padding-bottom:3px;">${util.out('Visibility')}:</div>
84568
+ <div class="div-visibility" style="display:flex;">
84569
+ <button title="${util.out('Visible')}" class="input-visible on" data-value="sm" style="width:100px;height:34px;">
84570
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-eye"></use></svg>
84571
+ <span>${util.out('Visible')}</span>
84572
+ </button>
84573
+ <button title="${util.out('Hidden')}" class="input-hidden" data-value="xs" style="width:100px;height:34px;">
84574
+ <svg class="is-icon-flex" style="width:16px;height:16px"><use xlink:href="#icon-eye-off"></use></svg>
84575
+ <span>${util.out('Hidden')}</span>
84576
+ </button>
84104
84577
  </div>
84578
+
84105
84579
  </div>
84106
84580
 
84107
- <div class="label checkbox grayscale" style="padding:30px 0 10px;">
84108
- <label class="label-block-grayscale label-checkbox" for="chkBlockGrayscale"><input id="chkBlockGrayscale" class="chk-grayscale" type="checkbox" /> ${util.out('Grayscale')}</label>
84109
- </div>
84581
+ <div id="divBlockGeneral" class="is-tab-content active" data-group="blocksettings" style="display:flex" tabindex="-1" style="padding:25px 25px 28px">
84110
84582
 
84111
- <button title="${util.out('Remove Content/Text')}" class="btn-clear-text" style="margin-top:20px">
84112
- <svg class="is-icon-flex"><use xlink:href="#icon-trash"></use></svg>
84113
- <span>${util.out('Remove Content/Text')}</span>
84114
- </button>
84583
+ <div style="padding-bottom: 3px;">${util.out('Background Color')}:</div>
84584
+ <div style="display:flex;">
84585
+ <button title="${util.out('Background Color')}" class="input-block-bgcolor is-btn-color" style="margin-right:15px"></button>
84586
+ <button title="${util.out('Gradient')}" class="btn-block-gradient classic" data-value="+"> ${util.out('Gradient')} </button>
84587
+ </div>
84115
84588
 
84116
- <button title="${util.out('Clear Breakpoints')}" class="btn-clear-breakpoint" style="margin-top:20px">
84117
- <svg class="is-icon-flex"><use xlink:href="#icon-trash"></use></svg>
84118
- <span>${util.out('Clear Breakpoints')}</span>
84119
- </button>
84589
+ <div style="padding-top:20px;padding-bottom: 3px;">${util.out('Background Image')}:</div>
84590
+ <div>
84591
+ <div class="asset-block-preview" style="display:none"></div>
84592
+ <div style="display: flex">
84593
+ <button title="${util.out('Image')}" class="btn-block-bgimage">
84594
+ <svg class="is-icon-flex"><use xlink:href="#ion-image"></use></svg>
84595
+ <span>${util.out('Image')}</span>
84596
+ </button>
84597
+ <button title="${util.out('Select')}" class="btn-block-asset">${this.builder.opts.selectIcon}</button>
84598
+ <button title="${util.out('Remove')}" class="btn-block-clear"><svg class="is-icon-flex" style="width:11px;height:11px;"><use xlink:href="#icon-clean"></use></svg></button>
84599
+ <button title="${util.out('Adjust')}" class="btn-block-adjust" style="width:40px"><svg class="is-icon-flex"><use xlink:href="#ion-wrench"></use></svg></button>
84600
+ </div>
84601
+ </div>
84120
84602
 
84121
- <div style="padding-top:23px;padding-bottom:3px;">${util.out('Lock')}:</div>
84603
+ <div class="div-content-textcolor flex flex-col">
84604
+ <div style="padding-top:20px;padding-bottom:3px;">${util.out('Text Color')}:</div>
84605
+ <div class="flex flex-row">
84606
+ <button title="0" data-textcolor="dark">${util.out('Dark')}</button>
84607
+ <button title="10" data-textcolor="light">${util.out('Light')}</button>
84608
+
84609
+ <button title="${util.out('Clear')}" data-textcolor=""><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>
84610
+ </div>
84611
+ </div>
84122
84612
 
84123
- <label class="switch"><input id="inpLockBlock" type="checkbox" checked=""><span class="slider round"></span></label>
84613
+ <div class="label-block-grayscale label checkbox grayscale" style="padding:30px 0 10px;">
84614
+ <label class="label-checkbox" for="chkBlockGrayscale"><input id="chkBlockGrayscale" class="chk-grayscale" type="checkbox" /> ${util.out('Grayscale')}</label>
84615
+ </div>
84124
84616
 
84125
- <div id="divBlockPos">
84617
+ <button title="${util.out('Remove Content/Text')}" class="btn-clear-text" style="margin-top:20px">
84618
+ <svg class="is-icon-flex"><use xlink:href="#icon-trash"></use></svg>
84619
+ <span>${util.out('Remove Content/Text')}</span>
84620
+ </button>
84126
84621
 
84127
- <div class="flex" style="gap:10px">
84128
- <div>
84129
- <label for="inpBlockTop" class="flex" style="padding:10px 0 3px;">${util.out('Top')}:</label>
84130
- <div style="display:flex">
84131
- <input id="inpBlockTop" class="inp-block-top" type="text" style="width:74px;height:35px">
84132
- <select id="inpBlockTopUnit">
84133
- <option></option>
84134
- <option>px</option>
84135
- <option>%</option>
84136
- </select>
84622
+ <button title="${util.out('Clear Breakpoints')}" class="btn-clear-breakpoint" style="margin-top:20px">
84623
+ <svg class="is-icon-flex"><use xlink:href="#icon-trash"></use></svg>
84624
+ <span>${util.out('Clear Breakpoints')}</span>
84625
+ </button>
84626
+
84627
+ <div style="padding-top:23px;padding-bottom:3px;">${util.out('Lock')}:</div>
84628
+
84629
+ <label class="switch"><input id="inpLockBlock" type="checkbox" checked=""><span class="slider round"></span></label>
84630
+
84631
+ <div id="divBlockPos">
84632
+
84633
+ <div class="flex" style="gap:10px">
84634
+ <div>
84635
+ <label for="inpBlockTop" class="flex" style="padding:10px 0 3px;">${util.out('Top')}:</label>
84636
+ <div style="display:flex">
84637
+ <input id="inpBlockTop" class="inp-block-top" type="text" style="width:74px;height:35px">
84638
+ <select id="inpBlockTopUnit">
84639
+ <option></option>
84640
+ <option>px</option>
84641
+ <option>%</option>
84642
+ </select>
84643
+ </div>
84137
84644
  </div>
84138
- </div>
84139
- <div>
84140
- <label for="inpBlockBottom" class="flex" style="padding:10px 0 3px;">${util.out('Bottom')}:</label>
84141
- <div style="display:flex">
84142
- <input id="inpBlockBottom" class="inp-block-top" type="text" style="width:74px;height:35px">
84143
- <select id="inpBlockBottomUnit">
84144
- <option></option>
84145
- <option>px</option>
84146
- <option>%</option>
84147
- </select>
84645
+ <div>
84646
+ <label for="inpBlockBottom" class="flex" style="padding:10px 0 3px;">${util.out('Bottom')}:</label>
84647
+ <div style="display:flex">
84648
+ <input id="inpBlockBottom" class="inp-block-top" type="text" style="width:74px;height:35px">
84649
+ <select id="inpBlockBottomUnit">
84650
+ <option></option>
84651
+ <option>px</option>
84652
+ <option>%</option>
84653
+ </select>
84654
+ </div>
84148
84655
  </div>
84149
84656
  </div>
84150
- </div>
84151
84657
 
84152
- <div class="flex" style="gap:10px">
84153
- <div>
84154
- <label for="inpBlockLeft" class="flex" style="padding:10px 0 3px;">${util.out('Left')}:</label>
84155
- <div style="display:flex">
84156
- <input id="inpBlockLeft" class="inp-block-left" type="text" style="width:74px;height:35px">
84157
- <select id="inpBlockLeftUnit">
84158
- <option></option>
84159
- <option>px</option>
84160
- <option>%</option>
84161
- </select>
84658
+ <div class="flex" style="gap:10px">
84659
+ <div>
84660
+ <label for="inpBlockLeft" class="flex" style="padding:10px 0 3px;">${util.out('Left')}:</label>
84661
+ <div style="display:flex">
84662
+ <input id="inpBlockLeft" class="inp-block-left" type="text" style="width:74px;height:35px">
84663
+ <select id="inpBlockLeftUnit">
84664
+ <option></option>
84665
+ <option>px</option>
84666
+ <option>%</option>
84667
+ </select>
84668
+ </div>
84162
84669
  </div>
84163
- </div>
84164
- <div>
84165
- <label for="inpBlockRight" class="flex" style="padding:10px 0 3px;">${util.out('Right')}:</label>
84166
- <div style="display:flex">
84167
- <input id="inpBlockRight" class="inp-block-left" type="text" style="width:74px;height:35px">
84168
- <select id="inpBlockRightUnit">
84169
- <option></option>
84170
- <option>px</option>
84171
- <option>%</option>
84172
- </select>
84670
+ <div>
84671
+ <label for="inpBlockRight" class="flex" style="padding:10px 0 3px;">${util.out('Right')}:</label>
84672
+ <div style="display:flex">
84673
+ <input id="inpBlockRight" class="inp-block-left" type="text" style="width:74px;height:35px">
84674
+ <select id="inpBlockRightUnit">
84675
+ <option></option>
84676
+ <option>px</option>
84677
+ <option>%</option>
84678
+ </select>
84679
+ </div>
84173
84680
  </div>
84174
84681
  </div>
84175
- </div>
84176
84682
 
84177
- <div class="flex" style="gap:10px">
84178
- <div>
84179
- <label for="inpBlockWidth" class="flex" style="padding:10px 0 3px;">${util.out('Width')}:</label>
84180
- <div style="display:flex">
84181
- <input id="inpBlockWidth" class="inp-block-left" type="text" style="width:74px;height:35px">
84182
- <select id="inpBlockWidthUnit">
84183
- <option></option>
84184
- <option>px</option>
84185
- <option>%</option>
84186
- </select>
84683
+ <div class="flex" style="gap:10px">
84684
+ <div>
84685
+ <label for="inpBlockWidth" class="flex" style="padding:10px 0 3px;">${util.out('Width')}:</label>
84686
+ <div style="display:flex">
84687
+ <input id="inpBlockWidth" class="inp-block-left" type="text" style="width:74px;height:35px">
84688
+ <select id="inpBlockWidthUnit">
84689
+ <option></option>
84690
+ <option>px</option>
84691
+ <option>%</option>
84692
+ </select>
84693
+ </div>
84187
84694
  </div>
84188
- </div>
84189
- <div>
84190
- <label for="inpBlockHeight" class="flex" style="padding:10px 0 3px;">${util.out('Height')}:</label>
84191
- <div style="display:flex">
84192
- <input id="inpBlockHeight" class="inp-block-left" type="text" style="width:74px;height:35px">
84193
- <select id="inpBlockHeightUnit">
84194
- <option></option>
84195
- <option>px</option>
84196
- <option>%</option>
84197
- </select>
84695
+ <div>
84696
+ <label for="inpBlockHeight" class="flex" style="padding:10px 0 3px;">${util.out('Height')}:</label>
84697
+ <div style="display:flex">
84698
+ <input id="inpBlockHeight" class="inp-block-left" type="text" style="width:74px;height:35px">
84699
+ <select id="inpBlockHeightUnit">
84700
+ <option></option>
84701
+ <option>px</option>
84702
+ <option>%</option>
84703
+ </select>
84704
+ </div>
84198
84705
  </div>
84199
84706
  </div>
84707
+
84200
84708
  </div>
84201
84709
 
84202
84710
  </div>
@@ -84298,19 +84806,19 @@ class BlockModal {
84298
84806
  const btnPageBgImage = modal.querySelector('.btn-page-bgimage');
84299
84807
  if (btnPageBgImage) dom.addEventListener(btnPageBgImage, 'click', () => {
84300
84808
  // Background image
84301
- const page = this.getPage();
84809
+ let pageOverlay = this.pageOverlay();
84302
84810
  let src = '';
84303
- if (page) if (page.style.backgroundImage) {
84304
- if (page.style.backgroundImage.indexOf('url(') !== -1) {
84305
- src = page.style.backgroundImage.slice(4, -1).replace(/["']/g, '');
84811
+ if (pageOverlay) if (pageOverlay.style.backgroundImage) {
84812
+ if (pageOverlay.style.backgroundImage.indexOf('url(') !== -1) {
84813
+ src = pageOverlay.style.backgroundImage.slice(4, -1).replace(/["']/g, '');
84306
84814
  }
84307
84815
  }
84308
84816
  this.openImagePicker(src, url => {
84309
- const page = this.getPage();
84817
+ let pageOverlay = this.pageOverlay();
84310
84818
  this.builder.uo.saveForUndo();
84311
- page.style.backgroundImage = `url("${url}")`;
84312
- page.style.backgroundSize = 'cover';
84313
- page.style.backgroundRepeat = 'no-repeat';
84819
+ pageOverlay.style.backgroundImage = `url("${url}")`;
84820
+ pageOverlay.style.backgroundSize = 'cover';
84821
+ pageOverlay.style.backgroundRepeat = 'no-repeat';
84314
84822
  const div = this.pageImagePreview;
84315
84823
  const btnPageAdjust = modal.querySelector('.btn-page-adjust');
84316
84824
  const btnPageClear = modal.querySelector('.btn-page-clear');
@@ -84341,9 +84849,43 @@ class BlockModal {
84341
84849
  });
84342
84850
  const btnPageAdjust = modal.querySelector('.btn-page-adjust');
84343
84851
  btnPageAdjust.addEventListener('click', () => {
84344
- let page = this.getPage();
84345
- this.builder.colTool.openImageAdjust(page, btnPageAdjust);
84852
+ let pageOverlay = this.pageOverlay();
84853
+ this.builder.colTool.openImageAdjust(pageOverlay, btnPageAdjust);
84346
84854
  });
84855
+ const chkPageGrayscale = modal.querySelector('#chkPageGrayscale');
84856
+ chkPageGrayscale.addEventListener('click', () => {
84857
+ this.builder.uo.saveForUndo();
84858
+ let pageOverlay = this.pageOverlay();
84859
+ const checked = chkPageGrayscale.checked;
84860
+ if (checked) {
84861
+ pageOverlay.style.filter = 'grayscale(1)';
84862
+ } else {
84863
+ if (pageOverlay.style.filter) pageOverlay.style.filter = pageOverlay.style.filter.replace('grayscale(1)', '');
84864
+ }
84865
+ this.builder.onChange();
84866
+ });
84867
+
84868
+ // Page Auto Layout
84869
+ const chkAutoLayout = modal.querySelector('#inpAutoLayout');
84870
+ chkAutoLayout.addEventListener(this.builder.isTouchSupport ? 'touchstart' : 'click', () => {
84871
+ const page = this.getPage();
84872
+ if (chkAutoLayout.checked) {
84873
+ page.classList.add('autolayout');
84874
+ } else {
84875
+ page.classList.remove('autolayout');
84876
+ }
84877
+ });
84878
+ if (this.builder.isTouchSupport) {
84879
+ let chkAutoLayoutLabel = chkAutoLayout.parentNode;
84880
+ chkAutoLayoutLabel.addEventListener('touchstart', () => {
84881
+ const page = this.getPage();
84882
+ if (chkAutoLayout.checked) {
84883
+ page.classList.add('autolayout');
84884
+ } else {
84885
+ page.classList.remove('autolayout');
84886
+ }
84887
+ });
84888
+ }
84347
84889
 
84348
84890
  // Block Background Image
84349
84891
 
@@ -84397,7 +84939,7 @@ class BlockModal {
84397
84939
  let blockOverlay = this.blockOverlay();
84398
84940
  this.builder.colTool.openImageAdjust(blockOverlay, btnAdjust);
84399
84941
  });
84400
- const chkGrayscale = modal.querySelector('.chk-grayscale');
84942
+ const chkGrayscale = modal.querySelector('#chkBlockGrayscale');
84401
84943
  chkGrayscale.addEventListener('click', () => {
84402
84944
  this.builder.uo.saveForUndo();
84403
84945
  let blockOverlay = this.blockOverlay();
@@ -84624,6 +85166,62 @@ class BlockModal {
84624
85166
  }
84625
85167
  });
84626
85168
  }
85169
+
85170
+ // Responsive Visibility
85171
+
85172
+ let btns = modal.querySelectorAll('.input-device');
85173
+ btns.forEach(btn => {
85174
+ btn.addEventListener('click', () => {
85175
+ const block = this.blockSelected();
85176
+ let elms = modal.querySelectorAll('.input-device');
85177
+ elms.forEach(elm => {
85178
+ elm.classList.remove('on');
85179
+ });
85180
+ btn.classList.add('on');
85181
+ this.realtimeVisibility(block);
85182
+ });
85183
+ });
85184
+ let btnVisible = modal.querySelector('.input-visible');
85185
+ let btnHidden = modal.querySelector('.input-hidden');
85186
+ btnVisible.addEventListener('click', () => {
85187
+ const block = this.blockSelected();
85188
+ this.builder.uo.saveForUndo();
85189
+ let divTarget = modal.querySelector('.div-target');
85190
+ let target = this.builder.responsive.readTarget(divTarget);
85191
+ if (target === 'xs') {
85192
+ block.classList.remove('xs-hidden');
85193
+ } else if (target === 'sm') {
85194
+ block.classList.remove('sm-hidden');
85195
+ } else if (target === 'md') {
85196
+ block.classList.remove('md-hidden');
85197
+ } else if (target === '') {
85198
+ block.classList.remove('desktop-hidden');
85199
+ }
85200
+ btnVisible.classList.add('on');
85201
+ btnHidden.classList.remove('on');
85202
+ this.builder.opts.onChange();
85203
+ });
85204
+ btnHidden.addEventListener('click', () => {
85205
+ const block = this.blockSelected();
85206
+ this.builder.uo.saveForUndo();
85207
+ let divTarget = modal.querySelector('.div-target');
85208
+ let target = this.builder.responsive.readTarget(divTarget);
85209
+ if (target === 'xs') {
85210
+ block.classList.add('xs-hidden');
85211
+ } else if (target === 'sm') {
85212
+ block.classList.add('sm-hidden');
85213
+ } else if (target === 'md') {
85214
+ block.classList.add('md-hidden');
85215
+ } else if (target === '') {
85216
+ block.classList.add('desktop-hidden');
85217
+ }
85218
+ btnVisible.classList.remove('on');
85219
+ btnHidden.classList.add('on');
85220
+ this.builder.opts.onChange();
85221
+ });
85222
+ new Tabs({
85223
+ element: modal
85224
+ });
84627
85225
  } // constructor
84628
85226
 
84629
85227
  getPage() {
@@ -84655,6 +85253,16 @@ class BlockModal {
84655
85253
  // this.builder.eb.common.applyPercentage(target);
84656
85254
  }
84657
85255
 
85256
+ pageOverlay() {
85257
+ const page = this.getPage();
85258
+ if (!page) return false;
85259
+ let pageOverlay = page.querySelector('.is-page-overlay');
85260
+ if (!pageOverlay) {
85261
+ page.insertAdjacentHTML('afterbegin', '<div class="is-page-overlay"></div>');
85262
+ pageOverlay = page.querySelector('.is-page-overlay');
85263
+ }
85264
+ return pageOverlay;
85265
+ }
84658
85266
  blockOverlay() {
84659
85267
  const block = this.builder.doc.querySelector('.is-block.active:not(.multi)');
84660
85268
  if (!block) return false;
@@ -84671,6 +85279,7 @@ class BlockModal {
84671
85279
  }
84672
85280
  realtime() {
84673
85281
  const modal = this.modal;
85282
+ if (!modal.classList.contains('active')) return;
84674
85283
  const page = this.getPage();
84675
85284
  const block = this.blockSelected();
84676
85285
  if (block) {
@@ -84713,7 +85322,7 @@ class BlockModal {
84713
85322
  }
84714
85323
 
84715
85324
  // Grayscale
84716
- const chkGrayscale = modal.querySelector('.chk-grayscale');
85325
+ const chkGrayscale = modal.querySelector('#chkBlockGrayscale');
84717
85326
  chkGrayscale.checked = false;
84718
85327
  if (blockOverlay) {
84719
85328
  if (blockOverlay.style.filter) {
@@ -84864,23 +85473,38 @@ class BlockModal {
84864
85473
  inpHeight.value = '';
84865
85474
  inpHeightUnit.value = '%';
84866
85475
  }
85476
+ this.realtimeVisibility(block);
84867
85477
  } else if (page) {
85478
+ let pageOverlay = this.pageOverlay();
85479
+
84868
85480
  // Background image
84869
85481
  let src = '';
84870
- if (page) if (page.style.backgroundImage) {
84871
- if (page.style.backgroundImage.indexOf('url(') !== -1) {
84872
- src = page.style.backgroundImage.slice(4, -1).replace(/["']/g, '');
85482
+ if (pageOverlay) if (pageOverlay.style.backgroundImage) {
85483
+ if (pageOverlay.style.backgroundImage.indexOf('url(') !== -1) {
85484
+ src = pageOverlay.style.backgroundImage.slice(4, -1).replace(/["']/g, '');
84873
85485
  }
84874
85486
  }
84875
85487
 
84876
85488
  // Update preview
84877
85489
  this.updatePanelPageImage(src);
84878
85490
 
84879
- // Show/hide
85491
+ // Show/hide grayscale
85492
+ const divPageGrayscale = modal.querySelector('.label-page-grayscale');
84880
85493
  if (src === '') {
84881
85494
  this.pageImagePreview.style.display = 'none';
85495
+ divPageGrayscale.style.display = 'none';
84882
85496
  } else {
84883
85497
  this.pageImagePreview.style.display = '';
85498
+ divPageGrayscale.style.display = '';
85499
+ }
85500
+
85501
+ // Grayscale
85502
+ const chkPageGrayscale = modal.querySelector('#chkPageGrayscale');
85503
+ chkPageGrayscale.checked = false;
85504
+ if (pageOverlay.style.filter) {
85505
+ if (pageOverlay.style.filter.indexOf('grayscale') !== -1) {
85506
+ chkPageGrayscale.checked = true;
85507
+ }
84884
85508
  }
84885
85509
 
84886
85510
  // Background color
@@ -84903,6 +85527,58 @@ class BlockModal {
84903
85527
  } else {
84904
85528
  btnPageGradient.style.backgroundImage = '';
84905
85529
  }
85530
+
85531
+ // Page Auto Layout
85532
+ const chkAutoLayout = modal.querySelector('#inpAutoLayout');
85533
+ if (page.classList.contains('autolayout')) {
85534
+ chkAutoLayout.checked = true;
85535
+ } else {
85536
+ chkAutoLayout.checked = false;
85537
+ }
85538
+ }
85539
+ }
85540
+ realtimeVisibility(row, initialOpen) {
85541
+ if (!this.modal) return;
85542
+ if (initialOpen) {
85543
+ const builderStuff = this.builder.builderStuff;
85544
+ const modal = builderStuff.querySelector('.is-modal.content-preview.active');
85545
+ if (modal) {
85546
+ let elms = this.modal.querySelectorAll('.input-device');
85547
+ elms.forEach(elm => {
85548
+ elm.classList.remove('on');
85549
+ });
85550
+ if (modal.classList.contains('is-screen-1920')) {
85551
+ this.modal.querySelector('.input-device[data-value=""]').classList.add('on');
85552
+ } else if (modal.classList.contains('is-screen-1440')) {
85553
+ this.modal.querySelector('.input-device[data-value=""]').classList.add('on');
85554
+ } else if (modal.classList.contains('is-screen-1024')) {
85555
+ this.modal.querySelector('.input-device[data-value="md"]').classList.add('on');
85556
+ } else if (modal.classList.contains('is-screen-768')) {
85557
+ this.modal.querySelector('.input-device[data-value="sm"]').classList.add('on');
85558
+ } else if (modal.classList.contains('is-screen-375')) {
85559
+ this.modal.querySelector('.input-device[data-value="xs"]').classList.add('on');
85560
+ }
85561
+ }
85562
+ }
85563
+ let divTarget = this.modal.querySelector('.div-target');
85564
+ let divVisibility = this.modal.querySelector('.div-visibility');
85565
+ let target = this.builder.responsive.readTarget(divTarget);
85566
+ let valVisibility = this.builder.responsive.getVisibility(row, target);
85567
+ this.builder.responsive.showVisibility(divVisibility, valVisibility);
85568
+
85569
+ // const divColsPerLine = this.modal.querySelector('.div-colsperline');
85570
+ let btns = this.modal.querySelectorAll('.input-colsperline');
85571
+ btns.forEach(btn => {
85572
+ btn.classList.remove('on');
85573
+ });
85574
+ if (target === 'xs') {
85575
+ if (!initialOpen) this.builder.livePreview.resizePreview(375);
85576
+ } else if (target === 'sm') {
85577
+ if (!initialOpen) this.builder.livePreview.resizePreview(768);
85578
+ } else if (target === 'md') {
85579
+ if (!initialOpen) this.builder.livePreview.resizePreview(1024);
85580
+ } else {
85581
+ if (!initialOpen) this.builder.livePreview.resizePreview(1920);
84906
85582
  }
84907
85583
  }
84908
85584
  openImagePicker(currentUrl, callback, btn) {
@@ -84926,17 +85602,17 @@ class BlockModal {
84926
85602
  }
84927
85603
  updatePageImage(src) {
84928
85604
  this.builder.uo.saveForUndo();
84929
- let page = this.getPage();
84930
- page.style.backgroundImage = 'url(\'' + src + '\')';
85605
+ let pageOverlay = this.pageOverlay();
85606
+ pageOverlay.style.backgroundImage = 'url(\'' + src + '\')';
84931
85607
 
84932
85608
  // Reset position & filter (grayscale)
84933
- page.style.filter = '';
84934
- page.style.backgroundSize = '';
84935
- page.style.backgroundPosition = '50% 60%';
84936
- page.removeAttribute('data-bg-xs');
84937
- page.removeAttribute('data-bg-sm');
84938
- page.removeAttribute('data-bg-md');
84939
- page.removeAttribute('data-bg-lg');
85609
+ pageOverlay.style.filter = '';
85610
+ pageOverlay.style.backgroundSize = '';
85611
+ pageOverlay.style.backgroundPosition = '50% 60%';
85612
+ pageOverlay.removeAttribute('data-bg-xs');
85613
+ pageOverlay.removeAttribute('data-bg-sm');
85614
+ pageOverlay.removeAttribute('data-bg-md');
85615
+ pageOverlay.removeAttribute('data-bg-lg');
84940
85616
  this.updatePanelPageImage(src);
84941
85617
  this.builder.onChange();
84942
85618
  }
@@ -84960,6 +85636,16 @@ class BlockModal {
84960
85636
  }
84961
85637
  const btnPageGradient = modal.querySelector('.btn-page-gradient');
84962
85638
  btnPageGradient.style.backgroundImage = '';
85639
+
85640
+ // Show/hide grayscale
85641
+ const divPageGrayscale = modal.querySelector('.label-page-grayscale');
85642
+ if (src === '') {
85643
+ this.pageImagePreview.style.display = 'none';
85644
+ divPageGrayscale.style.display = 'none';
85645
+ } else {
85646
+ this.pageImagePreview.style.display = '';
85647
+ divPageGrayscale.style.display = '';
85648
+ }
84963
85649
  }
84964
85650
  updateImage(src) {
84965
85651
  this.builder.uo.saveForUndo();
@@ -84975,6 +85661,7 @@ class BlockModal {
84975
85661
  blockOverlay.removeAttribute('data-bg-md');
84976
85662
  blockOverlay.removeAttribute('data-bg-lg');
84977
85663
  this.updatePanelImage(src);
85664
+ this.realtime();
84978
85665
  this.builder.onChange();
84979
85666
  }
84980
85667
  updatePanelImage(src) {
@@ -84997,6 +85684,16 @@ class BlockModal {
84997
85684
  }
84998
85685
  const btnGradient = modal.querySelector('.btn-block-gradient');
84999
85686
  btnGradient.style.backgroundImage = '';
85687
+
85688
+ // Show/hide grayscale
85689
+ const divGrayscale = modal.querySelector('.label-block-grayscale');
85690
+ if (src === '') {
85691
+ this.imagePreview.style.display = 'none';
85692
+ divGrayscale.style.display = 'none';
85693
+ } else {
85694
+ this.imagePreview.style.display = '';
85695
+ divGrayscale.style.display = '';
85696
+ }
85000
85697
  }
85001
85698
  show() {
85002
85699
  const modal = this.modal;
@@ -85027,6 +85724,7 @@ class BlockModal {
85027
85724
  }
85028
85725
  showHideControls() {
85029
85726
  const modal = this.modal;
85727
+ if (!modal.classList.contains('active')) return;
85030
85728
  const content1 = modal.querySelector('.modal-none');
85031
85729
  const content2 = modal.querySelector('.modal-content');
85032
85730
  const content3 = modal.querySelector('.modal-page-content');
@@ -85067,6 +85765,60 @@ class BlockModal {
85067
85765
  this.builder.doc.removeEventListener('click', this.handleBlockClick);
85068
85766
  }
85069
85767
  }
85768
+ position() {
85769
+ const dom = this.dom;
85770
+ let elementTool = this.elementTool;
85771
+ let elementMore = this.elementMore;
85772
+ dom.addClass(elementMore, 'transition1');
85773
+ let elmMore = elementTool.querySelector('.elm-more');
85774
+ const viewportHeight = window.innerHeight;
85775
+
85776
+ /*
85777
+ let top, left;
85778
+ if(!this.builder.iframe) {
85779
+ top = elmMore.getBoundingClientRect().top;
85780
+ left = elmMore.getBoundingClientRect().left;
85781
+ } else {
85782
+ let adjY = this.builder.iframe.getBoundingClientRect().top;
85783
+ let adjX = this.builder.iframe.getBoundingClientRect().left;
85784
+ top = elmMore.getBoundingClientRect().top;
85785
+ left = elmMore.getBoundingClientRect().left;
85786
+ top = top + adjY;
85787
+ left = left + adjX;
85788
+ }
85789
+ */
85790
+ const newPos = this.builder.util.getElementPosition(elmMore);
85791
+ let top = newPos.top;
85792
+ let left = newPos.left;
85793
+
85794
+ // elementMore.style.display = 'flex';
85795
+ const btnMore = elementTool.querySelector('.elm-more');
85796
+ this.util.showPop(elementMore, false, btnMore);
85797
+ const w = elementMore.offsetWidth; //to get value, element must not hidden (display:none). So set display:flex before this.
85798
+ const h = elementMore.offsetHeight;
85799
+ if (viewportHeight - top > h) {
85800
+ elementMore.style.top = top + window.pageYOffset + 27 + 'px';
85801
+ elementMore.style.left = left - w / 2 + 10 + 'px';
85802
+ dom.removeClass(elementMore, 'arrow-bottom');
85803
+ dom.removeClass(elementMore, 'arrow-right');
85804
+ dom.removeClass(elementMore, 'arrow-left');
85805
+ dom.removeClass(elementMore, 'center');
85806
+ dom.addClass(elementMore, 'arrow-top');
85807
+ dom.addClass(elementMore, 'center');
85808
+ } else {
85809
+ elementMore.style.top = top + window.pageYOffset - h - 8 + 'px';
85810
+ elementMore.style.left = left - w / 2 + 10 + 'px';
85811
+ dom.removeClass(elementMore, 'arrow-top');
85812
+ dom.removeClass(elementMore, 'arrow-right');
85813
+ dom.removeClass(elementMore, 'arrow-left');
85814
+ dom.removeClass(elementMore, 'center');
85815
+ dom.addClass(elementMore, 'arrow-bottom');
85816
+ dom.addClass(elementMore, 'center');
85817
+ }
85818
+ setTimeout(() => {
85819
+ dom.removeClass(elementMore, 'transition1');
85820
+ }, 300);
85821
+ }
85070
85822
  }
85071
85823
 
85072
85824
  class PageSize {
@@ -85199,12 +85951,19 @@ class PageSize {
85199
85951
  // let h = arr[1].trim();
85200
85952
  if (arr.length === 3) {
85201
85953
  // web
85202
- const docWidth = docContainer.offsetWidth;
85203
- const viewportWidth = this.builder.win.innerWidth;
85204
- if (docWidth < viewportWidth - 50) {
85205
- // web (container)
85206
- docContainer.classList.remove('page-web');
85207
- docContainer.classList.add('page-web-container');
85954
+ let box = docContainer.querySelector('.is-box');
85955
+ if (box) {
85956
+ const boxWidth = box.offsetWidth;
85957
+ const viewportWidth = this.builder.win.innerWidth;
85958
+ if (boxWidth < viewportWidth - 50) {
85959
+ // web (container)
85960
+ docContainer.classList.remove('page-web');
85961
+ docContainer.classList.add('page-web-container');
85962
+ } else {
85963
+ // web (full)
85964
+ docContainer.classList.remove('page-web-container');
85965
+ docContainer.classList.add('page-web');
85966
+ }
85208
85967
  } else {
85209
85968
  // web (full)
85210
85969
  docContainer.classList.remove('page-web-container');
@@ -85293,18 +86052,53 @@ class PageSize {
85293
86052
  position: relative;
85294
86053
  flex:none;
85295
86054
  background: #fff;
85296
- overflow: hidden;
86055
+ /* overflow: hidden;*/
85297
86056
  box-shadow: none;
85298
86057
  }
85299
86058
  ${css}
85300
86059
  </style>
86060
+
86061
+ ${html.includes('data-module="codeview"') ? `
86062
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/themes/prism.min.css" rel="stylesheet">
86063
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/themes/prism-coy.min.css" rel="stylesheet">
86064
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.25.0/prism.min.js"></script>
86065
+ <style>
86066
+ :not(pre)>code[class*=language-], pre[class*=language-] {
86067
+ background-color: #f4f4f4 !important;
86068
+ padding: 12px 16px !important;
86069
+ }
86070
+ pre[class*=language-]:after, pre[class*=language-]:before {
86071
+ box-shadow: none;
86072
+ }
86073
+ :not(pre)>code[class*=language-], pre[class*=language-] {
86074
+ margin-bottom: 1.2rem;
86075
+ }
86076
+ div[data-html] {
86077
+ min-height: 40px;
86078
+ }
86079
+ code[class*=language-], pre[class*=language-] {
86080
+ text-shadow: none;
86081
+ }
86082
+ </style>
86083
+ ` : ''}
85301
86084
  </head>
85302
86085
  <body class="print">
85303
86086
 
85304
86087
  <div class="is-page">${html}</div>
85305
86088
 
85306
86089
  <script>
85307
- window.print();
86090
+ var docReady = function(fn) {
86091
+ var stateCheck = setInterval(function() {
86092
+ if (document.readyState !== "complete") return;
86093
+ clearInterval(stateCheck);
86094
+ try {
86095
+ fn()
86096
+ } catch (e) {}
86097
+ }, 1);
86098
+ };
86099
+ docReady(function() {
86100
+ window.print();
86101
+ });
85308
86102
  </script>
85309
86103
  </body>
85310
86104
  </html>
@@ -85389,6 +86183,9 @@ class PageSize {
85389
86183
  width: ${docWidth};
85390
86184
  height: ${docHeight};
85391
86185
  }
86186
+ .hide-on-print {
86187
+ display: none !important;
86188
+ }
85392
86189
  }
85393
86190
  @page {
85394
86191
  size:${docWidth} ${docHeight};;
@@ -85409,6 +86206,9 @@ class PageSize {
85409
86206
  width: ${w};
85410
86207
  height: ${h};
85411
86208
  }
86209
+ .hide-on-print {
86210
+ display: none !important;
86211
+ }
85412
86212
  }
85413
86213
  @page {
85414
86214
  size:${w} ${h};
@@ -85678,7 +86478,7 @@ class ContentBuilder {
85678
86478
  style: 'width:180px;height:112.5px'
85679
86479
  }, {
85680
86480
  title: 'Web (container)',
85681
- pagesize: '800px,1000px,web',
86481
+ pagesize: '1000px,1000px,web',
85682
86482
  style: 'width:180px;height:112.5px'
85683
86483
  }, {
85684
86484
  title: '8.27x5.52',
@@ -86519,6 +87319,12 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
86519
87319
  if (window.data_basic) {
86520
87320
  // if snippet file included
86521
87321
  this.opts.snippetJSON = window.data_basic;
87322
+ if (!this.canvas) for (let i = this.opts.snippetJSON.snippets.length - 1; i >= 0; i--) {
87323
+ if (this.opts.snippetJSON.snippets[i].mode === 'canvas') {
87324
+ this.opts.snippetJSON.snippets.splice(i, 1);
87325
+ }
87326
+ }
87327
+
86522
87328
  // if snippetPath is specified (not empty), then use the specified. Otherwise, use the one generated from snippet file (_snippets_path)
86523
87329
  if (this.opts.snippetPath === '') {
86524
87330
  this.opts.snippetPath = window._snippets_path;
@@ -86566,12 +87372,12 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
86566
87372
  // this.iconButtons = ['icon', 'color','textsettings', 'createLink','|', 'undo', 'redo', 'aiassistant', 'snippets', 'pageoptions', 'print', 'zoom', 'html'];
86567
87373
  // this.iconButtonsMore = [];
86568
87374
 
86569
- this.buttons = ['bold', 'italic', 'underline', 'formatting', 'color', 'align', 'textsettings', 'createLink', 'tags', '|', 'undo', 'redo', 'html', 'zoom', 'more'];
86570
- this.buttonsMore = ['icon', 'image', '|', 'list', 'font', 'formatPara', '|', 'aiassistant', 'snippets', 'pageoptions', 'print', 'preferences'];
86571
- this.elementButtons = ['front', 'backward', 'moveup', 'movedown', 'group', 'ungroup', 'duplicate', 'delete', 'left', 'center', 'right', 'full', 'undo', 'redo', 'blocksettings', 'html', 'zoom', 'more'];
86572
- this.elementButtonsMore = ['aiassistant', 'snippets', 'pageoptions', 'print', 'preferences'];
86573
- this.iconButtons = ['icon', 'color', 'textsettings', 'createLink', '|', 'undo', 'redo', 'html', 'zoom', 'more'];
86574
- this.iconButtonsMore = ['aiassistant', 'snippets', 'pageoptions', 'print', 'preferences'];
87375
+ this.buttons = ['bold', 'italic', 'underline', 'formatting', 'color', 'align', 'textsettings', 'createLink', 'tags', '|', 'undo', 'redo', 'zoom', 'pageoptions', 'print', 'html', 'more'];
87376
+ this.buttonsMore = ['icon', 'image', '|', 'list', 'font', 'formatPara', '|', 'aiassistant', 'snippets', 'preferences'];
87377
+ this.elementButtons = ['front', 'backward', 'moveup', 'movedown', 'group', 'ungroup', 'duplicate', 'delete', 'left', 'center', 'right', 'full', 'undo', 'redo', 'blocksettings', 'zoom', 'pageoptions', 'print', 'html', 'more'];
87378
+ this.elementButtonsMore = ['aiassistant', 'snippets', 'preferences'];
87379
+ this.iconButtons = ['icon', 'color', 'textsettings', 'createLink', '|', 'undo', 'redo', 'zoom', 'pageoptions', 'print', 'html', 'more'];
87380
+ this.iconButtonsMore = ['aiassistant', 'snippets', 'preferences'];
86575
87381
  if (!this.docContainer && this.container !== '.is-container') {
86576
87382
  this.docContainer = this.container;
86577
87383
  this.container = '.is-container';
@@ -87083,6 +87889,11 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
87083
87889
  this.rte.hideBlockButtons();
87084
87890
  this.rte.positionToolbar();
87085
87891
  }
87892
+ if (this.blockmodal) {
87893
+ setTimeout(() => {
87894
+ this.blockmodal.showHideControls();
87895
+ }, 30);
87896
+ }
87086
87897
  },
87087
87898
  onSelectBlock: block => {
87088
87899
  if (this.onSelectBlock) this.onSelectBlock(block);
@@ -87238,6 +88049,57 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
87238
88049
  }
87239
88050
  }
87240
88051
  });
88052
+
88053
+ // Copy & Paste Block
88054
+ document.addEventListener('keydown', e => {
88055
+ if ((e.ctrlKey || e.metaKey) && e.which === 67) {
88056
+ //CTRL-C
88057
+ const activeBlock = docContainer.querySelector('.is-block.active'); // always get .cloned
88058
+ if (activeBlock) {
88059
+ this.copyBlock = activeBlock;
88060
+ }
88061
+ }
88062
+ });
88063
+ document.addEventListener('keydown', e => {
88064
+ if ((e.ctrlKey || e.metaKey) && e.which === 86) {
88065
+ //CTRL-V
88066
+
88067
+ const box = docContainer.querySelector('.is-box.box-select'); // always get .cloned
88068
+ let block = this.copyBlock;
88069
+ if (box && block) {
88070
+ if (document.querySelector('.is-modal.active:not(.is-modal-content)')) return;
88071
+ const focusedElement = e.target;
88072
+ const isEditable = focusedElement.tagName === 'INPUT' || focusedElement.tagName === 'TEXTAREA' || focusedElement.hasAttribute('contenteditable');
88073
+ if (isEditable) return;
88074
+ this.uo.saveForUndo();
88075
+ let block = this.copyBlock;
88076
+ const builder = block.querySelector(this.container);
88077
+ let html = '';
88078
+ if (builder) {
88079
+ html = this.readHtml(builder);
88080
+ }
88081
+ let clonedDiv = block.cloneNode(true);
88082
+ clonedDiv.style.top = '20%';
88083
+ clonedDiv.style.left = '20%';
88084
+ if (builder) {
88085
+ const cloneBuilder = clonedDiv.querySelector(this.container);
88086
+ cloneBuilder.innerHTML = '';
88087
+ box.appendChild(clonedDiv);
88088
+ const range = document.createRange();
88089
+ cloneBuilder.appendChild(range.createContextualFragment(html));
88090
+ this.applyBehaviorOn(cloneBuilder);
88091
+ cloneBuilder.click();
88092
+ } else {
88093
+ block.parentNode.appendChild(clonedDiv);
88094
+ }
88095
+ block.classList.remove('active');
88096
+ this.doc.querySelectorAll('.clone').forEach(elm => elm.parentNode.removeChild(elm));
88097
+ this.doc.querySelectorAll('.cloned').forEach(elm => elm.classList.remove('cloned'));
88098
+ this.eb.refresh();
88099
+ this.opts.onChange();
88100
+ }
88101
+ }
88102
+ });
87241
88103
  }
87242
88104
  let previousWidth = this.win.innerWidth;
87243
88105
  let timer;
@@ -87667,6 +88529,22 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
87667
88529
  top: 0;
87668
88530
  left: -1000px;
87669
88531
  }
88532
+ .h-ruler {
88533
+ top:0;
88534
+ left:-100vw;
88535
+ width: 300vw;
88536
+ height:2px;
88537
+ display:none;
88538
+ }
88539
+ .h-ruler.active { display: block }
88540
+ .v-ruler {
88541
+ top:0;
88542
+ left:0;
88543
+ width:2px;
88544
+ height: 100%;
88545
+ display:none;
88546
+ }
88547
+ .v-ruler.active { display: block }
87670
88548
 
87671
88549
  /* Resize Handles */
87672
88550
  .handle {
@@ -87841,16 +88719,19 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
87841
88719
  @media (max-width: 760px) {
87842
88720
  .is-box.autolayout .is-block > .rotate-handle,
87843
88721
  .is-box.autolayout .is-block > .handle {
87844
- display: none;
88722
+ display: none;
87845
88723
  }
87846
88724
 
87847
88725
  /* NEW */
87848
- .is-block.clone {
88726
+ .is-box.autolayout .is-block.clone {
87849
88727
  display:none;
87850
88728
  }
87851
- .is-block.cloned {
88729
+ .is-box.autolayout .is-block.cloned {
87852
88730
  outline: var(--is-outline);
87853
88731
  }
88732
+ .is-box.box-select {
88733
+ outline: none !important;
88734
+ }
87854
88735
  }
87855
88736
 
87856
88737
  .is-block.locked .handle,
@@ -88517,7 +89398,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
88517
89398
  this.setZoomOnControl(builder);
88518
89399
  }
88519
89400
  html(area) {
88520
- if (this.docContainer) {
89401
+ if (this.docContainer && !area) {
88521
89402
  // freeform
88522
89403
 
88523
89404
  const docContainer = this.doc.querySelector(this.docContainer);
@@ -88625,7 +89506,33 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
88625
89506
  }
88626
89507
  refresh() {
88627
89508
  if (this.eb) this.eb.refresh();
89509
+
89510
+ /*
89511
+ // Add block tool
89512
+ let html = `
89513
+ <div class="is-tool is-block-tool">
89514
+ <button type="button" tabindex="-1" title="${this.util.out('Settings')}" class="block-settings"><svg class="is-icon-flex"><use xlink:href="#icon-settings"></use></svg></button>
89515
+ </div>
89516
+ `;
89517
+ let blocks = this.doc.querySelectorAll('.is-block');
89518
+ blocks.forEach(block => {
89519
+ let tool = block.querySelector('.is-block-tool');
89520
+ if(tool) tool.remove();
89521
+ block.insertAdjacentHTML('beforeend', html);
89522
+ tool = block.querySelector('.is-block-tool');
89523
+ tool.addEventListener('click',(e)=>{
89524
+ if(document.querySelector('.is-modal.editblock.active')) {
89525
+ this.blockmodal.hide();
89526
+ } else {
89527
+ this.blockmodal.show();
89528
+ }
89529
+ e.preventDefault();
89530
+ e.stopImmediatePropagation();
89531
+ });
89532
+ });
89533
+ */
88628
89534
  }
89535
+
88629
89536
  group() {
88630
89537
  if (!this.eb) return;
88631
89538
  this.uo.saveForUndo();
@@ -88780,6 +89687,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
88780
89687
  <!--
88781
89688
  <button type="button" tabindex="-1" class="box-settings" title="${this.util.out('Settings')}"><svg class="is-icon-flex"><use xlink:href="#ion-more"></use></svg></button>
88782
89689
  -->
89690
+ <button type="button" tabindex="-1" class="box-duplicate" title="${this.util.out('Duplicate')}"><svg class="is-icon-flex" style="width:14px;height:14px"><use xlink:href="#icon-duplicate"></use></svg></button>
88783
89691
  <button type="button" tabindex="-1" class="box-remove" title="${this.util.out('Remove')}"><svg class="is-icon-flex"><use xlink:href="#icon-trash"></use></svg></button>
88784
89692
  </div>
88785
89693
  <div class="is-tool is-canvasadd-tool" style="transform: scale(1); transform-origin: center top;">
@@ -88830,6 +89738,57 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
88830
89738
  });
88831
89739
  this.opts.onChange();
88832
89740
  });
89741
+ const btnDuplicate = box.querySelector('.is-canvas-tool .box-duplicate');
89742
+ btnDuplicate.addEventListener('click', e => {
89743
+ this.eb.selectClear(); // clear clone
89744
+
89745
+ // clear active
89746
+ const box = e.target.closest('.is-box');
89747
+ const block = box.querySelector('.is-block.active');
89748
+ if (block) block.classList.remove('active');
89749
+ this.uo.saveForUndo();
89750
+ let copiedBox = box.cloneNode(true);
89751
+ copiedBox.setAttribute('data-box-copied', '1');
89752
+ let parent = box.parentNode;
89753
+ parent.insertBefore(copiedBox, box.nextElementSibling);
89754
+ let newBox = docContainer.querySelector('[data-box-copied]');
89755
+ newBox.removeAttribute('data-box-copied');
89756
+
89757
+ // Code Blocks Handling
89758
+ let codeBlocks = newBox.querySelectorAll('[data-module]');
89759
+ codeBlocks.forEach(element => {
89760
+ let html = decodeURIComponent(element.getAttribute('data-html')); // Original code is stored in data-html attribute
89761
+ html = html.replace(/{id}/g, this.util.makeId());
89762
+ //Fill the block with original code
89763
+ this.html(element, html);
89764
+ });
89765
+ newBox.scrollIntoView({
89766
+ behavior: 'smooth',
89767
+ block: 'center'
89768
+ });
89769
+ this.applyBehaviorCanvas();
89770
+
89771
+ // ContentBuilder Handling
89772
+ let containers = newBox.querySelectorAll('.is-builder');
89773
+ containers.forEach(container => {
89774
+ let containerHtml = this.html(container);
89775
+ let range = document.createRange();
89776
+ container.innerHTML = '';
89777
+ container.appendChild(range.createContextualFragment(containerHtml));
89778
+ container.removeAttribute('data-sort'); //important (ContentBuilder cleanup for the container)
89779
+ this.applyBehaviorOn(container);
89780
+ });
89781
+ this.eb.refresh();
89782
+ this.opts.onChange();
89783
+
89784
+ // Change selection
89785
+ setTimeout(() => {
89786
+ box.classList.remove('box-select');
89787
+ const prevBox = docContainer.querySelector('.box-select');
89788
+ if (prevBox) prevBox.classList.remove('box-select');
89789
+ newBox.classList.add('box-select');
89790
+ }, 30);
89791
+ });
88833
89792
  const btnRemove = box.querySelector('.is-canvas-tool .box-remove');
88834
89793
  btnRemove.addEventListener('click', e => {
88835
89794
  const box = e.target.closest('.is-box');
@@ -89896,6 +90855,12 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
89896
90855
  script.async = true;
89897
90856
  script.onload = () => {
89898
90857
  this.opts.snippetJSON = window.data_basic;
90858
+ if (!this.canvas) for (let i = this.opts.snippetJSON.snippets.length - 1; i >= 0; i--) {
90859
+ if (this.opts.snippetJSON.snippets[i].mode === 'canvas') {
90860
+ this.opts.snippetJSON.snippets.splice(i, 1);
90861
+ }
90862
+ }
90863
+
89899
90864
  // if snippetPath is specified (not empty), then use the specified. Otherwise, use the one generated from snippet file (_snippets_path)
89900
90865
  if (this.opts.snippetPath === '') {
89901
90866
  this.opts.snippetPath = window._snippets_path;
@@ -89922,7 +90887,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
89922
90887
  html = `
89923
90888
  <div class="is-box box-canvas autolayout">
89924
90889
  <div class="is-block block-steady height-auto" style="top: calc(50% - 357px); left: calc(50% - 348px); width: 696px;" data--t="calc(50% - 357px)" data--l="calc(50% - 348px)" data--b="" data--r="" data--w="696px" data--h="">
89925
- <div class="is-container leading-12 size-17">
90890
+ <div class="is-container">
89926
90891
  ${html}
89927
90892
  </div>
89928
90893
  <div class="is-block-overlay"></div>
@@ -91494,6 +92459,13 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
91494
92459
 
91495
92460
  if (this.opts.emailMode) bSnippet = false;
91496
92461
 
92462
+ // check if is block
92463
+ let isBlock = false;
92464
+ if (html.includes('"is-block')) {
92465
+ isBlock = true;
92466
+ bSnippet = false;
92467
+ }
92468
+
91497
92469
  // Convert snippet into your defined 12 columns grid
91498
92470
  var rowClass = this.opts.row; //row
91499
92471
  var colClass = this.opts.cols; //['col s1', 'col s2', 'col s3', 'col s4', 'col s5', 'col s6', 'col s7', 'col s8', 'col s9', 'col s10', 'col s11', 'col s12']
@@ -91540,24 +92512,26 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
91540
92512
  this.dom.removeClass(itemEl, 'snippet-item');
91541
92513
  let bw = '';
91542
92514
  if (this.page && this.page === '.is-wrapper') {
91543
- bw = '800px';
92515
+ bw = '760px';
91544
92516
  } else {
91545
92517
  if (occurrences === 2) {
91546
- bw = '800px';
92518
+ bw = '760px';
91547
92519
  } else if (occurrences >= 3) {
91548
- bw = '800px';
92520
+ bw = '760px';
91549
92521
  } else {
91550
92522
  bw = '540px';
91551
92523
  }
91552
92524
  }
91553
92525
  const blockTemplate = `
91554
92526
  <div class="is-block block-steady height-auto" data-new-dummy="1" style="top: 20%; left: 20%; width: ${bw};">
91555
- <div class="is-container container-new leading-12 size-17">
92527
+ <div class="is-container container-new">
91556
92528
  [%CONTENT%]
91557
92529
  </div>
91558
92530
  </div>
91559
92531
  `; // data-new-dummy will be used by onSort to apply top/left position (snippetpanel.js)
91560
92532
  itemEl.outerHTML = blockTemplate.replace('[%CONTENT%]', html);
92533
+ } else if (isBlock) {
92534
+ itemEl.outerHTML = html;
91561
92535
  } else {
91562
92536
  // Snippet is wrapped in row/colum (may contain custom code or has [data-html] attribute)
91563
92537
  // Can only be inserted after current row or last row (not on column or element).
@@ -91590,19 +92564,19 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
91590
92564
  itemEl.appendChild(range.createContextualFragment(html));
91591
92565
  let bw = '';
91592
92566
  if (this.page && this.page === '.is-wrapper') {
91593
- bw = '800px';
92567
+ bw = '760px';
91594
92568
  } else {
91595
92569
  if (occurrences === 2) {
91596
- bw = '800px';
92570
+ bw = '760px';
91597
92571
  } else if (occurrences >= 3) {
91598
- bw = '800px';
92572
+ bw = '760px';
91599
92573
  } else {
91600
92574
  bw = '540px';
91601
92575
  }
91602
92576
  }
91603
92577
  const blockTemplate = `
91604
92578
  <div class="is-block block-steady height-auto" data-new-dummy="1" style="top: 20%; left: 20%; width: ${bw};">
91605
- <div class="is-container container-new leading-12 size-17">
92579
+ <div class="is-container container-new">
91606
92580
  [%CONTENT%]
91607
92581
  </div>
91608
92582
  </div>