@themarioga/grid-editor 8.5.0 → 8.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +78 -4
  3. package/dist/grideditor.bundle.min.js +3 -3
  4. package/dist/grideditor.css +15 -4
  5. package/dist/grideditor.d.ts +59 -3
  6. package/dist/grideditor.esm.js +226 -38
  7. package/dist/grideditor.js +226 -38
  8. package/dist/grideditor.min.css +1 -1
  9. package/dist/grideditor.min.css.map +1 -1
  10. package/dist/grideditor.min.js +2 -2
  11. package/dist/grideditor.min.js.map +3 -3
  12. package/dist/locales/grideditor.es.esm.js +4 -0
  13. package/dist/locales/grideditor.es.js +4 -0
  14. package/dist/locales/grideditor.es.min.js +1 -1
  15. package/dist/locales/grideditor.es.min.js.map +2 -2
  16. package/dist/plugins/grideditor.accordion.esm.js +7 -0
  17. package/dist/plugins/grideditor.accordion.js +7 -0
  18. package/dist/plugins/grideditor.accordion.min.js +1 -1
  19. package/dist/plugins/grideditor.accordion.min.js.map +3 -3
  20. package/dist/plugins/grideditor.autosave.esm.js +309 -0
  21. package/dist/plugins/grideditor.autosave.js +316 -0
  22. package/dist/plugins/grideditor.autosave.min.js +1 -0
  23. package/dist/plugins/grideditor.autosave.min.js.map +7 -0
  24. package/dist/plugins/grideditor.card.esm.js +10 -0
  25. package/dist/plugins/grideditor.card.js +10 -0
  26. package/dist/plugins/grideditor.card.min.js +1 -1
  27. package/dist/plugins/grideditor.card.min.js.map +3 -3
  28. package/dist/plugins/grideditor.ckeditor.esm.js +29 -0
  29. package/dist/plugins/grideditor.ckeditor.js +29 -0
  30. package/dist/plugins/grideditor.ckeditor.min.js +1 -1
  31. package/dist/plugins/grideditor.ckeditor.min.js.map +3 -3
  32. package/dist/plugins/grideditor.clipboard.esm.js +3 -0
  33. package/dist/plugins/grideditor.clipboard.js +3 -0
  34. package/dist/plugins/grideditor.clipboard.min.js +1 -1
  35. package/dist/plugins/grideditor.clipboard.min.js.map +2 -2
  36. package/dist/plugins/grideditor.codemirror-inline.esm.js +11 -0
  37. package/dist/plugins/grideditor.codemirror-inline.js +11 -0
  38. package/dist/plugins/grideditor.codemirror-inline.min.js +1 -1
  39. package/dist/plugins/grideditor.codemirror-inline.min.js.map +3 -3
  40. package/dist/plugins/grideditor.elements.esm.js +6 -3
  41. package/dist/plugins/grideditor.elements.js +6 -3
  42. package/dist/plugins/grideditor.elements.min.js +1 -1
  43. package/dist/plugins/grideditor.elements.min.js.map +3 -3
  44. package/dist/plugins/grideditor.gutters.esm.js +5 -0
  45. package/dist/plugins/grideditor.gutters.js +5 -0
  46. package/dist/plugins/grideditor.gutters.min.js +1 -1
  47. package/dist/plugins/grideditor.gutters.min.js.map +3 -3
  48. package/dist/plugins/grideditor.inline-style.esm.js +18 -10
  49. package/dist/plugins/grideditor.inline-style.js +18 -10
  50. package/dist/plugins/grideditor.inline-style.min.js +3 -3
  51. package/dist/plugins/grideditor.inline-style.min.js.map +3 -3
  52. package/dist/plugins/grideditor.order.esm.js +5 -0
  53. package/dist/plugins/grideditor.order.js +5 -0
  54. package/dist/plugins/grideditor.order.min.js +1 -1
  55. package/dist/plugins/grideditor.order.min.js.map +3 -3
  56. package/dist/plugins/grideditor.popup.esm.js +17 -6
  57. package/dist/plugins/grideditor.popup.js +17 -6
  58. package/dist/plugins/grideditor.popup.min.js +1 -1
  59. package/dist/plugins/grideditor.popup.min.js.map +3 -3
  60. package/dist/plugins/grideditor.sections.esm.js +6 -3
  61. package/dist/plugins/grideditor.sections.js +6 -3
  62. package/dist/plugins/grideditor.sections.min.js +1 -1
  63. package/dist/plugins/grideditor.sections.min.js.map +3 -3
  64. package/dist/plugins/grideditor.summernote.esm.js +39 -0
  65. package/dist/plugins/grideditor.summernote.js +39 -0
  66. package/dist/plugins/grideditor.summernote.min.js +1 -1
  67. package/dist/plugins/grideditor.summernote.min.js.map +3 -3
  68. package/dist/plugins/grideditor.tabs.esm.js +7 -0
  69. package/dist/plugins/grideditor.tabs.js +7 -0
  70. package/dist/plugins/grideditor.tabs.min.js +1 -1
  71. package/dist/plugins/grideditor.tabs.min.js.map +3 -3
  72. package/dist/plugins/grideditor.tinymce.esm.js +31 -0
  73. package/dist/plugins/grideditor.tinymce.js +31 -0
  74. package/dist/plugins/grideditor.tinymce.min.js +1 -1
  75. package/dist/plugins/grideditor.tinymce.min.js.map +3 -3
  76. package/docs/events.md +8 -0
  77. package/docs/locale-keys.md +14 -0
  78. package/docs/plugins.md +86 -2
  79. package/example/autosave.html +39 -22
  80. package/example/index.html +1 -1
  81. package/example/plugins.html +10 -0
  82. package/package.json +1 -3
  83. package/src/js/grideditor.js +280 -30
  84. package/src/js/inline-style/display.js +4 -3
  85. package/src/js/inline-style/drawerflow.js +10 -5
  86. package/src/js/locales/grideditor.es.js +4 -0
  87. package/src/js/plugins/grideditor.accordion.js +6 -0
  88. package/src/js/plugins/grideditor.autosave.js +349 -0
  89. package/src/js/plugins/grideditor.card.js +6 -0
  90. package/src/js/plugins/grideditor.ckeditor.js +6 -0
  91. package/src/js/plugins/grideditor.clipboard.js +3 -0
  92. package/src/js/plugins/grideditor.codemirror-inline.js +7 -0
  93. package/src/js/plugins/grideditor.elements.js +4 -3
  94. package/src/js/plugins/grideditor.gutters.js +4 -0
  95. package/src/js/plugins/grideditor.inline-style.js +2 -0
  96. package/src/js/plugins/grideditor.order.js +4 -0
  97. package/src/js/plugins/grideditor.popup.js +15 -6
  98. package/src/js/plugins/grideditor.sections.js +4 -3
  99. package/src/js/plugins/grideditor.summernote.js +14 -0
  100. package/src/js/plugins/grideditor.tabs.js +6 -0
  101. package/src/js/plugins/grideditor.tinymce.js +8 -0
  102. package/src/js/text/grideditor.text.js +26 -0
  103. package/src/less/grideditor.less +16 -8
  104. package/types/grideditor.d.ts +59 -3
  105. package/AUTO_SAVE.md +0 -30
