@innovastudio/contentbox 1.6.165 → 1.6.166
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.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@innovastudio/contentbox",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.166",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "public/contentbox/contentbox.esm.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"ws": "^8.13.0"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@innovastudio/contentbuilder": "^1.5.
|
|
62
|
+
"@innovastudio/contentbuilder": "^1.5.164",
|
|
63
63
|
"js-beautify": "^1.14.0",
|
|
64
64
|
"sortablejs": "^1.15.2"
|
|
65
65
|
}
|
|
@@ -12625,6 +12625,45 @@ class SettingsUIGenerator$1 {
|
|
|
12625
12625
|
return label;
|
|
12626
12626
|
}
|
|
12627
12627
|
|
|
12628
|
+
hexToRgba(color) {
|
|
12629
|
+
// If it's already rgba() or rgb(), just return as-is
|
|
12630
|
+
if (/^rgba?\(/i.test(color)) {
|
|
12631
|
+
return color;
|
|
12632
|
+
} // Otherwise assume hex
|
|
12633
|
+
|
|
12634
|
+
|
|
12635
|
+
color = color.replace(/^#/, ''); // Expand shorthand hex (#rgb or #rgba)
|
|
12636
|
+
|
|
12637
|
+
if (color.length === 3 || color.length === 4) {
|
|
12638
|
+
color = color.split('').map(ch => ch + ch).join('');
|
|
12639
|
+
} // Parse r, g, b, a
|
|
12640
|
+
|
|
12641
|
+
|
|
12642
|
+
const r = parseInt(color.substring(0, 2), 16);
|
|
12643
|
+
const g = parseInt(color.substring(2, 4), 16);
|
|
12644
|
+
const b = parseInt(color.substring(4, 6), 16);
|
|
12645
|
+
const a = color.length === 8 ? parseInt(color.substring(6, 8), 16) / 255 : 1;
|
|
12646
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
12647
|
+
}
|
|
12648
|
+
|
|
12649
|
+
toHex(colorStr) {
|
|
12650
|
+
const ctx = document.createElement('canvas').getContext('2d');
|
|
12651
|
+
ctx.fillStyle = colorStr;
|
|
12652
|
+
const computed = ctx.fillStyle; // browser-normalized color
|
|
12653
|
+
// If already hex and 7 or 9 chars long (#rrggbb or #rrggbbaa), return as-is
|
|
12654
|
+
|
|
12655
|
+
if (computed.startsWith('#')) return computed; // Parse rgba(...) or rgb(...)
|
|
12656
|
+
|
|
12657
|
+
const rgba = computed.match(/\d+(\.\d+)?/g).map(Number);
|
|
12658
|
+
const [r, g, b, a = 1] = rgba; // default alpha = 1
|
|
12659
|
+
// Convert RGB and Alpha to hex (2 digits each)
|
|
12660
|
+
|
|
12661
|
+
const rgbHex = [r, g, b].map(v => v.toString(16).padStart(2, '0')).join('');
|
|
12662
|
+
const alphaHex = Math.round(a * 255).toString(16).padStart(2, '0'); // Only include alpha if it's not fully opaque
|
|
12663
|
+
|
|
12664
|
+
return a < 1 ? `#${rgbHex}${alphaHex}` : `#${rgbHex}`;
|
|
12665
|
+
}
|
|
12666
|
+
|
|
12628
12667
|
createColorInput(name, config, value) {
|
|
12629
12668
|
const container = document.createElement('div');
|
|
12630
12669
|
const label = document.createElement('label');
|
|
@@ -12645,13 +12684,15 @@ class SettingsUIGenerator$1 {
|
|
|
12645
12684
|
colorBtn.type = 'button';
|
|
12646
12685
|
colorBtn.title = config.label || 'Color';
|
|
12647
12686
|
colorBtn.className = 'btn-color is-btn-color';
|
|
12648
|
-
colorBtn.style.backgroundColor = input.value;
|
|
12687
|
+
colorBtn.style.backgroundColor = this.hexToRgba(input.value);
|
|
12649
12688
|
colorBtn.setAttribute('aria-label', `Choose color for ${config.label || name}`);
|
|
12650
12689
|
|
|
12651
12690
|
const openPicker = e => {
|
|
12652
12691
|
e.preventDefault();
|
|
12653
12692
|
this.builder.openColorPicker(input.value, color => {
|
|
12654
|
-
input.value = color;
|
|
12693
|
+
// input.value = color;
|
|
12694
|
+
const hex = this.toHex(color);
|
|
12695
|
+
input.value = hex;
|
|
12655
12696
|
colorBtn.style.backgroundColor = color;
|
|
12656
12697
|
input.dispatchEvent(new Event('change', {
|
|
12657
12698
|
bubbles: true
|
|
@@ -12717,10 +12758,10 @@ class SettingsUIGenerator$1 {
|
|
|
12717
12758
|
input.type = 'range';
|
|
12718
12759
|
input.className = 'is-rangeslider';
|
|
12719
12760
|
input.name = name;
|
|
12720
|
-
input.value = currentVal;
|
|
12721
12761
|
if (config.min !== undefined) input.min = config.min;
|
|
12722
12762
|
if (config.max !== undefined) input.max = config.max;
|
|
12723
12763
|
if (config.step !== undefined) input.step = config.step;
|
|
12764
|
+
input.value = currentVal;
|
|
12724
12765
|
input.addEventListener('input', () => {
|
|
12725
12766
|
labelText.textContent = (config.label || name) + ': ' + input.value + (config.unit || '');
|
|
12726
12767
|
});
|
|
@@ -12853,7 +12894,23 @@ class PanelPlugin {
|
|
|
12853
12894
|
const originalElement = editableClone.cloneNode(false); // Let plugin handle everything - pass the editable clone
|
|
12854
12895
|
|
|
12855
12896
|
const editorUI = plugin.editor.openContentEditor(editableClone, this.builder, async () => {
|
|
12856
|
-
this.builder.editor.saveForUndo(); //
|
|
12897
|
+
this.builder.editor.saveForUndo(); // Add index for sortable grid (for easy reorder)
|
|
12898
|
+
|
|
12899
|
+
let grid = editableClone.querySelector('.grid-sortable');
|
|
12900
|
+
|
|
12901
|
+
if (!grid) {
|
|
12902
|
+
if (currentElement.classList.contains('grid-sortable')) {
|
|
12903
|
+
grid = editableClone;
|
|
12904
|
+
}
|
|
12905
|
+
}
|
|
12906
|
+
|
|
12907
|
+
if (grid) {
|
|
12908
|
+
Array.from(grid.children).forEach((child, index) => {
|
|
12909
|
+
if (child.nodeType === 1 && child.tagName !== 'STYLE' && child.tagName !== 'SCRIPT') child.setAttribute('data-index', index);
|
|
12910
|
+
});
|
|
12911
|
+
} //----
|
|
12912
|
+
// Store edited content from clone
|
|
12913
|
+
|
|
12857
12914
|
|
|
12858
12915
|
currentElement.setAttribute('data-cb-original-content', editableClone.innerHTML); // Also performs similar value updates like the applyChanges()
|
|
12859
12916
|
// currentElement.setAttribute('data-cb-content', editableClone.getAttribute('data-cb-content'));
|
|
@@ -12884,6 +12941,8 @@ class PanelPlugin {
|
|
|
12884
12941
|
|
|
12885
12942
|
await runtime.reinitialize(currentElement.parentElement);
|
|
12886
12943
|
this.builder.onChange();
|
|
12944
|
+
this.builder.editor.hideElementTools();
|
|
12945
|
+
this.builder.makeSortable(currentElement.parentElement);
|
|
12887
12946
|
});
|
|
12888
12947
|
div.appendChild(editorUI);
|
|
12889
12948
|
} // Generate form
|
|
@@ -12906,6 +12965,8 @@ class PanelPlugin {
|
|
|
12906
12965
|
const container = this.currentElement.parentElement || this.currentElement.closest('.is-wrapper');
|
|
12907
12966
|
await runtime.reinitialize(container);
|
|
12908
12967
|
this.builder.onChange(); // console.log('Settings applied and component reinitialized');
|
|
12968
|
+
|
|
12969
|
+
this.builder.makeSortable(container);
|
|
12909
12970
|
}
|
|
12910
12971
|
|
|
12911
12972
|
}
|
|
@@ -26934,6 +26995,7 @@ class ControlPanel {
|
|
|
26934
26995
|
}
|
|
26935
26996
|
|
|
26936
26997
|
const plugin = runtime.getPlugin(pluginName);
|
|
26998
|
+
if (!plugin) return;
|
|
26937
26999
|
let titleHtml = out(plugin.displayName || plugin.name);
|
|
26938
27000
|
this.title.innerHTML = titleHtml; // this.title.style.cssText = 'margin-bottom: 0';
|
|
26939
27001
|
|
|
@@ -32643,18 +32705,21 @@ class Util$1 {
|
|
|
32643
32705
|
let builderActive = this.builder.doc.querySelector('.builder-active');
|
|
32644
32706
|
if (builderActive) this.builder.applyBehaviorOn(builderActive);
|
|
32645
32707
|
this.fixLayout(row);
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
|
|
32649
|
-
|
|
32708
|
+
try {
|
|
32709
|
+
// cellElement.click(); //change active block to the newly created
|
|
32710
|
+
if (element && element.tagName.toLowerCase() === 'img') {
|
|
32711
|
+
element.onload = () => {
|
|
32712
|
+
element.click();
|
|
32713
|
+
element.onload = null;
|
|
32714
|
+
setTimeout(() => {
|
|
32715
|
+
this.builder.element.image.repositionImageTool();
|
|
32716
|
+
}, 100);
|
|
32717
|
+
};
|
|
32718
|
+
} else if (element) {
|
|
32650
32719
|
element.click();
|
|
32651
|
-
|
|
32652
|
-
|
|
32653
|
-
|
|
32654
|
-
}, 100);
|
|
32655
|
-
};
|
|
32656
|
-
} else if (element) {
|
|
32657
|
-
element.click();
|
|
32720
|
+
}
|
|
32721
|
+
} catch (e) {
|
|
32722
|
+
// Do Nothing
|
|
32658
32723
|
}
|
|
32659
32724
|
}
|
|
32660
32725
|
if (mode === 'row') {
|
|
@@ -32772,6 +32837,10 @@ class Util$1 {
|
|
|
32772
32837
|
|
|
32773
32838
|
//Trigger Render event
|
|
32774
32839
|
this.builder.opts.onRender();
|
|
32840
|
+
|
|
32841
|
+
// Reinit after drag drop block
|
|
32842
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize();
|
|
32843
|
+
this.builder.makeSortable(this.builder.doc);
|
|
32775
32844
|
}
|
|
32776
32845
|
|
|
32777
32846
|
// https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro
|
|
@@ -32864,6 +32933,7 @@ class Util$1 {
|
|
|
32864
32933
|
|
|
32865
32934
|
//Hide Column tool (new!)
|
|
32866
32935
|
this.builder.util.hideColumnTool();
|
|
32936
|
+
this.builder.makeSortable(rowElement);
|
|
32867
32937
|
} else if (bSnippet) {
|
|
32868
32938
|
if (noedit) {
|
|
32869
32939
|
this.addContent(html, mode, 'data-noedit');
|
|
@@ -33037,6 +33107,7 @@ class Util$1 {
|
|
|
33037
33107
|
this.builder.doc.querySelectorAll('.dummy-module').forEach(module => {
|
|
33038
33108
|
module.classList.remove('dummy-module');
|
|
33039
33109
|
});
|
|
33110
|
+
this.builder.makeSortable(this.builder.doc);
|
|
33040
33111
|
|
|
33041
33112
|
// Change to row selection
|
|
33042
33113
|
rowElement.className = rowElement.className.replace('row-outline', '');
|
|
@@ -41663,6 +41734,7 @@ class HtmlUtil {
|
|
|
41663
41734
|
// Re-init plugins
|
|
41664
41735
|
if (this.builder.win.builderRuntime) await this.builder.win.builderRuntime.reinitialize();
|
|
41665
41736
|
this.builder.hideModal(modal);
|
|
41737
|
+
this.builder.makeSortable(this.builder.doc);
|
|
41666
41738
|
}
|
|
41667
41739
|
viewHtmlExternal() {
|
|
41668
41740
|
const util = this.builder.util;
|
|
@@ -42235,6 +42307,25 @@ class HtmlUtil {
|
|
|
42235
42307
|
element.classList.remove(`cb-${type}`);
|
|
42236
42308
|
}
|
|
42237
42309
|
element.removeAttribute('data-cb-loaded');
|
|
42310
|
+
let grid;
|
|
42311
|
+
if (element.classList.contains('grid-sortable')) {
|
|
42312
|
+
grid = element;
|
|
42313
|
+
}
|
|
42314
|
+
if (element.querySelector('.grid-sortable')) {
|
|
42315
|
+
grid = element.querySelector('.grid-sortable');
|
|
42316
|
+
}
|
|
42317
|
+
element.removeAttribute('id');
|
|
42318
|
+
if (grid) {
|
|
42319
|
+
Array.from(grid.children).forEach(elm => {
|
|
42320
|
+
elm.removeAttribute('data-index');
|
|
42321
|
+
elm.removeAttribute('data-item-id');
|
|
42322
|
+
});
|
|
42323
|
+
}
|
|
42324
|
+
const elms = element.querySelectorAll('[data-scroll], [data-scroll-once]');
|
|
42325
|
+
elms.forEach(elm => {
|
|
42326
|
+
elm.removeAttribute('data-scroll');
|
|
42327
|
+
elm.removeAttribute('data-scroll-once');
|
|
42328
|
+
});
|
|
42238
42329
|
});
|
|
42239
42330
|
html = '';
|
|
42240
42331
|
if (multiple) {
|
|
@@ -43367,6 +43458,9 @@ class Grid {
|
|
|
43367
43458
|
this.builder.hideTools();
|
|
43368
43459
|
cell.parentElement.insertBefore(cell, cell.previousElementSibling);
|
|
43369
43460
|
this.builder.opts.onChange(true);
|
|
43461
|
+
|
|
43462
|
+
// Re-init plugins
|
|
43463
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(cell);
|
|
43370
43464
|
}
|
|
43371
43465
|
}
|
|
43372
43466
|
moveColumnNext() {
|
|
@@ -43379,6 +43473,9 @@ class Grid {
|
|
|
43379
43473
|
this.builder.hideTools();
|
|
43380
43474
|
cell.parentElement.insertBefore(cellnext, cell);
|
|
43381
43475
|
this.builder.opts.onChange(true);
|
|
43476
|
+
|
|
43477
|
+
// Re-init plugins
|
|
43478
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(cell);
|
|
43382
43479
|
}
|
|
43383
43480
|
}
|
|
43384
43481
|
moveColumnUp() {
|
|
@@ -43408,6 +43505,9 @@ class Grid {
|
|
|
43408
43505
|
//Move row up
|
|
43409
43506
|
row.parentNode.insertBefore(row, row.previousElementSibling);
|
|
43410
43507
|
this.builder.opts.onChange(true);
|
|
43508
|
+
|
|
43509
|
+
// Re-init plugins
|
|
43510
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
43411
43511
|
return;
|
|
43412
43512
|
} else {
|
|
43413
43513
|
this.builder.uo.saveForUndo();
|
|
@@ -43458,6 +43558,9 @@ class Grid {
|
|
|
43458
43558
|
row = cell.parentNode; //update active row
|
|
43459
43559
|
util.fixLayout(row);
|
|
43460
43560
|
if (row.nextElementSibling) util.fixLayout(row.nextElementSibling);
|
|
43561
|
+
|
|
43562
|
+
// Re-init plugins
|
|
43563
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
43461
43564
|
}
|
|
43462
43565
|
moveColumnDown() {
|
|
43463
43566
|
let builder = this.builder;
|
|
@@ -43488,6 +43591,9 @@ class Grid {
|
|
|
43488
43591
|
//Move row down
|
|
43489
43592
|
row.parentNode.insertBefore(row.nextElementSibling, row);
|
|
43490
43593
|
this.builder.opts.onChange(true);
|
|
43594
|
+
|
|
43595
|
+
// Re-init plugins
|
|
43596
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
43491
43597
|
return;
|
|
43492
43598
|
} else {
|
|
43493
43599
|
this.builder.uo.saveForUndo();
|
|
@@ -43538,6 +43644,9 @@ class Grid {
|
|
|
43538
43644
|
row = cell.parentNode; //update active row
|
|
43539
43645
|
util.fixLayout(row);
|
|
43540
43646
|
if (row.previousElementSibling) util.fixLayout(row.previousElementSibling);
|
|
43647
|
+
|
|
43648
|
+
// Re-init plugins
|
|
43649
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
43541
43650
|
}
|
|
43542
43651
|
duplicateColumn() {
|
|
43543
43652
|
let builder = this.builder;
|
|
@@ -44241,6 +44350,9 @@ class Grid {
|
|
|
44241
44350
|
row.parentNode.insertBefore(row, row.previousElementSibling);
|
|
44242
44351
|
this.rowTool.position(row);
|
|
44243
44352
|
this.builder.opts.onChange();
|
|
44353
|
+
|
|
44354
|
+
// Re-init plugins
|
|
44355
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
44244
44356
|
} else {
|
|
44245
44357
|
// Move to previous container
|
|
44246
44358
|
|
|
@@ -44285,6 +44397,9 @@ class Grid {
|
|
|
44285
44397
|
row.parentNode.insertBefore(row.nextElementSibling, row);
|
|
44286
44398
|
this.rowTool.position(row);
|
|
44287
44399
|
this.builder.opts.onChange();
|
|
44400
|
+
|
|
44401
|
+
// Re-init plugins
|
|
44402
|
+
if (this.builder.win.builderRuntime) this.builder.win.builderRuntime.reinitialize(row);
|
|
44288
44403
|
} else {
|
|
44289
44404
|
// Move to next container
|
|
44290
44405
|
|
|
@@ -123188,6 +123303,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
|
|
|
123188
123303
|
}
|
|
123189
123304
|
});
|
|
123190
123305
|
});
|
|
123306
|
+
this.makeSortable(this.doc);
|
|
123191
123307
|
}
|
|
123192
123308
|
|
|
123193
123309
|
// Load plugins
|
|
@@ -125165,6 +125281,7 @@ Add an image for each feature.`, 'Create a new content showcasing a photo galler
|
|
|
125165
125281
|
});
|
|
125166
125282
|
});
|
|
125167
125283
|
});
|
|
125284
|
+
this.makeSortable(this.doc);
|
|
125168
125285
|
this.doc.querySelectorAll('.dummy-module').forEach(module => {
|
|
125169
125286
|
module.classList.remove('dummy-module');
|
|
125170
125287
|
});
|
|
@@ -126952,24 +127069,7 @@ Please obtain a license at: https://innovastudio.com/contentbox`);
|
|
|
126952
127069
|
});
|
|
126953
127070
|
|
|
126954
127071
|
// On Load HTML
|
|
126955
|
-
|
|
126956
|
-
grids.forEach(grid => {
|
|
126957
|
-
if (grid.closest('.is-builder')) new Sortable$1(grid, {
|
|
126958
|
-
animation: 600,
|
|
126959
|
-
dragClass: 'hide-drag-class',
|
|
126960
|
-
onStart: () => {
|
|
126961
|
-
this.uo.saveForUndo(true);
|
|
126962
|
-
},
|
|
126963
|
-
onSort: () => {
|
|
126964
|
-
if (grid.closest('[data-html]')) {
|
|
126965
|
-
const moduleElm = grid.closest('[data-html]');
|
|
126966
|
-
const encodedHtml = encodeURIComponent(moduleElm.innerHTML);
|
|
126967
|
-
moduleElm.setAttribute('data-html', encodedHtml);
|
|
126968
|
-
this.opts.onChange();
|
|
126969
|
-
}
|
|
126970
|
-
}
|
|
126971
|
-
});
|
|
126972
|
-
});
|
|
127072
|
+
this.makeSortable(this.doc, true);
|
|
126973
127073
|
this.refresh();
|
|
126974
127074
|
if (this.win.Block) {
|
|
126975
127075
|
this.win.Block.render();
|
|
@@ -127009,24 +127109,7 @@ Please obtain a license at: https://innovastudio.com/contentbox`);
|
|
|
127009
127109
|
this.applyBehavior();
|
|
127010
127110
|
|
|
127011
127111
|
// On Load HTML
|
|
127012
|
-
|
|
127013
|
-
grids.forEach(grid => {
|
|
127014
|
-
if (grid.closest('.is-builder')) new Sortable$1(grid, {
|
|
127015
|
-
animation: 600,
|
|
127016
|
-
dragClass: 'hide-drag-class',
|
|
127017
|
-
onStart: () => {
|
|
127018
|
-
this.uo.saveForUndo(true);
|
|
127019
|
-
},
|
|
127020
|
-
onSort: () => {
|
|
127021
|
-
if (grid.closest('[data-html]')) {
|
|
127022
|
-
const moduleElm = grid.closest('[data-html]');
|
|
127023
|
-
const encodedHtml = encodeURIComponent(moduleElm.innerHTML);
|
|
127024
|
-
moduleElm.setAttribute('data-html', encodedHtml);
|
|
127025
|
-
this.opts.onChange();
|
|
127026
|
-
}
|
|
127027
|
-
}
|
|
127028
|
-
});
|
|
127029
|
-
});
|
|
127112
|
+
this.makeSortable(this.doc, true);
|
|
127030
127113
|
|
|
127031
127114
|
// this.uo.saveForUndo(); //First time
|
|
127032
127115
|
|
|
@@ -129625,6 +129708,86 @@ Please obtain a license at: https://innovastudio.com/contentbox`);
|
|
|
129625
129708
|
// this.doc.querySelectorAll('.elm-inspected').forEach(elm => elm.classList.remove('elm-inspected'));
|
|
129626
129709
|
// this.doc.querySelectorAll('.elm-active').forEach(elm => elm.classList.remove('elm-active'));
|
|
129627
129710
|
}
|
|
129711
|
+
|
|
129712
|
+
// Make list inside plugin element sortable
|
|
129713
|
+
makeSortable(container, module) {
|
|
129714
|
+
const grids = container.querySelectorAll('.grid-sortable');
|
|
129715
|
+
grids.forEach(grid => {
|
|
129716
|
+
const sortable = new Sortable$1(grid, {
|
|
129717
|
+
animation: 600,
|
|
129718
|
+
onStart: () => {
|
|
129719
|
+
this.uo.saveForUndo(true);
|
|
129720
|
+
},
|
|
129721
|
+
onSort: async () => {
|
|
129722
|
+
if (module) if (grid.closest('[data-html]')) {
|
|
129723
|
+
const moduleElm = grid.closest('[data-html]');
|
|
129724
|
+
const encodedHtml = encodeURIComponent(moduleElm.innerHTML);
|
|
129725
|
+
moduleElm.setAttribute('data-html', encodedHtml);
|
|
129726
|
+
this.onChange();
|
|
129727
|
+
}
|
|
129728
|
+
let plugin = grid.closest('[data-cb-original-content]');
|
|
129729
|
+
if (plugin) {
|
|
129730
|
+
// grid.setAttribute('data-cb-original-content', plugin.innerHTML); // don't do this!
|
|
129731
|
+
this.updateCleanContentOrder(grid); // use this!
|
|
129732
|
+
|
|
129733
|
+
this.onChange();
|
|
129734
|
+
grid.click();
|
|
129735
|
+
}
|
|
129736
|
+
}
|
|
129737
|
+
});
|
|
129738
|
+
// Store instance for later access
|
|
129739
|
+
grid._sortable = sortable;
|
|
129740
|
+
});
|
|
129741
|
+
}
|
|
129742
|
+
async updateCleanContentOrder(grid) {
|
|
129743
|
+
if (!grid) return;
|
|
129744
|
+
const plugin = grid.closest('[data-cb-original-content]');
|
|
129745
|
+
if (!plugin) return;
|
|
129746
|
+
|
|
129747
|
+
// 1. Get the current visual order of data-index from the actual DOM
|
|
129748
|
+
const newIndexOrder = Array.from(grid.children).map(child => child.dataset.index).filter(index => index !== undefined); // in case some lack data-index
|
|
129749
|
+
|
|
129750
|
+
// 2. Parse the *original clean* HTML
|
|
129751
|
+
const cleanHtml = plugin.dataset.cbOriginalContent;
|
|
129752
|
+
const parser = new DOMParser();
|
|
129753
|
+
const doc = parser.parseFromString(cleanHtml, 'text/html');
|
|
129754
|
+
let cleanGrid = doc.querySelector('.grid-sortable');
|
|
129755
|
+
let pluginIsSortableRoot = false;
|
|
129756
|
+
if (!cleanGrid) {
|
|
129757
|
+
// console.log('[step] .grid-sortable not found inside parsed clean HTML — creating wrapper from body children');
|
|
129758
|
+
cleanGrid = doc.createElement('div');
|
|
129759
|
+
cleanGrid.classList.add('grid-sortable');
|
|
129760
|
+
Array.from(doc.body.children).forEach(child => {
|
|
129761
|
+
if (child.nodeType === 1) cleanGrid.appendChild(child);
|
|
129762
|
+
});
|
|
129763
|
+
doc.body.innerHTML = '';
|
|
129764
|
+
doc.body.appendChild(cleanGrid);
|
|
129765
|
+
pluginIsSortableRoot = true;
|
|
129766
|
+
}
|
|
129767
|
+
const cleanItems = Array.from(cleanGrid.children).filter(el => el.nodeType === 1);
|
|
129768
|
+
|
|
129769
|
+
// 3. Build a map: data-index → clean node
|
|
129770
|
+
const cleanItemMap = new Map();
|
|
129771
|
+
cleanItems.forEach(item => {
|
|
129772
|
+
const idx = item.dataset.index;
|
|
129773
|
+
if (idx !== undefined) cleanItemMap.set(idx, item);
|
|
129774
|
+
});
|
|
129775
|
+
|
|
129776
|
+
// 4. Reorder clean items to match newIndexOrder
|
|
129777
|
+
const reorderedCleanItems = newIndexOrder.map(idx => cleanItemMap.get(idx)).filter(Boolean); // skip missing
|
|
129778
|
+
|
|
129779
|
+
// 5. Serialize back to HTML string
|
|
129780
|
+
const newCleanHtml = reorderedCleanItems.map(item => item.outerHTML).join('');
|
|
129781
|
+
|
|
129782
|
+
// 6. Update the clean source
|
|
129783
|
+
if (pluginIsSortableRoot) {
|
|
129784
|
+
plugin.setAttribute('data-cb-original-content', newCleanHtml);
|
|
129785
|
+
} else {
|
|
129786
|
+
cleanGrid.innerHTML = newCleanHtml;
|
|
129787
|
+
const newHTML = doc.body.innerHTML;
|
|
129788
|
+
plugin.setAttribute('data-cb-original-content', newHTML);
|
|
129789
|
+
}
|
|
129790
|
+
}
|
|
129628
129791
|
}
|
|
129629
129792
|
|
|
129630
129793
|
class ContentStuff {
|
|
@@ -165286,23 +165449,7 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
|
165286
165449
|
activeModule.appendChild(range.createContextualFragment(html)); // We use createContextualFragment so that embedded javascript code (code block) will be executed
|
|
165287
165450
|
|
|
165288
165451
|
this.settings.onRender();
|
|
165289
|
-
|
|
165290
|
-
grids.forEach(grid => {
|
|
165291
|
-
new Sortable(grid, {
|
|
165292
|
-
animation: 600,
|
|
165293
|
-
onStart: () => {
|
|
165294
|
-
this.editor.saveForUndo(true);
|
|
165295
|
-
},
|
|
165296
|
-
onSort: () => {
|
|
165297
|
-
if (grid.closest('[data-html]')) {
|
|
165298
|
-
const moduleElm = grid.closest('[data-html]');
|
|
165299
|
-
const encodedHtml = encodeURIComponent(moduleElm.innerHTML);
|
|
165300
|
-
moduleElm.setAttribute('data-html', encodedHtml);
|
|
165301
|
-
this.onChange();
|
|
165302
|
-
}
|
|
165303
|
-
}
|
|
165304
|
-
});
|
|
165305
|
-
});
|
|
165452
|
+
this.makeSortable(activeModule);
|
|
165306
165453
|
this.settings.onChange();
|
|
165307
165454
|
this.hideModal(modalEditModule);
|
|
165308
165455
|
});
|
|
@@ -166369,27 +166516,89 @@ Add an image for each feature.`, 'Create a new block showcasing a photo gallery
|
|
|
166369
166516
|
const typePanel = document.querySelector('#divSidebarTypography');
|
|
166370
166517
|
if (typePanel.classList.contains('active')) this.sidebar.selectType();
|
|
166371
166518
|
});
|
|
166372
|
-
|
|
166373
|
-
|
|
166519
|
+
this.makeSortable(box, true);
|
|
166520
|
+
} // boxSetup
|
|
166521
|
+
// Make list inside plugin element sortable
|
|
166522
|
+
|
|
166374
166523
|
|
|
166524
|
+
makeSortable(container, module) {
|
|
166525
|
+
const grids = container.querySelectorAll('.grid-sortable');
|
|
166375
166526
|
grids.forEach(grid => {
|
|
166376
|
-
new Sortable(grid, {
|
|
166527
|
+
const sortable = new Sortable(grid, {
|
|
166377
166528
|
animation: 600,
|
|
166378
166529
|
onStart: () => {
|
|
166379
166530
|
this.editor.saveForUndo(true);
|
|
166380
166531
|
},
|
|
166381
|
-
onSort: () => {
|
|
166382
|
-
if (grid.closest('[data-html]')) {
|
|
166532
|
+
onSort: async () => {
|
|
166533
|
+
if (module) if (grid.closest('[data-html]')) {
|
|
166383
166534
|
const moduleElm = grid.closest('[data-html]');
|
|
166384
166535
|
const encodedHtml = encodeURIComponent(moduleElm.innerHTML);
|
|
166385
166536
|
moduleElm.setAttribute('data-html', encodedHtml);
|
|
166386
166537
|
this.onChange();
|
|
166387
166538
|
}
|
|
166539
|
+
let plugin = grid.closest('[data-cb-original-content]');
|
|
166540
|
+
|
|
166541
|
+
if (plugin) {
|
|
166542
|
+
// grid.setAttribute('data-cb-original-content', plugin.innerHTML); // don't do this!
|
|
166543
|
+
this.updateCleanContentOrder(grid); // use this!
|
|
166544
|
+
|
|
166545
|
+
this.onChange();
|
|
166546
|
+
grid.click();
|
|
166547
|
+
}
|
|
166388
166548
|
}
|
|
166389
|
-
});
|
|
166549
|
+
}); // Store instance for later access
|
|
166550
|
+
|
|
166551
|
+
grid._sortable = sortable;
|
|
166390
166552
|
});
|
|
166391
|
-
}
|
|
166553
|
+
}
|
|
166554
|
+
|
|
166555
|
+
async updateCleanContentOrder(grid) {
|
|
166556
|
+
if (!grid) return;
|
|
166557
|
+
const plugin = grid.closest('[data-cb-original-content]');
|
|
166558
|
+
if (!plugin) return; // 1. Get the current visual order of data-index from the actual DOM
|
|
166559
|
+
|
|
166560
|
+
const newIndexOrder = Array.from(grid.children).map(child => child.dataset.index).filter(index => index !== undefined); // in case some lack data-index
|
|
166561
|
+
// 2. Parse the *original clean* HTML
|
|
166562
|
+
|
|
166563
|
+
const cleanHtml = plugin.dataset.cbOriginalContent;
|
|
166564
|
+
const parser = new DOMParser();
|
|
166565
|
+
const doc = parser.parseFromString(cleanHtml, 'text/html');
|
|
166566
|
+
let cleanGrid = doc.querySelector('.grid-sortable');
|
|
166567
|
+
let pluginIsSortableRoot = false;
|
|
166392
166568
|
|
|
166569
|
+
if (!cleanGrid) {
|
|
166570
|
+
// console.log('[step] .grid-sortable not found inside parsed clean HTML — creating wrapper from body children');
|
|
166571
|
+
cleanGrid = doc.createElement('div');
|
|
166572
|
+
cleanGrid.classList.add('grid-sortable');
|
|
166573
|
+
Array.from(doc.body.children).forEach(child => {
|
|
166574
|
+
if (child.nodeType === 1) cleanGrid.appendChild(child);
|
|
166575
|
+
});
|
|
166576
|
+
doc.body.innerHTML = '';
|
|
166577
|
+
doc.body.appendChild(cleanGrid);
|
|
166578
|
+
pluginIsSortableRoot = true;
|
|
166579
|
+
}
|
|
166580
|
+
|
|
166581
|
+
const cleanItems = Array.from(cleanGrid.children).filter(el => el.nodeType === 1); // 3. Build a map: data-index → clean node
|
|
166582
|
+
|
|
166583
|
+
const cleanItemMap = new Map();
|
|
166584
|
+
cleanItems.forEach(item => {
|
|
166585
|
+
const idx = item.dataset.index;
|
|
166586
|
+
if (idx !== undefined) cleanItemMap.set(idx, item);
|
|
166587
|
+
}); // 4. Reorder clean items to match newIndexOrder
|
|
166588
|
+
|
|
166589
|
+
const reorderedCleanItems = newIndexOrder.map(idx => cleanItemMap.get(idx)).filter(Boolean); // skip missing
|
|
166590
|
+
// 5. Serialize back to HTML string
|
|
166591
|
+
|
|
166592
|
+
const newCleanHtml = reorderedCleanItems.map(item => item.outerHTML).join(''); // 6. Update the clean source
|
|
166593
|
+
|
|
166594
|
+
if (pluginIsSortableRoot) {
|
|
166595
|
+
plugin.setAttribute('data-cb-original-content', newCleanHtml);
|
|
166596
|
+
} else {
|
|
166597
|
+
cleanGrid.innerHTML = newCleanHtml;
|
|
166598
|
+
const newHTML = doc.body.innerHTML;
|
|
166599
|
+
plugin.setAttribute('data-cb-original-content', newHTML);
|
|
166600
|
+
}
|
|
166601
|
+
}
|
|
166393
166602
|
|
|
166394
166603
|
addSection(html, contentCss) {
|
|
166395
166604
|
let newSection = this.addIdea(html);
|