@themarioga/grid-editor 6.0.0 → 7.1.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 (147) hide show
  1. package/AUTO_SAVE.md +2 -2
  2. package/BUILDING.md +45 -29
  3. package/CHANGELOG.md +59 -0
  4. package/README.md +163 -87
  5. package/UPGRADING.md +119 -0
  6. package/dist/grideditor.bundle.min.js +14 -0
  7. package/dist/grideditor.d.ts +335 -0
  8. package/dist/grideditor.esm.js +3977 -0
  9. package/dist/grideditor.jquery.js +253 -0
  10. package/dist/grideditor.jquery.min.js +1 -0
  11. package/dist/grideditor.jquery.min.js.map +7 -0
  12. package/dist/grideditor.js +3983 -0
  13. package/dist/grideditor.min.js +6 -0
  14. package/dist/grideditor.min.js.map +7 -0
  15. package/dist/locales/grideditor.es.esm.js +158 -0
  16. package/dist/locales/grideditor.es.js +164 -168
  17. package/dist/locales/grideditor.es.min.js +6 -2
  18. package/dist/locales/grideditor.es.min.js.map +7 -1
  19. package/dist/plugins/grideditor.accordion.esm.js +294 -0
  20. package/dist/plugins/grideditor.accordion.js +286 -180
  21. package/dist/plugins/grideditor.accordion.min.js +1 -2
  22. package/dist/plugins/grideditor.accordion.min.js.map +7 -1
  23. package/dist/plugins/grideditor.alignment.esm.js +55 -0
  24. package/dist/plugins/grideditor.alignment.js +58 -77
  25. package/dist/plugins/grideditor.alignment.min.js +1 -2
  26. package/dist/plugins/grideditor.alignment.min.js.map +7 -1
  27. package/dist/plugins/grideditor.card.esm.js +73 -0
  28. package/dist/plugins/grideditor.card.js +74 -64
  29. package/dist/plugins/grideditor.card.min.js +1 -2
  30. package/dist/plugins/grideditor.card.min.js.map +7 -1
  31. package/dist/plugins/grideditor.ckeditor.esm.js +500 -0
  32. package/dist/plugins/grideditor.ckeditor.js +484 -449
  33. package/dist/plugins/grideditor.ckeditor.min.js +1 -2
  34. package/dist/plugins/grideditor.ckeditor.min.js.map +7 -1
  35. package/dist/plugins/grideditor.clipboard.esm.js +326 -0
  36. package/dist/plugins/grideditor.clipboard.js +298 -235
  37. package/dist/plugins/grideditor.clipboard.min.js +1 -2
  38. package/dist/plugins/grideditor.clipboard.min.js.map +7 -1
  39. package/dist/plugins/grideditor.codemirror-inline.esm.js +205 -0
  40. package/dist/plugins/grideditor.codemirror-inline.js +188 -168
  41. package/dist/plugins/grideditor.codemirror-inline.min.js +1 -2
  42. package/dist/plugins/grideditor.codemirror-inline.min.js.map +7 -1
  43. package/dist/plugins/grideditor.codemirror.esm.js +63 -0
  44. package/dist/plugins/grideditor.codemirror.js +60 -71
  45. package/dist/plugins/grideditor.codemirror.min.js +1 -2
  46. package/dist/plugins/grideditor.codemirror.min.js.map +7 -1
  47. package/dist/plugins/grideditor.elements.esm.js +271 -0
  48. package/dist/plugins/grideditor.elements.js +256 -149
  49. package/dist/plugins/grideditor.elements.min.js +1 -2
  50. package/dist/plugins/grideditor.elements.min.js.map +7 -1
  51. package/dist/plugins/grideditor.float.esm.js +34 -0
  52. package/dist/plugins/grideditor.float.js +37 -52
  53. package/dist/plugins/grideditor.float.min.js +1 -2
  54. package/dist/plugins/grideditor.float.min.js.map +7 -1
  55. package/dist/plugins/grideditor.gutters.esm.js +143 -0
  56. package/dist/plugins/grideditor.gutters.js +134 -131
  57. package/dist/plugins/grideditor.gutters.min.js +1 -2
  58. package/dist/plugins/grideditor.gutters.min.js.map +7 -1
  59. package/dist/plugins/grideditor.order.esm.js +189 -0
  60. package/dist/plugins/grideditor.order.js +170 -182
  61. package/dist/plugins/grideditor.order.min.js +1 -2
  62. package/dist/plugins/grideditor.order.min.js.map +7 -1
  63. package/dist/plugins/grideditor.popup.esm.js +187 -0
  64. package/dist/plugins/grideditor.popup.js +183 -134
  65. package/dist/plugins/grideditor.popup.min.js +1 -2
  66. package/dist/plugins/grideditor.popup.min.js.map +7 -1
  67. package/dist/plugins/grideditor.sections.esm.js +271 -0
  68. package/dist/plugins/grideditor.sections.js +250 -173
  69. package/dist/plugins/grideditor.sections.min.js +1 -2
  70. package/dist/plugins/grideditor.sections.min.js.map +7 -1
  71. package/dist/plugins/grideditor.spacing.esm.js +318 -0
  72. package/dist/plugins/grideditor.spacing.js +296 -272
  73. package/dist/plugins/grideditor.spacing.min.js +1 -2
  74. package/dist/plugins/grideditor.spacing.min.js.map +7 -1
  75. package/dist/plugins/grideditor.summernote.esm.js +509 -0
  76. package/dist/plugins/grideditor.summernote.js +493 -427
  77. package/dist/plugins/grideditor.summernote.min.js +1 -2
  78. package/dist/plugins/grideditor.summernote.min.js.map +7 -1
  79. package/dist/plugins/grideditor.tabs.esm.js +237 -0
  80. package/dist/plugins/grideditor.tabs.js +233 -139
  81. package/dist/plugins/grideditor.tabs.min.js +1 -2
  82. package/dist/plugins/grideditor.tabs.min.js.map +7 -1
  83. package/dist/plugins/grideditor.textalign.esm.js +40 -0
  84. package/dist/plugins/grideditor.textalign.js +43 -56
  85. package/dist/plugins/grideditor.textalign.min.js +1 -2
  86. package/dist/plugins/grideditor.textalign.min.js.map +7 -1
  87. package/dist/plugins/grideditor.tinymce.esm.js +519 -0
  88. package/dist/plugins/grideditor.tinymce.js +502 -490
  89. package/dist/plugins/grideditor.tinymce.min.js +1 -2
  90. package/dist/plugins/grideditor.tinymce.min.js.map +7 -1
  91. package/dist/plugins/grideditor.visibility.esm.js +158 -0
  92. package/dist/plugins/grideditor.visibility.js +140 -149
  93. package/dist/plugins/grideditor.visibility.min.js +1 -2
  94. package/dist/plugins/grideditor.visibility.min.js.map +7 -1
  95. package/docs/events.md +47 -21
  96. package/docs/locale-keys.md +6 -0
  97. package/docs/plugins.md +47 -25
  98. package/example/adapter.html +112 -0
  99. package/example/attributes.html +89 -62
  100. package/example/autocols.html +9 -9
  101. package/example/autosave.html +18 -16
  102. package/example/basic.html +8 -6
  103. package/example/breakpoints.html +5 -6
  104. package/example/ckeditor.html +4 -5
  105. package/example/clipboard.html +15 -11
  106. package/example/codemirror.html +13 -8
  107. package/example/containers.html +11 -9
  108. package/example/custom_editor.html +53 -34
  109. package/example/elements.html +14 -12
  110. package/example/index.html +16 -2
  111. package/example/locale.html +6 -7
  112. package/example/plugins.html +44 -29
  113. package/example/summernote.html +6 -5
  114. package/example/utilities.html +17 -13
  115. package/example/wrap_content.html +13 -10
  116. package/package.json +44 -12
  117. package/src/js/dom.js +401 -0
  118. package/src/js/grideditor.classic.js +16 -0
  119. package/src/js/grideditor.jquery.js +325 -0
  120. package/src/js/{jquery.grideditor.js → grideditor.js} +1284 -1124
  121. package/src/js/locales/grideditor.es.js +163 -156
  122. package/src/js/plugins/grideditor.accordion.js +97 -77
  123. package/src/js/plugins/grideditor.alignment.js +5 -7
  124. package/src/js/plugins/grideditor.card.js +23 -23
  125. package/src/js/plugins/grideditor.ckeditor.js +107 -106
  126. package/src/js/plugins/grideditor.clipboard.js +49 -37
  127. package/src/js/plugins/grideditor.codemirror-inline.js +50 -37
  128. package/src/js/plugins/grideditor.codemirror.js +9 -10
  129. package/src/js/plugins/grideditor.elements.js +57 -33
  130. package/src/js/plugins/grideditor.float.js +4 -6
  131. package/src/js/plugins/grideditor.gutters.js +20 -15
  132. package/src/js/plugins/grideditor.order.js +28 -25
  133. package/src/js/plugins/grideditor.popup.js +63 -51
  134. package/src/js/plugins/grideditor.sections.js +39 -32
  135. package/src/js/plugins/grideditor.spacing.js +42 -45
  136. package/src/js/plugins/grideditor.summernote.js +112 -76
  137. package/src/js/plugins/grideditor.tabs.js +65 -57
  138. package/src/js/plugins/grideditor.textalign.js +4 -6
  139. package/src/js/plugins/grideditor.tinymce.js +148 -140
  140. package/src/js/plugins/grideditor.visibility.js +24 -25
  141. package/src/js/register.js +18 -0
  142. package/src/js/text/grideditor.text.js +77 -56
  143. package/types/grideditor.d.ts +335 -0
  144. package/dist/jquery.grideditor.bundle.min.js +0 -10
  145. package/dist/jquery.grideditor.js +0 -4927
  146. package/dist/jquery.grideditor.min.js +0 -2
  147. package/dist/jquery.grideditor.min.js.map +0 -1