@@ -653,6 +653,7 @@
653
653
  var refitToolbar = function() {
654
654
  };
655
655
  var addButtons = [];
656
+ var shownToolbar = {};
656
657
  var toolbarGroup = null;
657
658
  var warnedHere = {};
658
659
  var sortables = [];
@@ -763,31 +764,53 @@
763
764
  whenConfirmed();
764
765
  return;
765
766
  }
766
- var Modal = modalLibrary();
767
- if (!Modal) {
768
- if (window.confirm(message)) {
767
+ confirmWith(message, { danger: true }, function(confirmed) {
768
+ if (confirmed) {
769
769
  whenConfirmed();
770
770
  }
771
+ });
772
+ }
773
+ function confirmWith(message, options, answer) {
774
+ options = options || {};
775
+ var Modal = modalLibrary();
776
+ if (!Modal) {
777
+ answer(window.confirm(message));
771
778
  return;
772
779
  }
773
780
  var modal = confirmModal();
774
781
  var confirmed = false;
782
+ var ok = one(modal, ".ge-confirm-ok");
783
+ if (pendingAnswer) {
784
+ pendingAnswer(null);
785
+ }
786
+ var settle = function(value) {
787
+ if (pendingAnswer !== settle) {
788
+ return;
789
+ }
790
+ pendingAnswer = null;
791
+ answer(value);
792
+ };
793
+ pendingAnswer = settle;
794
+ one(modal, ".modal-title").textContent = options.title || t("confirm.title");
795
+ one(modal, ".ge-confirm-cancel").textContent = options.cancel || t("confirm.cancel");
796
+ ok.textContent = options.ok || t("confirm.ok");
797
+ toggleClass(ok, "btn-danger", !!options.danger);
798
+ toggleClass(ok, "btn-primary", !options.danger);
775
799
  one(modal, ".ge-confirm-message").textContent = message;
776
- one(modal, ".ge-confirm-ok").onclick = function() {
800
+ ok.onclick = function() {
777
801
  confirmed = true;
778
802
  Modal.getInstance(modal).hide();
779
803
  };
780
804
  confirmHandlers.hidden = function() {
781
- if (confirmed) {
782
- whenConfirmed();
783
- }
805
+ settle(confirmed);
784
806
  };
785
807
  confirmHandlers.shown = function() {
786
- one(modal, ".ge-confirm-ok").focus();
808
+ ok.focus();
787
809
  };
788
810
  Modal.getOrCreateInstance(modal).show();
789
811
  }
790
812
  var confirmHandlers = { hidden: null, shown: null };
813
+ var pendingAnswer = null;
791
814
  function confirmModal() {
792
815
  if (confirmDialog) {
793
816
  return confirmDialog;
@@ -801,13 +824,14 @@
801
824
  one(confirmDialog, ".ge-confirm-cancel").textContent = t("confirm.cancel");
802
825
  one(confirmDialog, ".ge-confirm-ok").textContent = t("confirm.ok");
803
826
  trackModal(confirmDialog);
827
+ var asking = confirmDialog;
804
828
  confirmDialog.addEventListener("hidden.bs.modal", function() {
805
- if (confirmHandlers.hidden) {
829
+ if (asking === confirmDialog && confirmHandlers.hidden) {
806
830
  confirmHandlers.hidden();
807
831
  }
808
832
  });
809
833
  confirmDialog.addEventListener("shown.bs.modal", function() {
810
- if (confirmHandlers.shown) {
834
+ if (asking === confirmDialog && confirmHandlers.shown) {
811
835
  confirmHandlers.shown();
812
836
  }
813
837
  });
@@ -821,6 +845,9 @@
821
845
  confirmHandlers.shown = null;
822
846
  retireModal(confirmDialog);
823
847
  confirmDialog = null;
848
+ if (pendingAnswer) {
849
+ pendingAnswer(null);
850
+ }
824
851
  }
825
852
  function retireModal(panel) {
826
853
  var Modal = modalLibrary();
@@ -1115,7 +1142,7 @@
1115
1142
  settings.new_row_layouts.forEach(function(layout) {
1116
1143
  var grouped = !Array.isArray(layout);
1117
1144
  var btn = element("a", {
1118
- "class": "btn btn-sm btn-primary",
1145
+ "class": "btn btn-sm btn-light",
1119
1146
  title: grouped ? t("row.add_row_cols", { columns: layout.columns, counts: rowColsText(layout.row_cols) }) : t("row.add", { layout: layout.join("-") }),
1120
1147
  // What this button makes, in the markup rather than in
1121
1148
  // memory: a drag works on a clone of it
@@ -1150,7 +1177,7 @@
1150
1177
  Object.keys(CONTAINERS).forEach(function(type) {
1151
1178
  var definition = CONTAINERS[type];
1152
1179
  var button = labelButton(
1153
- element("a", { "class": "btn btn-sm btn-primary ge-add-container" }),
1180
+ element("a", { "class": "btn btn-sm btn-light ge-add-container" }),
1154
1181
  t(definition.labelKey),
1155
1182
  definition.iconClass
1156
1183
  );
@@ -1171,8 +1198,10 @@
1171
1198
  addButtons.push({ button, home: addContainerGroup, group: toolbarGroupOf(definition.group) || "content" });
1172
1199
  });
1173
1200
  var endItems = [];
1201
+ shownToolbar = {};
1174
1202
  Object.keys(FEATURES).forEach(function(name) {
1175
- (FEATURES[name].toolbar || []).forEach(function(item, index) {
1203
+ shownToolbar[name] = toolbarOf(FEATURES[name]);
1204
+ shownToolbar[name].forEach(function(item, index) {
1176
1205
  var button = featureButton(name, item, index);
1177
1206
  if (item.align === "end") {
1178
1207
  endItems.push(button);
@@ -1271,7 +1300,7 @@
1271
1300
  names.forEach(function(name) {
1272
1301
  var tab = tabs.appendChild(element("button", {
1273
1302
  type: "button",
1274
- "class": "btn btn-sm btn-outline-primary",
1303
+ "class": "btn btn-sm btn-outline-secondary",
1275
1304
  role: "tab",
1276
1305
  "data-ge-group": name
1277
1306
  }, groupLabel(name)));
@@ -1308,6 +1337,22 @@
1308
1337
  return !closest(entry.button, ".ge-toolbar-stash");
1309
1338
  });
1310
1339
  }
1340
+ function toolbarOf(feature) {
1341
+ var items = typeof feature.toolbar === "function" ? feature.toolbar() : feature.toolbar;
1342
+ return Array.isArray(items) ? items : [];
1343
+ }
1344
+ function refreshToolbar() {
1345
+ if (!mainControls || destroyed) {
1346
+ return;
1347
+ }
1348
+ var previewing = !!one(mainControls, ".gm-preview.active");
1349
+ removeMainControls();
1350
+ createMainControls();
1351
+ if (previewing) {
1352
+ addClass(one(mainControls, ".gm-preview"), "active btn-danger");
1353
+ }
1354
+ onScroll();
1355
+ }
1311
1356
  function removeMainControls() {
1312
1357
  if (toolbarLifetime) {
1313
1358
  toolbarLifetime.abort();
@@ -1320,7 +1365,7 @@
1320
1365
  mainControls.remove();
1321
1366
  }
1322
1367
  function createOverflowMenu(start) {
1323
- var more = create('<div class="ge-toolbar-more"><button type="button" class="btn btn-sm btn-primary"><i class="bi bi-three-dots"></i></button><div class="ge-toolbar-overflow"><div class="ge-addRowGroup btn-group"></div><div class="ge-addContainerGroup btn-group"></div></div></div>');
1368
+ var more = create('<div class="ge-toolbar-more"><button type="button" class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button><div class="ge-toolbar-overflow"><div class="ge-addRowGroup btn-group"></div><div class="ge-addContainerGroup btn-group"></div></div></div>');
1324
1369
  start.parentNode.insertBefore(more, start.nextSibling);
1325
1370
  var toggle2 = one(more, "button");
1326
1371
  var panel = one(more, ".ge-toolbar-overflow");
@@ -1411,7 +1456,8 @@
1411
1456
  function featureButton(name, item, index) {
1412
1457
  var iconClass = item.iconClass || (item.align === "end" ? "bi bi-plus" : null);
1413
1458
  var label = typeof item.label === "function" ? item.label() : item.label || t(item.labelKey);
1414
- var button = labelButton(element("a", { "class": "btn btn-sm btn-primary ge-add-container ge-add-feature" }), label, iconClass);
1459
+ var colour = item.align === "end" ? "btn-primary" : "btn-light";
1460
+ var button = labelButton(element("a", { "class": "btn btn-sm " + colour + " ge-add-container ge-add-feature" }), label, iconClass);
1415
1461
  addClass(button, item.className || "");
1416
1462
  attr(button, {
1417
1463
  "data-ge-toolbar": "feature",
@@ -1533,7 +1579,10 @@
1533
1579
  return { region, before };
1534
1580
  }
1535
1581
  function insertFeatureFromToolbar(button, where, source) {
1536
- var item = FEATURES[button.getAttribute("data-ge-feature")].toolbar[parseInt(button.getAttribute("data-ge-item"), 10)];
1582
+ var item = (shownToolbar[button.getAttribute("data-ge-feature")] || [])[parseInt(button.getAttribute("data-ge-item"), 10)];
1583
+ if (!item) {
1584
+ return null;
1585
+ }
1537
1586
  var made = item.create();
1538
1587
  if (!made) {
1539
1588
  return null;
@@ -1919,22 +1968,122 @@
1919
1968
  closeSizePicker();
1920
1969
  hideDropMarker();
1921
1970
  closeDialog();
1922
- all(canvas, ".ge-tools-drawer").forEach(function(drawer) {
1923
- drawer.remove();
1924
- });
1971
+ removeDrawers(canvas);
1925
1972
  pluginFields.clear();
1926
- unwrapTexts();
1973
+ unwrapTexts(canvas);
1927
1974
  plugins("onDeinit");
1928
1975
  clearPreviews(canvas);
1929
- all(canvas, "[data-ge-row-cols]").forEach(function(row) {
1930
- row.removeAttribute("data-ge-row-cols");
1931
- });
1976
+ clearRowCols(canvas);
1932
1977
  unmarkContainers();
1933
1978
  removeSortable();
1934
1979
  removeResizable();
1935
- runFilter(false);
1980
+ runFilter(false, canvas);
1981
+ }
1982
+ function removeDrawers(root) {
1983
+ all(root, ".ge-tools-drawer").forEach(function(drawer) {
1984
+ drawer.remove();
1985
+ });
1986
+ }
1987
+ function clearRowCols(root) {
1988
+ all(root, "[data-ge-row-cols]").forEach(function(row) {
1989
+ row.removeAttribute("data-ge-row-cols");
1990
+ });
1991
+ }
1992
+ function pluginsWithoutCleanMarkup() {
1993
+ var names = [];
1994
+ [CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
1995
+ Object.keys(registry).forEach(function(name) {
1996
+ var plugin = registry[name];
1997
+ var marks = plugin.unmark || plugin.onDeinit || plugin.onBeforeDeinit;
1998
+ if (marks && !plugin.cleanMarkup) {
1999
+ names.push(name);
2000
+ }
2001
+ });
2002
+ });
2003
+ return names;
2004
+ }
2005
+ function copyCanvas() {
2006
+ var copy = canvas.cloneNode(true);
2007
+ var toLive = /* @__PURE__ */ new Map();
2008
+ var toCopy = /* @__PURE__ */ new Map();
2009
+ var live = document.createTreeWalker(canvas, NodeFilter.SHOW_ELEMENT);
2010
+ var copied = document.createTreeWalker(copy, NodeFilter.SHOW_ELEMENT);
2011
+ var a = live.currentNode;
2012
+ var b = copied.currentNode;
2013
+ while (a && b) {
2014
+ toLive.set(b, a);
2015
+ toCopy.set(a, b);
2016
+ a = live.nextNode();
2017
+ b = copied.nextNode();
2018
+ }
2019
+ return {
2020
+ root: copy,
2021
+ liveOf: function(node) {
2022
+ return toLive.get(node) || null;
2023
+ },
2024
+ copyOf: function(node) {
2025
+ return toCopy.get(node) || null;
2026
+ }
2027
+ };
2028
+ }
2029
+ function snapshotHtml() {
2030
+ if (sourceOpen) {
2031
+ return getHtml();
2032
+ }
2033
+ var missing = pluginsWithoutCleanMarkup();
2034
+ if (missing.length) {
2035
+ missing.forEach(function(name) {
2036
+ warnOnceHere("snapshot:" + name, 'the "' + name + '" plugin has no cleanMarkup, so the canvas leaves editing to be read: open texts and settings panels close');
2037
+ });
2038
+ return getHtml();
2039
+ }
2040
+ var copy = copyCanvas();
2041
+ var root = copy.root;
2042
+ [root].concat(all(root, ".ge-active-target, .ge-settings-target")).forEach(function(node) {
2043
+ removeClass(node, "ge-active-target ge-settings-target");
2044
+ dropEmptyClass(node);
2045
+ });
2046
+ all(root, ".ge-drop-marker").forEach(function(marker) {
2047
+ marker.remove();
2048
+ });
2049
+ removeDrawers(root);
2050
+ unwrapTexts(root);
2051
+ var refused = null;
2052
+ [CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
2053
+ Object.keys(registry).forEach(function(name) {
2054
+ var plugin = registry[name];
2055
+ if (refused || !plugin.cleanMarkup) {
2056
+ return;
2057
+ }
2058
+ if (plugin.cleanMarkup(root, copy.liveOf) === false) {
2059
+ refused = name;
2060
+ }
2061
+ });
2062
+ });
2063
+ if (refused) {
2064
+ warnOnceHere("snapshot-refused:" + refused, 'the "' + refused + '" plugin cannot take its marking off a copy right now, so the canvas leaves editing to be read');
2065
+ return getHtml();
2066
+ }
2067
+ clearPreviews(root);
2068
+ clearRowCols(root);
2069
+ all(root, "[data-ge-container]").forEach(unmarkContainerClasses);
2070
+ sortables.forEach(function(sortableInstance) {
2071
+ var list = copy.copyOf(sortableInstance.el);
2072
+ if (list) {
2073
+ all(list, "[draggable]").forEach(function(node) {
2074
+ node.removeAttribute("draggable");
2075
+ });
2076
+ }
2077
+ });
2078
+ removeResizeFurniture(root);
2079
+ runFilter(false, root);
2080
+ stripPixelWidths(root);
2081
+ return root.innerHTML;
1936
2082
  }
1937
- function getHtml() {
2083
+ function getHtml(options) {
2084
+ if (options && options.keepEditing) {
2085
+ return snapshotHtml();
2086
+ }
1938
2087
  deinit();
1939
2088
  stripPixelWidths(canvas);
1940
2089
  var html = canvas.innerHTML;
@@ -1948,10 +2097,24 @@
1948
2097
  init();
1949
2098
  return html;
1950
2099
  }
1951
- function getPlainHtml() {
1952
- return plainHtml(getHtml());
2100
+ function getPlainHtml(options) {
2101
+ return plainHtml(getHtml(options));
2102
+ }
2103
+ function setHtml2(html) {
2104
+ if (sourceOpen) {
2105
+ closeSource();
2106
+ if (mainControls) {
2107
+ all(mainControls, ".gm-edit-mode").forEach(function(button) {
2108
+ removeClass(button, "active btn-danger");
2109
+ });
2110
+ }
2111
+ }
2112
+ deinit();
2113
+ setHtml(canvas, html);
2114
+ init();
1953
2115
  }
1954
2116
  function destroy() {
2117
+ plugins("onDestroy");
1955
2118
  if (sourceOpen) {
1956
2119
  closeSource();
1957
2120
  }
@@ -2064,6 +2227,11 @@
2064
2227
  closeDialog,
2065
2228
  rowFromLayout: rowFromLayoutValue,
2066
2229
  nodeHtml,
2230
+ // The markup as getHtml gives it, with the canvas left editing
2231
+ snapshotHtml,
2232
+ setHtml: setHtml2,
2233
+ // A question in the editor's confirm modal
2234
+ confirm: confirmWith,
2067
2235
  // A text editor has rewritten a content area, so whatever the
2068
2236
  // editor and its plugins had put in there goes back in
2069
2237
  textReady,
@@ -2076,6 +2244,8 @@
2076
2244
  // A node's drawer: its first child, or for a content area the
2077
2245
  // one beside it in its text block
2078
2246
  drawerOf,
2247
+ // The toolbar built again, from the plugins' toolbars as they are now
2248
+ refreshToolbar,
2079
2249
  toolbarItems: function(name) {
2080
2250
  return mainControls ? all(mainControls, '[data-ge-toolbar="feature"][data-ge-feature="' + name + '"]') : [];
2081
2251
  }
@@ -2586,10 +2756,13 @@
2586
2756
  if (definition) {
2587
2757
  definition.unmark(container);
2588
2758
  }
2589
- removeClass(container, "ge-container ge-container-" + containerTypeOf(container));
2590
- dropEmptyClass(container);
2759
+ unmarkContainerClasses(container);
2591
2760
  });
2592
2761
  }
2762
+ function unmarkContainerClasses(container) {
2763
+ removeClass(container, "ge-container ge-container-" + containerTypeOf(container));
2764
+ dropEmptyClass(container);
2765
+ }
2593
2766
  function prependDrawer(node, className) {
2594
2767
  var drawer = element("div", { "class": className });
2595
2768
  node.insertBefore(drawer, node.firstChild);
@@ -3990,13 +4163,16 @@
3990
4163
  on(handle, "pointerup pointercancel", onUp);
3991
4164
  }
3992
4165
  function removeResizable() {
3993
- all(canvas, ".ge-resize-handle").forEach(function(handle) {
4166
+ removeResizeFurniture(canvas);
4167
+ }
4168
+ function removeResizeFurniture(root) {
4169
+ all(root, ".ge-resize-handle").forEach(function(handle) {
3994
4170
  handle.remove();
3995
4171
  });
3996
- all(canvas, ".ge-resize-size").forEach(function(readout) {
4172
+ all(root, ".ge-resize-size").forEach(function(readout) {
3997
4173
  readout.remove();
3998
4174
  });
3999
- stripPixelWidths(canvas);
4175
+ stripPixelWidths(root);
4000
4176
  }
4001
4177
  function snapUnits(col, pixels) {
4002
4178
  var units = Math.round(pixels / rowContentWidth(col.parentElement) * MAX_COL_SIZE);
@@ -4204,7 +4380,7 @@
4204
4380
  setOffset(column, tier, wanted.offset);
4205
4381
  return column;
4206
4382
  }
4207
- function runFilter(isInit) {
4383
+ function runFilter(isInit, root) {
4208
4384
  if (!settings.custom_filter || !settings.custom_filter.length) {
4209
4385
  return;
4210
4386
  }
@@ -4213,7 +4389,7 @@
4213
4389
  if (typeof func == "string") {
4214
4390
  func = window[func];
4215
4391
  }
4216
- func(canvas, isInit);
4392
+ func(root || canvas, isInit);
4217
4393
  });
4218
4394
  }
4219
4395
  function textCutter() {
@@ -4333,8 +4509,8 @@
4333
4509
  }
4334
4510
  });
4335
4511
  }
4336
- function unwrapTexts() {
4337
- all(canvas, ".ge-text-block").forEach(function(textBlock) {
4512
+ function unwrapTexts(root) {
4513
+ all(root, ".ge-text-block").forEach(function(textBlock) {
4338
4514
  unwrap(textBlock);
4339
4515
  });
4340
4516
  }
@@ -4507,6 +4683,18 @@
4507
4683
  instances.set(canvas, instance);
4508
4684
  loadPlugins();
4509
4685
  instance.settings = settingsCopy();
4686
+ Object.keys(featureMethods).forEach(function(name) {
4687
+ if (Object.prototype.hasOwnProperty.call(own, name) || name in instance) {
4688
+ return;
4689
+ }
4690
+ instance[name] = function() {
4691
+ if (destroyed) {
4692
+ warnOnceHere("destroyed:" + name, t("warning.destroyed", { method: name }));
4693
+ return null;
4694
+ }
4695
+ return featureMethods[name].apply(null, arguments);
4696
+ };
4697
+ });
4510
4698
  setup();
4511
4699
  init();
4512
4700
  GridEditor._created.forEach(function(hook) {
@@ -4522,7 +4710,7 @@
4522
4710
  GridEditor._plainHtml = plainHtml;
4523
4711
  GridEditor.Sortable = null;
4524
4712
  GridEditor.bootstrap = null;
4525
- GridEditor.version = false ? "dev" : "8.5.0";
4713
+ GridEditor.version = false ? "dev" : "8.7.0";
4526
4714
  GridEditor.locales = {
4527
4715
  en: {
4528
4716
  "tool.move": "Move",