@@ -1,172 +1,163 @@
1
- /**
2
- * Visibility for grid-editor.
3
- *
4
- * A utility plugin: load this file after the editor and every row, column,
5
- * element and container can be hidden at some breakpoints and shown at
6
- * others, with Bootstrap's d-{breakpoint}-none and d-{breakpoint}-block (or
7
- * -flex, for a row, which is a flex container and stops being a grid as a
8
- * block). What it can ask the editor for is the handle its factory is called
9
- * with, described in docs/plugins.md.
10
- *
11
- * <script src="dist/jquery.grideditor.min.js"></script>
12
- * <script src="dist/plugins/grideditor.visibility.min.js"></script>
13
- *
14
- * A hidden node is never hidden from the editor, which would leave nothing to
15
- * click to show it again. It stays on the canvas, faded and striped in a view
16
- * where it is hidden, and in the all view says at which breakpoints it is.
17
- *
18
- * utilities.visibility.drawer: false leaves the eye out of the drawers, and
19
- * the panel field is the only control.
20
- */
21
- (function($) {
22
-
23
- $.extend($.fn.gridEditor.locales.en, {
24
- 'utility.visibility': 'Visibility',
25
- 'utility.visibility_hidden': 'Hidden',
26
- 'utility.visibility_shown': 'Shown',
27
- 'tool.hide_in_view': 'Hide in this view',
28
- 'tool.show_in_view': 'Show in this view',
29
- 'badge.hidden_in': 'Hidden at {breakpoints}',
30
- });
31
-
32
- /** A node that carries any class of the family, at any breakpoint. */
33
- var CLASS_PATTERN = /(?:^|\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\s|$)/;
34
-
35
- var NODES = '.row, .column, .ge-content, .ge-element, [data-ge-container]';
36
-
37
- $.fn.gridEditor.utilities.visibility = function(ge) {
38
-
39
- var options = $.extend({ drawer: true }, ge.settings.utilities.visibility);
40
-
41
- /** What "shown" is written as on this kind of node. */
1
+ (() => {
2
+ // src/js/register.js
3
+ var GridEditor = window.GridEditor;
4
+ if (!GridEditor || typeof GridEditor.get !== "function") {
5
+ throw new Error("grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, its locales and grideditor.jquery.js");
6
+ }
7
+
8
+ // src/js/dom.js
9
+ function all(root, selector) {
10
+ return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];
11
+ }
12
+ function selfAndAll(root, selector) {
13
+ if (!root) {
14
+ return [];
15
+ }
16
+ var found = all(root, selector);
17
+ if (root.nodeType === 1 && root.matches(selector)) {
18
+ found.unshift(root);
19
+ }
20
+ return found;
21
+ }
22
+ function children(node, selector) {
23
+ if (!node) {
24
+ return [];
25
+ }
26
+ return Array.prototype.filter.call(node.children, function(each) {
27
+ return !selector || each.matches(selector);
28
+ });
29
+ }
30
+ function is(node, selector) {
31
+ return !!node && node.nodeType === 1 && node.matches(selector);
32
+ }
33
+ function removeClass(node, names) {
34
+ split(names).forEach(function(name) {
35
+ node.classList.remove(name);
36
+ });
37
+ return node;
38
+ }
39
+ function toggleClass(node, names, state) {
40
+ split(names).forEach(function(name) {
41
+ if (state === void 0) {
42
+ node.classList.toggle(name);
43
+ } else {
44
+ node.classList.toggle(name, !!state);
45
+ }
46
+ });
47
+ return node;
48
+ }
49
+ function split(names) {
50
+ return String(names || "").split(/\s+/).filter(Boolean);
51
+ }
52
+ function dropEmptyClass(node) {
53
+ if (!node.getAttribute("class")) {
54
+ node.removeAttribute("class");
55
+ }
56
+ return node;
57
+ }
58
+
59
+ // src/js/plugins/grideditor.visibility.js
60
+ Object.assign(GridEditor.locales.en, {
61
+ "utility.visibility": "Visibility",
62
+ "utility.visibility_hidden": "Hidden",
63
+ "utility.visibility_shown": "Shown",
64
+ "tool.hide_in_view": "Hide in this view",
65
+ "tool.show_in_view": "Show in this view",
66
+ "badge.hidden_in": "Hidden at {breakpoints}"
67
+ });
68
+ var CLASS_PATTERN = /(?:^|\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\s|$)/;
69
+ var NODES = ".row, .column, .ge-content, .ge-element, [data-ge-container]";
70
+ GridEditor.utilities.visibility = function(ge) {
71
+ var options = Object.assign({ drawer: true }, ge.settings.utilities.visibility);
42
72
  function shown(kind) {
43
- return kind === 'row' ? 'flex' : 'block';
73
+ return kind === "row" ? "flex" : "block";
44
74
  }
45
-
46
75
  function applies(node, kind) {
47
- return kind === 'row' || kind === 'column' || kind === 'element' || kind === 'text' || kind === 'plain' ||
48
- node.is('[data-ge-container]');
76
+ return kind === "row" || kind === "column" || kind === "element" || kind === "text" || kind === "plain" || is(node, "[data-ge-container]");
49
77
  }
50
-
51
78
  function hiddenAt(node, view) {
52
- return ge.getUtility(node, 'visibility', view) === 'none';
79
+ return ge.getUtility(node, "visibility", view) === "none";
53
80
  }
54
-
55
- /** The breakpoints at which the node is hidden, smallest first. */
56
81
  function hiddenTiers(node) {
57
- return ge.breakpoints.filter(function(key) { return hiddenAt(node, key); });
82
+ return ge.breakpoints.filter(function(key) {
83
+ return hiddenAt(node, key);
84
+ });
58
85
  }
59
-
60
- /**
61
- * Whether the node is hidden in the view being edited. In the all view
62
- * that means hidden at every breakpoint, since "hidden at some" is what
63
- * the badge is for.
64
- */
65
86
  function hiddenHere(node) {
66
- return ge.view() === 'all'
67
- ? hiddenTiers(node).length === ge.breakpoints.length
68
- : hiddenAt(node, ge.view());
87
+ return ge.view() === "all" ? hiddenTiers(node).length === ge.breakpoints.length : hiddenAt(node, ge.view());
69
88
  }
70
-
71
- /** What the breakpoint below the view shows, which an inherit falls back to. */
72
89
  function hiddenBelow(node) {
73
- var index = ge.breakpoints.indexOf(ge.view());
74
-
75
- return index > 0 && hiddenAt(node, ge.breakpoints[index - 1]);
90
+ var index = ge.breakpoints.indexOf(ge.view());
91
+ return index > 0 && hiddenAt(node, ge.breakpoints[index - 1]);
76
92
  }
77
-
78
- /**
79
- * Hide or show the node in the view being edited, with as few classes as
80
- * that takes. In a breakpoint view that is often none at all: showing a
81
- * node the breakpoint below shows removes this breakpoint's d-*-none
82
- * rather than writing a d-*-block on top of it. In the all view a node
83
- * is hidden everywhere or shown everywhere, and shown is no class.
84
- */
85
93
  function toggle(node, kind) {
86
- var hide = !hiddenHere(node);
87
- var value;
88
-
89
- if (ge.view() === 'all') {
90
- value = hide ? 'none' : null;
91
- } else if (hide) {
92
- value = hiddenBelow(node) ? null : 'none';
93
- } else {
94
- value = hiddenBelow(node) ? shown(kind) : null;
95
- }
96
-
97
- ge.setUtility(node, 'visibility', value, { source: 'tool' });
94
+ var hide = !hiddenHere(node);
95
+ var value;
96
+ if (ge.view() === "all") {
97
+ value = hide ? "none" : null;
98
+ } else if (hide) {
99
+ value = hiddenBelow(node) ? null : "none";
100
+ } else {
101
+ value = hiddenBelow(node) ? shown(kind) : null;
102
+ }
103
+ ge.setUtility(node, "visibility", value, { source: "tool" });
98
104
  }
99
-
100
- /**
101
- * The canvas shows each node as the view sees it. ge-visibility keeps a
102
- * node Bootstrap would hide on the canvas, ge-hidden-in-view fades it,
103
- * and data-ge-hidden-in carries the badge text for the all view.
104
- */
105
105
  function mark(scope) {
106
- scope.find(NODES).addBack(NODES).each(function() {
107
- var node = $(this);
108
- var kind = ge.kindOf(node);
109
- var carries = applies(node, kind) && CLASS_PATTERN.test(node.attr('class') || '');
110
- var tiers = carries ? hiddenTiers(node) : [];
111
- var here = carries && hiddenHere(node);
112
- var partly = carries && ge.view() === 'all' && tiers.length > 0 && !here;
113
-
114
- node.toggleClass('ge-visibility', carries).toggleClass('ge-hidden-in-view', here);
115
-
116
- if (partly) {
117
- node.attr('data-ge-hidden-in', ge.t('badge.hidden_in', { breakpoints: tiers.join(', ') }));
118
- } else {
119
- node.removeAttr('data-ge-hidden-in');
120
- }
121
-
122
- node.children('.ge-tools-drawer').children('.ge-visibility-tool').each(function() {
123
- $(this)
124
- .attr('title', here ? ge.t('tool.show_in_view') : ge.t('tool.hide_in_view'))
125
- .find('i').attr('class', here ? 'bi bi-eye-slash' : 'bi bi-eye');
106
+ selfAndAll(scope, NODES).forEach(function(node) {
107
+ var kind = ge.kindOf(node);
108
+ var carries = applies(node, kind) && CLASS_PATTERN.test(node.getAttribute("class") || "");
109
+ var tiers = carries ? hiddenTiers(node) : [];
110
+ var here = carries && hiddenHere(node);
111
+ var partly = carries && ge.view() === "all" && tiers.length > 0 && !here;
112
+ toggleClass(node, "ge-visibility", carries);
113
+ toggleClass(node, "ge-hidden-in-view", here);
114
+ if (partly) {
115
+ node.setAttribute("data-ge-hidden-in", ge.t("badge.hidden_in", { breakpoints: tiers.join(", ") }));
116
+ } else {
117
+ node.removeAttribute("data-ge-hidden-in");
118
+ }
119
+ children(node, ".ge-tools-drawer").forEach(function(drawer) {
120
+ children(drawer, ".ge-visibility-tool").forEach(function(tool) {
121
+ tool.setAttribute("title", here ? ge.t("tool.show_in_view") : ge.t("tool.hide_in_view"));
122
+ all(tool, "i").forEach(function(icon) {
123
+ icon.setAttribute("class", here ? "bi bi-eye-slash" : "bi bi-eye");
126
124
  });
125
+ });
127
126
  });
127
+ });
128
128
  }
129
-
130
129
  function unmark() {
131
- ge.canvas.find('.ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]').each(function() {
132
- var node = $(this)
133
- .removeClass('ge-visibility ge-hidden-in-view')
134
- .removeAttr('data-ge-hidden-in')
135
- ;
136
-
137
- if (!node.attr('class')) { node.removeAttr('class'); }
138
- });
130
+ all(ge.canvas, ".ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]").forEach(function(node) {
131
+ removeClass(node, "ge-visibility ge-hidden-in-view");
132
+ node.removeAttribute("data-ge-hidden-in");
133
+ dropEmptyClass(node);
134
+ });
139
135
  }
140
-
141
136
  return {
142
- families: [{
143
- name: 'visibility',
144
- prefix: 'd',
145
- values: ['none', 'block', 'flex'],
146
- appliesTo: ['row', 'column', 'text', 'element', 'container'],
147
- labelKey: 'utility.visibility',
148
-
149
- /** Hidden, or shown the way this kind of node is shown. */
150
- choices: function(node, kind) {
151
- return ['none', shown(kind)];
152
- },
153
-
154
- label: function(value) {
155
- return value === 'none' ? ge.t('utility.visibility_hidden') : ge.t('utility.visibility_shown');
156
- },
157
- }],
158
-
159
- drawerTools: function(drawer, node, kind) {
160
- if (!options.drawer || !applies(node, kind)) { return; }
161
-
162
- ge.createTool(drawer, ge.t('tool.hide_in_view'), 'ge-visibility-tool', 'bi bi-eye', function() {
163
- toggle(node, kind);
164
- });
137
+ families: [{
138
+ name: "visibility",
139
+ prefix: "d",
140
+ values: ["none", "block", "flex"],
141
+ appliesTo: ["row", "column", "text", "element", "container"],
142
+ labelKey: "utility.visibility",
143
+ /** Hidden, or shown the way this kind of node is shown. */
144
+ choices: function(node, kind) {
145
+ return ["none", shown(kind)];
165
146
  },
166
-
167
- onRefresh: mark,
168
- onDeinit: unmark,
147
+ label: function(value) {
148
+ return value === "none" ? ge.t("utility.visibility_hidden") : ge.t("utility.visibility_shown");
149
+ }
150
+ }],
151
+ drawerTools: function(drawer, node, kind) {
152
+ if (!options.drawer || !applies(node, kind)) {
153
+ return;
154
+ }
155
+ ge.createTool(drawer, ge.t("tool.hide_in_view"), "ge-visibility-tool", "bi bi-eye", function() {
156
+ toggle(node, kind);
157
+ });
158
+ },
159
+ onRefresh: mark,
160
+ onDeinit: unmark
169
161
  };
170
- };
171
-
172
- })(jQuery);
162
+ };
163
+ })();
@@ -1,2 +1 @@
1
- (c=>{c.extend(c.fn.gridEditor.locales.en,{"utility.visibility":"Visibility","utility.visibility_hidden":"Hidden","utility.visibility_shown":"Shown","tool.hide_in_view":"Hide in this view","tool.show_in_view":"Show in this view","badge.hidden_in":"Hidden at {breakpoints}"});var v=/(?:^|\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\s|$)/,n=".row, .column, .ge-content, .ge-element, [data-ge-container]";c.fn.gridEditor.utilities.visibility=function(o){var e=c.extend({drawer:!0},o.settings.utilities.visibility);function r(i){return"row"===i?"flex":"block"}function s(i,e){return"row"===e||"column"===e||"element"===e||"text"===e||"plain"===e||i.is("[data-ge-container]")}function t(i,e){return"none"===o.getUtility(i,"visibility",e)}function a(e){return o.breakpoints.filter(function(i){return t(e,i)})}function d(i){return"all"===o.view()?a(i).length===o.breakpoints.length:t(i,o.view())}function u(i){var e=o.breakpoints.indexOf(o.view());return 0<e&&t(i,o.breakpoints[e-1])}return{families:[{name:"visibility",prefix:"d",values:["none","block","flex"],appliesTo:["row","column","text","element","container"],labelKey:"utility.visibility",choices:function(i,e){return["none",r(e)]},label:function(i){return"none"===i?o.t("utility.visibility_hidden"):o.t("utility.visibility_shown")}}],drawerTools:function(i,n,l){e.drawer&&s(n,l)&&o.createTool(i,o.t("tool.hide_in_view"),"ge-visibility-tool","bi bi-eye",function(){var i,e,t;e=l,t=!d(i=n),t="all"===o.view()?t?"none":null:t?u(i)?null:"none":u(i)?r(e):null,o.setUtility(i,"visibility",t,{source:"tool"})})},onRefresh:function(i){i.find(n).addBack(n).each(function(){var i=c(this),e=s(i,o.kindOf(i))&&v.test(i.attr("class")||""),t=e?a(i):[],n=e&&d(i),l=e&&"all"===o.view()&&0<t.length&&!n;i.toggleClass("ge-visibility",e).toggleClass("ge-hidden-in-view",n),l?i.attr("data-ge-hidden-in",o.t("badge.hidden_in",{breakpoints:t.join(", ")})):i.removeAttr("data-ge-hidden-in"),i.children(".ge-tools-drawer").children(".ge-visibility-tool").each(function(){c(this).attr("title",n?o.t("tool.show_in_view"):o.t("tool.hide_in_view")).find("i").attr("class",n?"bi bi-eye-slash":"bi bi-eye")})})},onDeinit:function(){o.canvas.find(".ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]").each(function(){var i=c(this).removeClass("ge-visibility ge-hidden-in-view").removeAttr("data-ge-hidden-in");i.attr("class")||i.removeAttr("class")})}}}})(jQuery);
2
- //# sourceMappingURL=grideditor.visibility.min.js.map
1
+ (()=>{var a=window.GridEditor;if(!a||typeof a.get!="function")throw new Error("grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, its locales and grideditor.jquery.js");function s(t,n){return t?Array.prototype.slice.call(t.querySelectorAll(n)):[]}function x(t,n){if(!t)return[];var r=s(t,n);return t.nodeType===1&&t.matches(n)&&r.unshift(t),r}function p(t,n){return t?Array.prototype.filter.call(t.children,function(r){return!n||r.matches(n)}):[]}function b(t,n){return!!t&&t.nodeType===1&&t.matches(n)}function w(t,n){return E(n).forEach(function(r){t.classList.remove(r)}),t}function d(t,n,r){return E(n).forEach(function(u){r===void 0?t.classList.toggle(u):t.classList.toggle(u,!!r)}),t}function E(t){return String(t||"").split(/\s+/).filter(Boolean)}function A(t){return t.getAttribute("class")||t.removeAttribute("class"),t}Object.assign(a.locales.en,{"utility.visibility":"Visibility","utility.visibility_hidden":"Hidden","utility.visibility_shown":"Shown","tool.hide_in_view":"Hide in this view","tool.show_in_view":"Show in this view","badge.hidden_in":"Hidden at {breakpoints}"});var O=/(?:^|\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\s|$)/,H=".row, .column, .ge-content, .ge-element, [data-ge-container]";a.utilities.visibility=function(t){var n=Object.assign({drawer:!0},t.settings.utilities.visibility);function r(i){return i==="row"?"flex":"block"}function u(i,e){return e==="row"||e==="column"||e==="element"||e==="text"||e==="plain"||b(i,"[data-ge-container]")}function c(i,e){return t.getUtility(i,"visibility",e)==="none"}function h(i){return t.breakpoints.filter(function(e){return c(i,e)})}function v(i){return t.view()==="all"?h(i).length===t.breakpoints.length:c(i,t.view())}function m(i){var e=t.breakpoints.indexOf(t.view());return e>0&&c(i,t.breakpoints[e-1])}function T(i,e){var l=!v(i),o;t.view()==="all"?o=l?"none":null:l?o=m(i)?null:"none":o=m(i)?r(e):null,t.setUtility(i,"visibility",o,{source:"tool"})}function C(i){x(i,H).forEach(function(e){var l=t.kindOf(e),o=u(e,l)&&O.test(e.getAttribute("class")||""),g=o?h(e):[],f=o&&v(e),_=o&&t.view()==="all"&&g.length>0&&!f;d(e,"ge-visibility",o),d(e,"ge-hidden-in-view",f),_?e.setAttribute("data-ge-hidden-in",t.t("badge.hidden_in",{breakpoints:g.join(", ")})):e.removeAttribute("data-ge-hidden-in"),p(e,".ge-tools-drawer").forEach(function(B){p(B,".ge-visibility-tool").forEach(function(y){y.setAttribute("title",f?t.t("tool.show_in_view"):t.t("tool.hide_in_view")),s(y,"i").forEach(function(k){k.setAttribute("class",f?"bi bi-eye-slash":"bi bi-eye")})})})})}function S(){s(t.canvas,".ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]").forEach(function(i){w(i,"ge-visibility ge-hidden-in-view"),i.removeAttribute("data-ge-hidden-in"),A(i)})}return{families:[{name:"visibility",prefix:"d",values:["none","block","flex"],appliesTo:["row","column","text","element","container"],labelKey:"utility.visibility",choices:function(i,e){return["none",r(e)]},label:function(i){return i==="none"?t.t("utility.visibility_hidden"):t.t("utility.visibility_shown")}}],drawerTools:function(i,e,l){!n.drawer||!u(e,l)||t.createTool(i,t.t("tool.hide_in_view"),"ge-visibility-tool","bi bi-eye",function(){T(e,l)})},onRefresh:C,onDeinit:S}};})();
@@ -1 +1,7 @@
1
- {"version":3,"file":"grideditor.visibility.min.js","sources":["../../src/js/plugins/grideditor.visibility.js"],"names":["$","extend","fn","gridEditor","locales","en","utility.visibility","utility.visibility_hidden","utility.visibility_shown","tool.hide_in_view","tool.show_in_view","badge.hidden_in","CLASS_PATTERN","NODES","utilities","visibility","ge","options","drawer","settings","shown","kind","applies","node","is","hiddenAt","view","getUtility","hiddenTiers","breakpoints","filter","key","hiddenHere","length","hiddenBelow","index","indexOf","families","name","prefix","values","appliesTo","labelKey","choices","label","value","t","drawerTools","createTool","hide","setUtility","source","onRefresh","scope","find","addBack","each","this","carries","kindOf","test","attr","tiers","here","partly","toggleClass","join","removeAttr","children","onDeinit","canvas","removeClass","jQuery"],"mappings":"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"}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/js/register.js", "../../src/js/dom.js", "../../src/js/plugins/grideditor.visibility.js"],
4
+ "sourcesContent": ["/**\n * What a plugin's or a locale's classic script imports in place of the\n * editor: the GridEditor the page already loaded.\n *\n * The build points `import { GridEditor } from '../grideditor.js'` here for\n * the classic scripts, so each registers on the editor the page has rather\n * than bringing its own. Loaded before the editor there is nothing to\n * register on, and saying so is better than a TypeError three calls later.\n */\nvar GridEditor = window.GridEditor;\n\nif (!GridEditor || typeof GridEditor.get !== 'function') {\n throw new Error('grid-editor: load grideditor.js (or grideditor.bundle.min.js) before its plugins, ' +\n 'its locales and grideditor.jquery.js');\n}\n\nexport { GridEditor };\nexport default GridEditor;\n", "/**\n * The DOM, the way grid-editor uses it.\n *\n * Small helpers over the browser's own API, for the core and the shipped\n * plugins. Not a public API: a plugin of a host's own is free to write its\n * DOM code however it likes, and this file makes no promise to it.\n *\n * Stateless on purpose. The build puts a copy of this file in each plugin's\n * classic script, so anything kept here would be kept once per copy; a\n * module that needs to remember something about a node keeps its own\n * WeakMap.\n */\n\n/** Every element under `root` matching `selector`, as an array. */\nexport function all(root, selector) {\n return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];\n}\n\n/** The first element under `root` matching `selector`, or null. */\nexport function one(root, selector) {\n return root ? root.querySelector(selector) : null;\n}\n\n/** `root` itself when it matches, then every element under it that does. */\nexport function selfAndAll(root, selector) {\n if (!root) { return []; }\n\n var found = all(root, selector);\n if (root.nodeType === 1 && root.matches(selector)) { found.unshift(root); }\n return found;\n}\n\n/** The element children of `node`, those matching `selector` if one is given. */\nexport function children(node, selector) {\n if (!node) { return []; }\n\n return Array.prototype.filter.call(node.children, function(each) {\n return !selector || each.matches(selector);\n });\n}\n\n/** The first element child matching `selector`, or null. */\nexport function child(node, selector) {\n return children(node, selector)[0] || null;\n}\n\n/** The nearest ancestor-or-self matching `selector` below `stopAt`, or null. */\nexport function closest(node, selector, stopAt) {\n var found = node && node.nodeType === 1 ? node.closest(selector) : null;\n\n if (found && stopAt && found !== stopAt && !stopAt.contains(found)) { return null; }\n return found;\n}\n\n/** Whether `node` is an element matching `selector`. */\nexport function is(node, selector) {\n return !!node && node.nodeType === 1 && node.matches(selector);\n}\n\n/** Whether `node` is in the document. */\nexport function attached(node) {\n return !!node && document.documentElement.contains(node);\n}\n\n/** The element siblings after `node` that match `selector`. */\nexport function nextAll(node, selector) {\n var found = [];\n\n for (var next = node.nextElementSibling; next; next = next.nextElementSibling) {\n if (!selector || next.matches(selector)) { found.push(next); }\n }\n return found;\n}\n\n/** The ancestors of `node` up to, and not including, `stop`, nearest first. */\nexport function parentsUntil(node, stop) {\n var found = [];\n\n for (var parent = node.parentElement; parent && parent !== stop; parent = parent.parentElement) {\n found.push(parent);\n }\n return found;\n}\n\n/**\n * The nodes the html parses into, detached. Parsed the way innerHTML parses,\n * so a <script> in it never runs, here or once it is in the page.\n */\nexport function parse(html) {\n var template = document.createElement('template');\n template.innerHTML = html;\n return Array.prototype.slice.call(template.content.childNodes);\n}\n\n/** The one element the html is, detached. */\nexport function create(html) {\n var nodes = parse(html.trim());\n\n for (var i = 0; i < nodes.length; i++) {\n if (nodes[i].nodeType === 1) { return nodes[i]; }\n }\n return null;\n}\n\n/** An element of `tag`, with `attributes` and `text`. */\nexport function element(tag, attributes, text) {\n var node = document.createElement(tag);\n\n Object.keys(attributes || {}).forEach(function(name) {\n var value = attributes[name];\n if (value !== null && value !== undefined && value !== false) { node.setAttribute(name, value); }\n });\n if (text !== undefined && text !== null) { node.textContent = text; }\n\n return node;\n}\n\n/** Replace what `node` holds with `html`. A <script> in it does not run. */\nexport function setHtml(node, html) {\n node.innerHTML = html === undefined || html === null ? '' : String(html);\n return node;\n}\n\n/** Add one or several space separated classes. */\nexport function addClass(node, names) {\n split(names).forEach(function(name) { node.classList.add(name); });\n return node;\n}\n\nexport function removeClass(node, names) {\n split(names).forEach(function(name) { node.classList.remove(name); });\n return node;\n}\n\n/** Each class on, or off, or flipped when `on` is not given. */\nexport function toggleClass(node, names, state) {\n split(names).forEach(function(name) {\n if (state === undefined) {\n node.classList.toggle(name);\n } else {\n node.classList.toggle(name, !!state);\n }\n });\n return node;\n}\n\nexport function hasClass(node, name) {\n return !!node && node.nodeType === 1 && node.classList.contains(name);\n}\n\nfunction split(names) {\n return String(names || '').split(/\\s+/).filter(Boolean);\n}\n\n/** Take the class attribute off when there is nothing left in it. */\nexport function dropEmptyClass(node) {\n if (!node.getAttribute('class')) { node.removeAttribute('class'); }\n return node;\n}\n\n/** Take the style attribute off when there is nothing left in it. */\nexport function dropEmptyStyle(node) {\n if (!node.getAttribute('style')) { node.removeAttribute('style'); }\n return node;\n}\n\n/** Set attributes; a null or undefined value takes the attribute off. */\nexport function attr(node, attributes) {\n Object.keys(attributes).forEach(function(name) {\n var value = attributes[name];\n\n if (value === null || value === undefined) {\n node.removeAttribute(name);\n } else {\n node.setAttribute(name, value);\n }\n });\n return node;\n}\n\n/**\n * Inline styles, by css property name. A number is pixels for the properties\n * that take a length, as jQuery had it; an empty string takes one off.\n */\nexport function css(node, styles) {\n Object.keys(styles).forEach(function(property) {\n var value = styles[property];\n\n if (typeof value === 'number' && !UNITLESS[property]) { value = value + 'px'; }\n node.style.setProperty(property, value === null || value === undefined ? '' : String(value));\n });\n return node;\n}\n\nvar UNITLESS = { opacity: true, 'z-index': true, 'flex-grow': true, 'flex-shrink': true, order: true };\n\n/** What an element of this tag shows as when nothing hides it. */\nvar defaultDisplays = {};\n\nfunction defaultDisplay(node) {\n var tag = node.nodeName;\n\n if (!defaultDisplays[tag]) {\n var probe = document.body.appendChild(document.createElement(tag));\n defaultDisplays[tag] = getComputedStyle(probe).display;\n probe.remove();\n if (defaultDisplays[tag] === 'none') { defaultDisplays[tag] = 'block'; }\n }\n return defaultDisplays[tag];\n}\n\n/** Show a node: its inline display:none off, and a display of its own if a stylesheet hides it. */\nexport function show(node) {\n node.style.removeProperty('display');\n if (getComputedStyle(node).display === 'none') { node.style.display = defaultDisplay(node); }\n return node;\n}\n\nexport function hide(node) {\n node.style.display = 'none';\n return node;\n}\n\n/** Show or hide; flip when `on` is not given. */\nexport function toggle(node, state) {\n if (state === undefined) { state = !visible(node); }\n return state ? show(node) : hide(node);\n}\n\n/** Whether a node takes up room: what jQuery's :visible meant. */\nexport function visible(node) {\n return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);\n}\n\n/** The border box's width, fractions included. */\nexport function outerWidth(node) {\n return node.getBoundingClientRect().width;\n}\n\nexport function outerHeight(node) {\n return node.getBoundingClientRect().height;\n}\n\n/** The content box's height, which is what jQuery's height() gave. */\nexport function contentHeight(node) {\n var style = getComputedStyle(node);\n return node.clientHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);\n}\n\n/** Where a node is on the page, not in the window. */\nexport function offset(node) {\n var box = node.getBoundingClientRect();\n return { top: box.top + window.pageYOffset, left: box.left + window.pageXOffset };\n}\n\n/** Its index among its parent's element children, those matching `selector` if given. */\nexport function indexIn(node, selector) {\n return children(node.parentElement, selector).indexOf(node);\n}\n\n/** Put `node` right after `reference`. */\nexport function insertAfter(node, reference) {\n reference.parentNode.insertBefore(node, reference.nextSibling);\n return node;\n}\n\n/** Replace `node` with what it holds. */\nexport function unwrap(node) {\n var parent = node.parentNode;\n\n while (node.firstChild) { parent.insertBefore(node.firstChild, node); }\n node.remove();\n}\n\n/** Put `node` inside `wrapper`, where `node` was. */\nexport function wrap(node, wrapper) {\n node.parentNode.insertBefore(wrapper, node);\n wrapper.appendChild(node);\n return wrapper;\n}\n\n/**\n * Listen on `root` for `types` (space separated) on descendants that match\n * `selector`, with `this` the matched element, as jQuery's delegated\n * handlers had it. Hands back the listener, for removeEventListener; a\n * signal in `options` removes it too.\n */\nexport function delegate(root, types, selector, handler, options) {\n var listener = function(event) {\n var match = closest(event.target, selector, root);\n if (match && root.contains(match)) { return handler.call(match, event); }\n return undefined;\n };\n\n split(types).forEach(function(type) { root.addEventListener(type, listener, options); });\n return listener;\n}\n\n/** Listen for several space separated event types with one handler. */\nexport function on(target, types, handler, options) {\n split(types).forEach(function(type) { target.addEventListener(type, handler, options); });\n return handler;\n}\n\nexport function off(target, types, handler, options) {\n split(types).forEach(function(type) { target.removeEventListener(type, handler, options); });\n}\n\n/** A mouse event of `type` sent to `node`, the way a pointer would. */\nexport function fire(node, type) {\n node.dispatchEvent(new MouseEvent(type, { bubbles: type !== 'mouseenter' && type !== 'mouseleave' }));\n}\n\n/* ------------------------------------------------------------------\n * Taking a node away, visibly.\n *\n * The durations are the ones 6.x had through jQuery: 400 ms unless the\n * caller says otherwise. `done` runs once the node is out of sight, which is\n * when the caller removes it; a node that is already out of sight is done at\n * once, on the next task, as jQuery had it.\n * ------------------------------------------------------------------ */\n\nvar DEFAULT_DURATION = 400;\n\nfunction animateAway(node, frames, duration, done) {\n duration = duration === undefined ? DEFAULT_DURATION : duration;\n\n var finish = function() {\n hide(node);\n if (done) { done(); }\n };\n\n if (!visible(node) || !node.animate || duration <= 0) {\n window.setTimeout(finish, 0);\n return;\n }\n\n var animation = node.animate(frames(getComputedStyle(node)), {\n duration: duration,\n easing: 'ease-in-out',\n });\n var called = false;\n var once = function() {\n if (called) { return; }\n called = true;\n finish();\n };\n\n animation.onfinish = once;\n animation.oncancel = once;\n}\n\n/** Fold a node up to nothing, then hide it. */\nexport function slideUp(node, duration, done) {\n if (typeof duration === 'function') {\n done = duration;\n duration = undefined;\n }\n\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n return [\n {\n height: style.height,\n paddingTop: style.paddingTop,\n paddingBottom: style.paddingBottom,\n marginTop: style.marginTop,\n marginBottom: style.marginBottom,\n },\n { height: '0px', paddingTop: '0px', paddingBottom: '0px', marginTop: '0px', marginBottom: '0px' },\n ];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n\n/** Fade a node out, then hide it. */\nexport function fadeOut(node, duration, done) {\n animateAway(node, function(style) {\n return [{ opacity: style.opacity }, { opacity: 0 }];\n }, duration, done);\n}\n\n/** Fade and fold a node, in height and, with `width`, sideways too, then hide it. */\nexport function shrinkAway(node, duration, done, width) {\n node.style.overflow = 'hidden';\n animateAway(node, function(style) {\n var from = { opacity: style.opacity, height: style.height };\n var to = { opacity: 0, height: '0px' };\n\n if (width) {\n from.width = style.width;\n to.width = '0px';\n }\n return [from, to];\n }, duration, function() {\n node.style.removeProperty('overflow');\n if (done) { done(); }\n });\n}\n", "/**\n * Visibility for grid-editor.\n *\n * A utility plugin: load this file after the editor and every row, column,\n * element and container can be hidden at some breakpoints and shown at\n * others, with Bootstrap's d-{breakpoint}-none and d-{breakpoint}-block (or\n * -flex, for a row, which is a flex container and stops being a grid as a\n * block). What it can ask the editor for is the handle its factory is called\n * with, described in docs/plugins.md.\n *\n * <script src=\"dist/grideditor.min.js\"></script>\n * <script src=\"dist/plugins/grideditor.visibility.min.js\"></script>\n *\n * A hidden node is never hidden from the editor, which would leave nothing to\n * click to show it again. It stays on the canvas, faded and striped in a view\n * where it is hidden, and in the all view says at which breakpoints it is.\n *\n * utilities.visibility.drawer: false leaves the eye out of the drawers, and\n * the panel field is the only control.\n */\nimport { GridEditor } from '../grideditor.js';\nimport * as dom from '../dom.js';\n\nObject.assign(GridEditor.locales.en, {\n 'utility.visibility': 'Visibility',\n 'utility.visibility_hidden': 'Hidden',\n 'utility.visibility_shown': 'Shown',\n 'tool.hide_in_view': 'Hide in this view',\n 'tool.show_in_view': 'Show in this view',\n 'badge.hidden_in': 'Hidden at {breakpoints}',\n});\n\n/** A node that carries any class of the family, at any breakpoint. */\nvar CLASS_PATTERN = /(?:^|\\s)d-(?:(?:sm|md|lg|xl|xxl)-)?(?:none|block|flex)(?:\\s|$)/;\n\nvar NODES = '.row, .column, .ge-content, .ge-element, [data-ge-container]';\n\nGridEditor.utilities.visibility = function(ge) {\n\n var options = Object.assign({ drawer: true }, ge.settings.utilities.visibility);\n\n /** What \"shown\" is written as on this kind of node. */\n function shown(kind) {\n return kind === 'row' ? 'flex' : 'block';\n }\n\n function applies(node, kind) {\n return kind === 'row' || kind === 'column' || kind === 'element' || kind === 'text' || kind === 'plain' ||\n dom.is(node, '[data-ge-container]');\n }\n\n function hiddenAt(node, view) {\n return ge.getUtility(node, 'visibility', view) === 'none';\n }\n\n /** The breakpoints at which the node is hidden, smallest first. */\n function hiddenTiers(node) {\n return ge.breakpoints.filter(function(key) { return hiddenAt(node, key); });\n }\n\n /**\n * Whether the node is hidden in the view being edited. In the all view\n * that means hidden at every breakpoint, since \"hidden at some\" is what\n * the badge is for.\n */\n function hiddenHere(node) {\n return ge.view() === 'all'\n ? hiddenTiers(node).length === ge.breakpoints.length\n : hiddenAt(node, ge.view());\n }\n\n /** What the breakpoint below the view shows, which an inherit falls back to. */\n function hiddenBelow(node) {\n var index = ge.breakpoints.indexOf(ge.view());\n\n return index > 0 && hiddenAt(node, ge.breakpoints[index - 1]);\n }\n\n /**\n * Hide or show the node in the view being edited, with as few classes as\n * that takes. In a breakpoint view that is often none at all: showing a\n * node the breakpoint below shows removes this breakpoint's d-*-none\n * rather than writing a d-*-block on top of it. In the all view a node\n * is hidden everywhere or shown everywhere, and shown is no class.\n */\n function toggle(node, kind) {\n var hide = !hiddenHere(node);\n var value;\n\n if (ge.view() === 'all') {\n value = hide ? 'none' : null;\n } else if (hide) {\n value = hiddenBelow(node) ? null : 'none';\n } else {\n value = hiddenBelow(node) ? shown(kind) : null;\n }\n\n ge.setUtility(node, 'visibility', value, { source: 'tool' });\n }\n\n /**\n * The canvas shows each node as the view sees it. ge-visibility keeps a\n * node Bootstrap would hide on the canvas, ge-hidden-in-view fades it,\n * and data-ge-hidden-in carries the badge text for the all view.\n */\n function mark(scope) {\n dom.selfAndAll(scope, NODES).forEach(function(node) {\n var kind = ge.kindOf(node);\n var carries = applies(node, kind) && CLASS_PATTERN.test(node.getAttribute('class') || '');\n var tiers = carries ? hiddenTiers(node) : [];\n var here = carries && hiddenHere(node);\n var partly = carries && ge.view() === 'all' && tiers.length > 0 && !here;\n\n dom.toggleClass(node, 'ge-visibility', carries);\n dom.toggleClass(node, 'ge-hidden-in-view', here);\n\n if (partly) {\n node.setAttribute('data-ge-hidden-in', ge.t('badge.hidden_in', { breakpoints: tiers.join(', ') }));\n } else {\n node.removeAttribute('data-ge-hidden-in');\n }\n\n dom.children(node, '.ge-tools-drawer').forEach(function(drawer) {\n dom.children(drawer, '.ge-visibility-tool').forEach(function(tool) {\n tool.setAttribute('title', here ? ge.t('tool.show_in_view') : ge.t('tool.hide_in_view'));\n dom.all(tool, 'i').forEach(function(icon) {\n icon.setAttribute('class', here ? 'bi bi-eye-slash' : 'bi bi-eye');\n });\n });\n });\n });\n }\n\n function unmark() {\n dom.all(ge.canvas, '.ge-visibility, .ge-hidden-in-view, [data-ge-hidden-in]').forEach(function(node) {\n dom.removeClass(node, 'ge-visibility ge-hidden-in-view');\n node.removeAttribute('data-ge-hidden-in');\n dom.dropEmptyClass(node);\n });\n }\n\n return {\n families: [{\n name: 'visibility',\n prefix: 'd',\n values: ['none', 'block', 'flex'],\n appliesTo: ['row', 'column', 'text', 'element', 'container'],\n labelKey: 'utility.visibility',\n\n /** Hidden, or shown the way this kind of node is shown. */\n choices: function(node, kind) {\n return ['none', shown(kind)];\n },\n\n label: function(value) {\n return value === 'none' ? ge.t('utility.visibility_hidden') : ge.t('utility.visibility_shown');\n },\n }],\n\n drawerTools: function(drawer, node, kind) {\n if (!options.drawer || !applies(node, kind)) { return; }\n\n ge.createTool(drawer, ge.t('tool.hide_in_view'), 'ge-visibility-tool', 'bi bi-eye', function() {\n toggle(node, kind);\n });\n },\n\n onRefresh: mark,\n onDeinit: unmark,\n };\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["GridEditor", "all", "root", "selector", "selfAndAll", "root", "selector", "found", "all", "children", "node", "each", "is", "node", "selector", "removeClass", "node", "names", "split", "name", "toggleClass", "state", "split", "names", "dropEmptyClass", "node", "GridEditor", "CLASS_PATTERN", "NODES", "ge", "options", "shown", "kind", "applies", "node", "is", "hiddenAt", "view", "hiddenTiers", "key", "hiddenHere", "hiddenBelow", "index", "toggle", "hide", "value", "mark", "scope", "selfAndAll", "carries", "tiers", "here", "partly", "toggleClass", "children", "drawer", "tool", "all", "icon", "unmark", "removeClass", "dropEmptyClass"]
7
+ }
package/docs/events.md CHANGED
@@ -1,31 +1,56 @@
1
1
  grid-editor events
2
2
  ==================
3
3
 
4
- Every operation grid-editor performs is announced, twice: as a jQuery event on
4
+ Every operation grid-editor performs is announced, twice: as a DOM event on
5
5
  the canvas, and as a callback in the `callbacks` setting. The event is the
6
- primary mechanism — several listeners, namespacing, `off()` — and the callback
7
- is there for hosts that configure the plugin once, from generated or
8
- server-side code, and cannot easily bind.
6
+ primary mechanism — several listeners, `removeEventListener`, a listener on
7
+ an ancestor — and the callback is there for hosts that configure the editor
8
+ once, from generated or server-side code, and cannot easily bind.
9
9
 
10
10
  ```javascript
11
- // as events
12
- $('#myGrid').on('grideditor:before-add-row', function(e, payload) {
13
- if (payload.parent.hasClass('locked')) { e.preventDefault(); }
14
- });
15
-
16
- // as callbacks
17
- $('#myGrid').gridEditor({
11
+ var ge = new GridEditor('#myGrid', {
12
+ // as callbacks
18
13
  callbacks: {
19
- before_add_row: function(payload) { return !payload.parent.hasClass('locked'); },
14
+ before_add_row: function(payload) { return !payload.parent.classList.contains('locked'); },
20
15
  after_move: function(payload) { console.log(payload.from, payload.to); },
21
16
  },
22
17
  });
18
+
19
+ // as events
20
+ ge.canvas.addEventListener('grideditor:before-add-row', function(e) {
21
+ if (e.detail.parent.classList.contains('locked')) { e.preventDefault(); }
22
+ });
23
23
  ```
24
24
 
25
25
  A callback's name is its event name with `grideditor:` dropped and the dashes
26
26
  turned into underscores: `before-add-row` → `before_add_row`.
27
27
 
28
28
 
29
+ How an event is delivered
30
+ -------------------------
31
+
32
+ Each notification is a `CustomEvent` dispatched on the canvas, named
33
+ `grideditor:<name>`, with the payload as its `detail`. It bubbles, so a
34
+ listener on the document hears every editor on the page, and it is
35
+ cancelable: `preventDefault()` on a `before-*` is what cancels it (see
36
+ *Canceling* below). The events come in the order of *Ordering*, and every
37
+ listener and every callback hears each notification, whatever the ones before
38
+ it did.
39
+
40
+ A listener that throws is the browser's to report, as any listener's error
41
+ is: the other listeners, the callbacks and the operation go on. Up to 6.x an
42
+ error thrown in a jQuery handler stopped the operation where it was.
43
+
44
+ The payload's nodes are elements. Up to 6.x they were jQuery objects, and
45
+ they still are for a page that loads `grideditor.jquery.js`: through the
46
+ adapter, a jQuery listener - bound on the canvas or delegated from an
47
+ ancestor - runs once per notification with `(event, payload)`, the payload's
48
+ nodes wrapped, and `preventDefault()` on its event cancels as before. The
49
+ `callbacks` a page passes to `$(el).gridEditor()` get jQuery objects too.
50
+ Without the adapter, a jQuery listener is handed the DOM event alone, with
51
+ the payload in `event.originalEvent.detail`.
52
+
53
+
29
54
  The catalogue
30
55
  -------------
31
56
 
@@ -52,7 +77,7 @@ about every insertion can bind `grideditor:before-add` and switch on
52
77
  | `grideditor:before-convert` | — | yes | before the host's plain content is made a text, on a click, with the type chosen |
53
78
  | `grideditor:after-convert` | — | no | once the type is on it, before its editor has finished opening |
54
79
  | `grideditor:before-edit-html` | — | yes | with the codemirror-inline plugin, before a block's html is replaced with what was written; canceled, the editor stays open |
55
- | `grideditor:after-edit-html` | — | no | once it is, and the canvas is editing again; `node` is what was written, which may be several nodes or none |
80
+ | `grideditor:after-edit-html` | — | no | once it is, and the canvas is editing again; `node` is the first element written, or null when only text was, and `nodes` every element written |
56
81
  | `grideditor:before-delete` | — | yes | before any node is removed, whatever its kind |
57
82
  | `grideditor:after-delete` | — | no | after removal completes, animation included |
58
83
  | `grideditor:before-move` | — | yes | on drag start (see *Canceling*) |
@@ -81,15 +106,16 @@ The payload
81
106
  kind: 'row', // row | column | text | plain | element
82
107
  // tabs | accordion | popup | tab | accordion-item
83
108
  // section, with the sections plugin
84
- node: jQuery, // the node added, deleted, moved or resized
85
- parent: jQuery, // where it is going, or where it came from on a delete
86
- canvas: jQuery,
109
+ node: Element, // the node added, deleted, moved or resized
110
+ parent: Element, // where it is going, or where it came from on a delete;
111
+ // null for a node created detached, with no placement
112
+ canvas: Element,
87
113
  breakpoint: 'lg', // the view at the time: a breakpoint key, or 'all'
88
114
  source: 'tool', // tool | api | dragdrop | panel (a width chosen in the panel)
89
115
 
90
116
  // move only
91
- from: { parent: jQuery, index: 2 },
92
- to: { parent: jQuery, index: 0 },
117
+ from: { parent: Element, index: 2 },
118
+ to: { parent: Element, index: 0 },
93
119
 
94
120
  // resize and indent only: units, not pixels. A size can also be
95
121
  // 'equal' or 'auto', and null when the width field chose "inherit"
@@ -100,7 +126,7 @@ The payload
100
126
  ],
101
127
 
102
128
  // a pane inside a container
103
- container: jQuery,
129
+ container: Element,
104
130
 
105
131
  // convert only
106
132
  from: 'plain',
@@ -199,9 +225,9 @@ from inside a handler are queued and run when the operation that called them
199
225
  has finished, rather than rebuilding the canvas underneath it:
200
226
 
201
227
  ```javascript
202
- $('#myGrid').on('grideditor:after-add-row', function(e, payload) {
228
+ ge.canvas.addEventListener('grideditor:after-add-row', function(e) {
203
229
  // runs after this add has finished, not in the middle of it
204
- $('#myGrid').gridEditor('createRow', [6, 6], { appendTo: payload.canvas });
230
+ ge.createRow([6, 6], { appendTo: e.detail.canvas });
205
231
  });
206
232
  ```
207
233
 
@@ -295,6 +295,12 @@ all the same: the developer reading them is the one who chose the locale.
295
295
  | --- | --- | --- |
296
296
  | `error.sortable_missing` | SortableJS not available! … | Logged once when the drag library is not on the page |
297
297
  | `warning.setting_removed` | The {setting} setting was removed in 4.0. Use {replacement} instead. | Logged once per removed setting a host still passes |
298
+ | `warning.already_editing` | This element already has an editor: … | An editor asked for on an element that has one; the one it has is handed back |
299
+ | `warning.destroyed` | {method}() was called on an editor that has been destroyed, … | Logged once per method called on a destroyed editor |
300
+ | `warning.duplicate_build` | grideditor.js was loaded twice: … | A second copy of the classic script, which keeps the first `GridEditor` |
301
+ | `warning.plugin_6x` | The "{name}" plugin is written for grid-editor 6 … | `grideditor.jquery.js`: a plugin registered on `$.fn.gridEditor.*`, which is left out |
302
+ | `warning.adapter_no_jquery` | grideditor.jquery.js needs jQuery 4, … | `grideditor.jquery.js` loaded on a page with no jQuery |
303
+ | `warning.oninit_removed` | tinyMCE's oninit option was removed in 7.0 … | A `tinymce.config` that still has `oninit`; `init_instance_callback` is called |
298
304
  | `error.tinymce_missing` | tinyMCE not available! … | `content_types: ['tinymce']` with no tinyMCE loaded |
299
305
  | `error.ckeditor_missing` | CKEditor not available! … | `content_types: ['ckeditor']` with no CKEditor loaded |
300
306
  | `error.summernote_missing` | Summernote not available! … | `content_types: ['summernote']` with no Summernote loaded |