@themarioga/grid-editor 6.0.0-beta.5 → 7.0.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.
- package/AUTO_SAVE.md +2 -2
- package/BUILDING.md +45 -29
- package/CHANGELOG.md +54 -0
- package/README.md +140 -89
- package/UPGRADING.md +146 -2
- package/dist/grideditor.bundle.min.js +14 -0
- package/dist/grideditor.d.ts +335 -0
- package/dist/grideditor.esm.js +3977 -0
- package/dist/grideditor.jquery.js +253 -0
- package/dist/grideditor.jquery.min.js +1 -0
- package/dist/grideditor.jquery.min.js.map +7 -0
- package/dist/grideditor.js +3983 -0
- package/dist/grideditor.min.js +6 -0
- package/dist/grideditor.min.js.map +7 -0
- package/dist/locales/grideditor.es.esm.js +158 -0
- package/dist/locales/grideditor.es.js +164 -170
- package/dist/locales/grideditor.es.min.js +6 -2
- package/dist/locales/grideditor.es.min.js.map +7 -1
- package/dist/plugins/grideditor.accordion.esm.js +294 -0
- package/dist/plugins/grideditor.accordion.js +286 -180
- package/dist/plugins/grideditor.accordion.min.js +1 -2
- package/dist/plugins/grideditor.accordion.min.js.map +7 -1
- package/dist/plugins/grideditor.alignment.esm.js +55 -0
- package/dist/plugins/grideditor.alignment.js +58 -77
- package/dist/plugins/grideditor.alignment.min.js +1 -2
- package/dist/plugins/grideditor.alignment.min.js.map +7 -1
- package/dist/plugins/grideditor.card.esm.js +73 -0
- package/dist/plugins/grideditor.card.js +74 -64
- package/dist/plugins/grideditor.card.min.js +1 -2
- package/dist/plugins/grideditor.card.min.js.map +7 -1
- package/dist/plugins/grideditor.ckeditor.esm.js +500 -0
- package/dist/plugins/grideditor.ckeditor.js +482 -493
- package/dist/plugins/grideditor.ckeditor.min.js +1 -2
- package/dist/plugins/grideditor.ckeditor.min.js.map +7 -1
- package/dist/plugins/grideditor.clipboard.esm.js +326 -0
- package/dist/plugins/grideditor.clipboard.js +298 -235
- package/dist/plugins/grideditor.clipboard.min.js +1 -2
- package/dist/plugins/grideditor.clipboard.min.js.map +7 -1
- package/dist/plugins/grideditor.codemirror-inline.esm.js +205 -0
- package/dist/plugins/grideditor.codemirror-inline.js +188 -168
- package/dist/plugins/grideditor.codemirror-inline.min.js +1 -2
- package/dist/plugins/grideditor.codemirror-inline.min.js.map +7 -1
- package/dist/plugins/grideditor.codemirror.esm.js +63 -0
- package/dist/plugins/grideditor.codemirror.js +60 -71
- package/dist/plugins/grideditor.codemirror.min.js +1 -2
- package/dist/plugins/grideditor.codemirror.min.js.map +7 -1
- package/dist/plugins/grideditor.elements.esm.js +271 -0
- package/dist/plugins/grideditor.elements.js +256 -149
- package/dist/plugins/grideditor.elements.min.js +1 -2
- package/dist/plugins/grideditor.elements.min.js.map +7 -1
- package/dist/plugins/grideditor.float.esm.js +34 -0
- package/dist/plugins/grideditor.float.js +37 -52
- package/dist/plugins/grideditor.float.min.js +1 -2
- package/dist/plugins/grideditor.float.min.js.map +7 -1
- package/dist/plugins/grideditor.gutters.esm.js +143 -0
- package/dist/plugins/grideditor.gutters.js +134 -131
- package/dist/plugins/grideditor.gutters.min.js +1 -2
- package/dist/plugins/grideditor.gutters.min.js.map +7 -1
- package/dist/plugins/grideditor.order.esm.js +189 -0
- package/dist/plugins/grideditor.order.js +170 -182
- package/dist/plugins/grideditor.order.min.js +1 -2
- package/dist/plugins/grideditor.order.min.js.map +7 -1
- package/dist/plugins/grideditor.popup.esm.js +187 -0
- package/dist/plugins/grideditor.popup.js +183 -134
- package/dist/plugins/grideditor.popup.min.js +1 -2
- package/dist/plugins/grideditor.popup.min.js.map +7 -1
- package/dist/plugins/grideditor.sections.esm.js +271 -0
- package/dist/plugins/grideditor.sections.js +250 -173
- package/dist/plugins/grideditor.sections.min.js +1 -2
- package/dist/plugins/grideditor.sections.min.js.map +7 -1
- package/dist/plugins/grideditor.spacing.esm.js +318 -0
- package/dist/plugins/grideditor.spacing.js +296 -272
- package/dist/plugins/grideditor.spacing.min.js +1 -2
- package/dist/plugins/grideditor.spacing.min.js.map +7 -1
- package/dist/plugins/grideditor.summernote.esm.js +509 -0
- package/dist/plugins/grideditor.summernote.js +491 -471
- package/dist/plugins/grideditor.summernote.min.js +1 -2
- package/dist/plugins/grideditor.summernote.min.js.map +7 -1
- package/dist/plugins/grideditor.tabs.esm.js +237 -0
- package/dist/plugins/grideditor.tabs.js +233 -139
- package/dist/plugins/grideditor.tabs.min.js +1 -2
- package/dist/plugins/grideditor.tabs.min.js.map +7 -1
- package/dist/plugins/grideditor.textalign.esm.js +40 -0
- package/dist/plugins/grideditor.textalign.js +43 -56
- package/dist/plugins/grideditor.textalign.min.js +1 -2
- package/dist/plugins/grideditor.textalign.min.js.map +7 -1
- package/dist/plugins/grideditor.tinymce.esm.js +519 -0
- package/dist/plugins/grideditor.tinymce.js +500 -534
- package/dist/plugins/grideditor.tinymce.min.js +1 -2
- package/dist/plugins/grideditor.tinymce.min.js.map +7 -1
- package/dist/plugins/grideditor.visibility.esm.js +158 -0
- package/dist/plugins/grideditor.visibility.js +140 -149
- package/dist/plugins/grideditor.visibility.min.js +1 -2
- package/dist/plugins/grideditor.visibility.min.js.map +7 -1
- package/docs/events.md +47 -21
- package/docs/locale-keys.md +7 -4
- package/docs/plugins.md +49 -27
- package/example/adapter.html +112 -0
- package/example/attributes.html +85 -61
- package/example/autocols.html +9 -9
- package/example/autosave.html +13 -14
- package/example/basic.html +4 -5
- package/example/breakpoints.html +5 -6
- package/example/ckeditor.html +4 -5
- package/example/clipboard.html +11 -10
- package/example/codemirror.html +9 -7
- package/example/containers.html +7 -8
- package/example/custom_editor.html +53 -34
- package/example/elements.html +10 -11
- package/example/index.html +16 -2
- package/example/locale.html +6 -7
- package/example/plugins.html +44 -29
- package/example/summernote.html +6 -5
- package/example/utilities.html +17 -13
- package/example/wrap_content.html +9 -9
- package/package.json +43 -12
- package/src/js/dom.js +401 -0
- package/src/js/grideditor.classic.js +16 -0
- package/src/js/grideditor.jquery.js +325 -0
- package/src/js/{jquery.grideditor.js → grideditor.js} +1284 -1124
- package/src/js/locales/grideditor.es.js +163 -158
- package/src/js/plugins/grideditor.accordion.js +97 -77
- package/src/js/plugins/grideditor.alignment.js +5 -7
- package/src/js/plugins/grideditor.card.js +23 -23
- package/src/js/plugins/grideditor.ckeditor.js +107 -106
- package/src/js/plugins/grideditor.clipboard.js +49 -37
- package/src/js/plugins/grideditor.codemirror-inline.js +50 -37
- package/src/js/plugins/grideditor.codemirror.js +9 -10
- package/src/js/plugins/grideditor.elements.js +57 -33
- package/src/js/plugins/grideditor.float.js +4 -6
- package/src/js/plugins/grideditor.gutters.js +20 -15
- package/src/js/plugins/grideditor.order.js +28 -25
- package/src/js/plugins/grideditor.popup.js +63 -51
- package/src/js/plugins/grideditor.sections.js +39 -32
- package/src/js/plugins/grideditor.spacing.js +42 -45
- package/src/js/plugins/grideditor.summernote.js +112 -76
- package/src/js/plugins/grideditor.tabs.js +65 -57
- package/src/js/plugins/grideditor.textalign.js +4 -6
- package/src/js/plugins/grideditor.tinymce.js +147 -139
- package/src/js/plugins/grideditor.visibility.js +24 -25
- package/src/js/register.js +18 -0
- package/src/js/text/grideditor.text.js +81 -106
- package/types/grideditor.d.ts +335 -0
- package/dist/jquery.grideditor.bundle.min.js +0 -10
- package/dist/jquery.grideditor.js +0 -4927
- package/dist/jquery.grideditor.min.js +0 -2
- package/dist/jquery.grideditor.min.js.map +0 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* What it can ask the editor for is the handle its factory is called with,
|
|
9
9
|
* described in docs/plugins.md.
|
|
10
10
|
*
|
|
11
|
-
* <script src="dist/
|
|
11
|
+
* <script src="dist/grideditor.min.js"></script>
|
|
12
12
|
* <script src="dist/plugins/grideditor.clipboard.min.js"></script>
|
|
13
13
|
*
|
|
14
14
|
* What is copied is kept in localStorage, so it survives a reload and can be
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* A paste is an add like any other - before-add-* and after-add-*, with
|
|
19
19
|
* `source: 'paste'` - so a host can turn one away.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
import { GridEditor } from '../grideditor.js';
|
|
22
|
+
import * as dom from '../dom.js';
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Object.assign(GridEditor.locales.en, {
|
|
24
25
|
'tool.copy': 'Copy',
|
|
25
26
|
'tool.paste': 'Paste',
|
|
26
27
|
'clipboard.paste_row': 'Paste row',
|
|
@@ -33,7 +34,6 @@ var VERSION = 1;
|
|
|
33
34
|
|
|
34
35
|
/** Where nothing can be stored, what was copied lives here, for this page. */
|
|
35
36
|
var memory = null;
|
|
36
|
-
var editors = 0;
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* What each drawer takes when something is pasted into it, by the kind of the
|
|
@@ -83,18 +83,23 @@ function write(clip) {
|
|
|
83
83
|
memory = clip;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
announce();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Every editor on the page looks at the clipboard again. */
|
|
90
|
+
function announce() {
|
|
91
|
+
document.dispatchEvent(new CustomEvent(CHANGE));
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
// Another tab copied something: every editor here looks again
|
|
90
|
-
|
|
91
|
-
if (e.
|
|
95
|
+
window.addEventListener('storage', function(e) {
|
|
96
|
+
if (e.key === STORAGE_ITEM) { announce(); }
|
|
92
97
|
});
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
GridEditor.features.clipboard = function(ge) {
|
|
95
100
|
|
|
96
|
-
var namespace = '.ge-clipboard-' + (++editors);
|
|
97
101
|
var shown = null; // What the toolbar's paste buttons stand for
|
|
102
|
+
var listening = false; // Whether refresh is on the document's change event
|
|
98
103
|
|
|
99
104
|
function used(name) {
|
|
100
105
|
return !ge.settings.plugins || ge.settings.plugins.indexOf(name) !== -1;
|
|
@@ -103,10 +108,10 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
103
108
|
/** A category this editor can take: the plugin that makes it is here. */
|
|
104
109
|
function available(clip) {
|
|
105
110
|
if (clip.category === 'container') {
|
|
106
|
-
return
|
|
111
|
+
return !!GridEditor.containers[clip.kind] && used(clip.kind);
|
|
107
112
|
}
|
|
108
|
-
if (clip.category === 'section') { return
|
|
109
|
-
if (clip.category === 'element') { return
|
|
113
|
+
if (clip.category === 'section') { return !!GridEditor.features.sections && used('sections'); }
|
|
114
|
+
if (clip.category === 'element') { return !!GridEditor.features.elements && used('elements'); }
|
|
110
115
|
|
|
111
116
|
return true;
|
|
112
117
|
}
|
|
@@ -116,7 +121,7 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
function categoryOf(kind) {
|
|
119
|
-
if (
|
|
124
|
+
if (GridEditor.containers[kind]) { return 'container'; }
|
|
120
125
|
|
|
121
126
|
return ['row', 'column', 'section', 'text', 'element'].indexOf(kind) !== -1 ? kind : null;
|
|
122
127
|
}
|
|
@@ -129,10 +134,15 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
129
134
|
|
|
130
135
|
// The canvas came back with new drawers: the one to flash is the
|
|
131
136
|
// node's new copy tool
|
|
132
|
-
var tool = ge.drawerOf(node)
|
|
133
|
-
tool
|
|
137
|
+
var tool = dom.child(ge.drawerOf(node), '.ge-copy');
|
|
138
|
+
if (!tool) { return; }
|
|
139
|
+
|
|
140
|
+
var icon = dom.one(tool, 'i');
|
|
141
|
+
dom.addClass(tool, 'ge-copied');
|
|
142
|
+
if (icon) { icon.setAttribute('class', 'bi bi-check2'); }
|
|
134
143
|
setTimeout(function() {
|
|
135
|
-
|
|
144
|
+
dom.removeClass(tool, 'ge-copied');
|
|
145
|
+
if (icon) { icon.setAttribute('class', 'bi bi-copy'); }
|
|
136
146
|
}, 1200);
|
|
137
147
|
}
|
|
138
148
|
|
|
@@ -148,9 +158,12 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
148
158
|
* them: two copies of a tab strip pointing at one set of panes is a tab
|
|
149
159
|
* strip that opens the other copy's tabs. An id the page does not have
|
|
150
160
|
* is kept, so pasting into another page changes nothing.
|
|
161
|
+
*
|
|
162
|
+
* Parsed the way innerHTML parses, so a <script> in what was copied is
|
|
163
|
+
* markup, pasted like the rest, and does not run in the editor.
|
|
151
164
|
*/
|
|
152
165
|
function fresh(html) {
|
|
153
|
-
var node =
|
|
166
|
+
var node = dom.create(html);
|
|
154
167
|
var renamed = {};
|
|
155
168
|
var taken = function(id) {
|
|
156
169
|
return !!document.getElementById(id) || Object.keys(renamed).some(function(old) {
|
|
@@ -158,8 +171,8 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
158
171
|
});
|
|
159
172
|
};
|
|
160
173
|
|
|
161
|
-
|
|
162
|
-
var id =
|
|
174
|
+
dom.selfAndAll(node, '[id]').forEach(function(element) {
|
|
175
|
+
var id = element.id;
|
|
163
176
|
if (!document.getElementById(id)) { return; }
|
|
164
177
|
|
|
165
178
|
var generated = GENERATED_ID.exec(id);
|
|
@@ -174,14 +187,12 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
174
187
|
}
|
|
175
188
|
|
|
176
189
|
renamed[id] = next;
|
|
177
|
-
|
|
190
|
+
element.id = next;
|
|
178
191
|
});
|
|
179
192
|
|
|
180
193
|
if (!Object.keys(renamed).length) { return node; }
|
|
181
194
|
|
|
182
|
-
|
|
183
|
-
var element = this;
|
|
184
|
-
|
|
195
|
+
dom.selfAndAll(node, '*').forEach(function(element) {
|
|
185
196
|
REFERENCES.forEach(function(name) {
|
|
186
197
|
var value = element.getAttribute(name);
|
|
187
198
|
if (value === null) { return; }
|
|
@@ -205,13 +216,13 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
205
216
|
function refresh() {
|
|
206
217
|
var clip = read();
|
|
207
218
|
|
|
208
|
-
ge.canvas
|
|
209
|
-
|
|
219
|
+
dom.all(ge.canvas, '.ge-paste').forEach(function(tool) {
|
|
220
|
+
dom.toggle(tool, fits(clip, tool.getAttribute('data-ge-paste').split(' ')));
|
|
210
221
|
});
|
|
211
222
|
|
|
212
|
-
ge.toolbarItems('clipboard').
|
|
213
|
-
var item = TOOLBAR[parseInt(
|
|
214
|
-
|
|
223
|
+
ge.toolbarItems('clipboard').forEach(function(button) {
|
|
224
|
+
var item = TOOLBAR[parseInt(button.getAttribute('data-ge-item'), 10)];
|
|
225
|
+
dom.toggle(button, fits(clip, [item.kind]));
|
|
215
226
|
});
|
|
216
227
|
|
|
217
228
|
shown = clip;
|
|
@@ -221,7 +232,7 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
221
232
|
{ kind: 'row', labelKey: 'clipboard.paste_row' },
|
|
222
233
|
{ kind: 'section', labelKey: 'clipboard.paste_section' },
|
|
223
234
|
].map(function(item) {
|
|
224
|
-
return
|
|
235
|
+
return Object.assign(item, {
|
|
225
236
|
iconClass: 'bi bi-clipboard-plus',
|
|
226
237
|
// On the right, as an icon: pasting is not one of the things
|
|
227
238
|
// the add buttons make
|
|
@@ -244,25 +255,26 @@ $.fn.gridEditor.features.clipboard = function(ge) {
|
|
|
244
255
|
var categories = TARGETS[kind];
|
|
245
256
|
if (!categories) { return; }
|
|
246
257
|
|
|
247
|
-
ge.createTool(drawer, ge.t('tool.paste'), 'ge-paste', 'bi bi-clipboard-plus', function() {
|
|
258
|
+
var tool = ge.createTool(drawer, ge.t('tool.paste'), 'ge-paste', 'bi bi-clipboard-plus', function() {
|
|
248
259
|
paste(node, categories);
|
|
249
260
|
});
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
.toggle(fits(read(), categories));
|
|
261
|
+
tool.setAttribute('data-ge-paste', categories.join(' '));
|
|
262
|
+
dom.toggle(tool, fits(read(), categories));
|
|
253
263
|
},
|
|
254
264
|
|
|
255
265
|
toolbar: TOOLBAR,
|
|
256
266
|
|
|
257
267
|
onInit: function() {
|
|
258
268
|
refresh();
|
|
259
|
-
|
|
269
|
+
if (!listening) {
|
|
270
|
+
document.addEventListener(CHANGE, refresh);
|
|
271
|
+
listening = true;
|
|
272
|
+
}
|
|
260
273
|
},
|
|
261
274
|
|
|
262
275
|
onDeinit: function() {
|
|
263
|
-
|
|
276
|
+
document.removeEventListener(CHANGE, refresh);
|
|
277
|
+
listening = false;
|
|
264
278
|
},
|
|
265
279
|
};
|
|
266
280
|
};
|
|
267
|
-
|
|
268
|
-
})(jQuery);
|
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
* <script src="codemirror/mode/javascript/javascript.js"></script>
|
|
17
17
|
* <script src="codemirror/mode/css/css.js"></script>
|
|
18
18
|
* <script src="codemirror/mode/htmlmixed/htmlmixed.js"></script>
|
|
19
|
-
* <script src="dist/
|
|
19
|
+
* <script src="dist/grideditor.min.js"></script>
|
|
20
20
|
* <script src="dist/plugins/grideditor.codemirror-inline.min.js"></script>
|
|
21
21
|
*
|
|
22
22
|
* Without CodeMirror on the page the html is edited in a plain textarea.
|
|
23
23
|
* CodeMirror's options are the codemirror plugin's, codemirror.config.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
import { GridEditor } from '../grideditor.js';
|
|
26
|
+
import * as dom from '../dom.js';
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
Object.assign(GridEditor.locales.en, {
|
|
28
29
|
'tool.edit_html': 'Edit html',
|
|
29
30
|
'codemirror.apply': 'Apply',
|
|
30
31
|
'codemirror.cancel': 'Cancel',
|
|
@@ -33,14 +34,14 @@ $.extend($.fn.gridEditor.locales.en, {
|
|
|
33
34
|
/** What has html of its own to edit: a pane's is split between its button and its body. */
|
|
34
35
|
var KINDS = ['row', 'column', 'text', 'plain', 'element', 'section'];
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
GridEditor.features['codemirror-inline'] = function(ge) {
|
|
37
38
|
|
|
38
39
|
var open = []; // The blocks being edited: { node, kind, from, wrapper, textarea, editor }
|
|
39
40
|
|
|
40
41
|
function options() {
|
|
41
42
|
var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};
|
|
42
43
|
|
|
43
|
-
return
|
|
44
|
+
return Object.assign({
|
|
44
45
|
mode: 'htmlmixed',
|
|
45
46
|
lineNumbers: true,
|
|
46
47
|
lineWrapping: true,
|
|
@@ -53,29 +54,29 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
53
54
|
|
|
54
55
|
/** What stands for the node in its column: a text's text block, or the node. */
|
|
55
56
|
function anchorOf(node) {
|
|
56
|
-
var textBlock = node.
|
|
57
|
-
return textBlock
|
|
57
|
+
var textBlock = node.parentElement;
|
|
58
|
+
return dom.hasClass(textBlock, 'ge-text-block') ? textBlock : node;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
function entryOf(node) {
|
|
61
|
-
return open.filter(function(entry) { return entry.node
|
|
62
|
+
return open.filter(function(entry) { return entry.node === node; })[0] || null;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
function editable(node, kind) {
|
|
65
|
-
return KINDS.indexOf(kind) !== -1 ||
|
|
66
|
+
return KINDS.indexOf(kind) !== -1 || dom.is(node, '[data-ge-container]');
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
/** The editor where the block was, the block hidden behind it. */
|
|
69
70
|
function show(entry) {
|
|
70
|
-
var anchor = anchorOf(entry.node)
|
|
71
|
-
entry.wrapper
|
|
71
|
+
var anchor = dom.addClass(anchorOf(entry.node), 'ge-code-hidden');
|
|
72
|
+
dom.insertAfter(entry.wrapper, anchor);
|
|
72
73
|
if (entry.editor) { entry.editor.refresh(); }
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
function hide(entry) {
|
|
76
|
-
entry.wrapper.
|
|
77
|
-
anchorOf(entry.node)
|
|
78
|
-
entry.node
|
|
77
|
+
entry.wrapper.remove();
|
|
78
|
+
dom.removeClass(anchorOf(entry.node), 'ge-code-hidden');
|
|
79
|
+
dom.removeClass(entry.node, 'ge-code-hidden');
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
function close(entry) {
|
|
@@ -94,30 +95,33 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
94
95
|
// As getHtml gives it: no drawers, no editor open in it
|
|
95
96
|
from: ge.nodeHtml(node),
|
|
96
97
|
// A drawer, to the editor: never content, never a block to move
|
|
97
|
-
wrapper:
|
|
98
|
+
wrapper: dom.element('div', { 'class': 'ge-tools-drawer ge-code-inline' }),
|
|
98
99
|
editor: null,
|
|
99
100
|
};
|
|
100
|
-
entry.textarea =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
entry.textarea = entry.wrapper.appendChild(dom.element('textarea', { 'class': 'ge-code-inline-source' }));
|
|
102
|
+
entry.textarea.value = entry.from;
|
|
103
|
+
|
|
104
|
+
var bar = entry.wrapper.appendChild(dom.element('div', { 'class': 'ge-code-inline-bar' }));
|
|
105
|
+
var applyButton = bar.appendChild(dom.element('button', {
|
|
106
|
+
type: 'button',
|
|
107
|
+
'class': 'btn btn-sm btn-primary ge-code-apply',
|
|
108
|
+
}, ge.t('codemirror.apply')));
|
|
109
|
+
applyButton.addEventListener('click', function() { apply(entry); });
|
|
110
|
+
var cancelButton = bar.appendChild(dom.element('button', {
|
|
111
|
+
type: 'button',
|
|
112
|
+
'class': 'btn btn-sm btn-outline-secondary ge-code-cancel',
|
|
113
|
+
}, ge.t('codemirror.cancel')));
|
|
114
|
+
cancelButton.addEventListener('click', function() { close(entry); });
|
|
111
115
|
|
|
112
116
|
open.push(entry);
|
|
113
117
|
show(entry);
|
|
114
118
|
|
|
115
119
|
if (window.CodeMirror) {
|
|
116
|
-
entry.editor = window.CodeMirror.fromTextArea(entry.textarea
|
|
117
|
-
|
|
120
|
+
entry.editor = window.CodeMirror.fromTextArea(entry.textarea, options());
|
|
121
|
+
dom.addClass(entry.editor.getWrapperElement(), 'ge-code-editor');
|
|
118
122
|
entry.editor.focus();
|
|
119
123
|
} else {
|
|
120
|
-
entry.textarea.
|
|
124
|
+
entry.textarea.focus();
|
|
121
125
|
}
|
|
122
126
|
}
|
|
123
127
|
|
|
@@ -127,7 +131,7 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
127
131
|
* getHtml, so what was written is read as the editor reads any markup.
|
|
128
132
|
*/
|
|
129
133
|
function apply(entry) {
|
|
130
|
-
var to = entry.editor ? entry.editor.getValue() : entry.textarea.
|
|
134
|
+
var to = entry.editor ? entry.editor.getValue() : entry.textarea.value;
|
|
131
135
|
var payload = ge.payloadFor(entry.kind, entry.node, { source: 'tool', from: entry.from, to: to });
|
|
132
136
|
|
|
133
137
|
// Canceled, the editor stays open with what was written in it
|
|
@@ -135,15 +139,26 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
135
139
|
|
|
136
140
|
close(entry);
|
|
137
141
|
|
|
138
|
-
var instance = ge.canvas
|
|
142
|
+
var instance = GridEditor.get(ge.canvas);
|
|
139
143
|
instance.deinit();
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
// Parsed as innerHTML parses: a <script> written here is markup,
|
|
146
|
+
// and does not run in the editor
|
|
147
|
+
var made = dom.parse(to);
|
|
148
|
+
var parent = entry.node.parentElement;
|
|
149
|
+
entry.node.replaceWith.apply(entry.node, made);
|
|
143
150
|
|
|
144
151
|
instance.init();
|
|
145
152
|
|
|
146
|
-
|
|
153
|
+
// The node is the first element written, or none when only text was;
|
|
154
|
+
// `nodes` is every element written, which may be several
|
|
155
|
+
var written = made.filter(function(node) { return node.nodeType === 1; });
|
|
156
|
+
var first = written[0] || null;
|
|
157
|
+
|
|
158
|
+
ge.emit('after-edit-html', ge.payloadFor(entry.kind, first || entry.node, {
|
|
159
|
+
node: first,
|
|
160
|
+
nodes: written,
|
|
161
|
+
parent: first ? first.parentElement : parent,
|
|
147
162
|
source: 'tool',
|
|
148
163
|
from: entry.from,
|
|
149
164
|
to: to,
|
|
@@ -174,7 +189,7 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
174
189
|
|
|
175
190
|
onInit: function() {
|
|
176
191
|
open.slice().forEach(function(entry) {
|
|
177
|
-
if (
|
|
192
|
+
if (!dom.attached(entry.node)) {
|
|
178
193
|
if (entry.editor) { entry.editor.toTextArea(); }
|
|
179
194
|
entry.wrapper.remove();
|
|
180
195
|
open.splice(open.indexOf(entry), 1);
|
|
@@ -186,5 +201,3 @@ $.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
|
186
201
|
},
|
|
187
202
|
};
|
|
188
203
|
};
|
|
189
|
-
|
|
190
|
-
})(jQuery);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* <script src="codemirror/mode/javascript/javascript.js"></script>
|
|
14
14
|
* <script src="codemirror/mode/css/css.js"></script>
|
|
15
15
|
* <script src="codemirror/mode/htmlmixed/htmlmixed.js"></script>
|
|
16
|
-
* <script src="dist/
|
|
16
|
+
* <script src="dist/grideditor.min.js"></script>
|
|
17
17
|
* <script src="dist/plugins/grideditor.codemirror.min.js"></script>
|
|
18
18
|
*
|
|
19
19
|
* CodeMirror 5 rather than 6: 6 comes as ES modules only, for a bundler,
|
|
@@ -21,13 +21,14 @@
|
|
|
21
21
|
* CodeMirror on the page the source view is the textarea, as before, and
|
|
22
22
|
* the console says why.
|
|
23
23
|
*/
|
|
24
|
-
|
|
24
|
+
import { GridEditor } from '../grideditor.js';
|
|
25
|
+
import * as dom from '../dom.js';
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
Object.assign(GridEditor.locales.en, {
|
|
27
28
|
'error.codemirror_missing': 'CodeMirror not available! Make sure you loaded the CodeMirror js file; the source is edited in a plain textarea without it.',
|
|
28
29
|
});
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
GridEditor.features.codemirror = function(ge) {
|
|
31
32
|
|
|
32
33
|
var editor = null;
|
|
33
34
|
var warned = false;
|
|
@@ -35,7 +36,7 @@ $.fn.gridEditor.features.codemirror = function(ge) {
|
|
|
35
36
|
function options() {
|
|
36
37
|
var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};
|
|
37
38
|
|
|
38
|
-
return
|
|
39
|
+
return Object.assign({
|
|
39
40
|
mode: 'htmlmixed',
|
|
40
41
|
lineNumbers: true,
|
|
41
42
|
lineWrapping: true,
|
|
@@ -56,10 +57,10 @@ $.fn.gridEditor.features.codemirror = function(ge) {
|
|
|
56
57
|
return;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
var height =
|
|
60
|
+
var height = dom.outerHeight(textarea);
|
|
60
61
|
|
|
61
|
-
editor = window.CodeMirror.fromTextArea(textarea
|
|
62
|
-
|
|
62
|
+
editor = window.CodeMirror.fromTextArea(textarea, options());
|
|
63
|
+
dom.addClass(editor.getWrapperElement(), 'ge-code-editor');
|
|
63
64
|
editor.setSize(null, height);
|
|
64
65
|
editor.focus();
|
|
65
66
|
},
|
|
@@ -75,5 +76,3 @@ $.fn.gridEditor.features.codemirror = function(ge) {
|
|
|
75
76
|
},
|
|
76
77
|
};
|
|
77
78
|
};
|
|
78
|
-
|
|
79
|
-
})(jQuery);
|
|
@@ -6,16 +6,17 @@
|
|
|
6
6
|
* beside the texts, instead of rich text. What it can ask the editor for is
|
|
7
7
|
* the handle its factory is called with, described in docs/plugins.md.
|
|
8
8
|
*
|
|
9
|
-
* <script src="dist/
|
|
9
|
+
* <script src="dist/grideditor.min.js"></script>
|
|
10
10
|
* <script src="dist/plugins/grideditor.elements.min.js"></script>
|
|
11
11
|
*
|
|
12
12
|
* Up to 5.x an element lived inside a content area, among the text. Markup
|
|
13
13
|
* saved that way still loads: the editor takes each element out of the text
|
|
14
14
|
* it sits in, which is what `cuts` is for.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
import { GridEditor } from '../grideditor.js';
|
|
17
|
+
import * as dom from '../dom.js';
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Object.assign(GridEditor.locales.en, {
|
|
19
20
|
'tool.delete_element': 'Remove element',
|
|
20
21
|
'tool.element_info': 'Element: {name}',
|
|
21
22
|
'confirm.delete_element': 'Delete element?',
|
|
@@ -24,47 +25,49 @@ $.extend($.fn.gridEditor.locales.en, {
|
|
|
24
25
|
/** A column's children that are something else than an element, whatever elements.auto says. */
|
|
25
26
|
var NOT_ELEMENTS = '.row, .ge-content, .ge-text-block, [data-ge-container], .ge-tools-drawer, .ge-resize-handle';
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
GridEditor.features.elements = function(ge) {
|
|
28
29
|
|
|
29
30
|
var warnedIntoText = false;
|
|
30
31
|
|
|
31
32
|
function elementsEnabled() {
|
|
32
33
|
if (ge.settings.elements.enabled !== 'auto') { return !!ge.settings.elements.enabled; }
|
|
33
34
|
|
|
34
|
-
return ge.settings.elements.auto || ge.canvas.
|
|
35
|
+
return ge.settings.elements.auto || !!ge.canvas.querySelector(ge.settings.elements.selector);
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/** Whether a child of a column is an element. */
|
|
38
39
|
function isElement(node) {
|
|
39
40
|
return ge.settings.elements.auto
|
|
40
|
-
? !node.
|
|
41
|
-
: node.
|
|
41
|
+
? !node.matches(NOT_ELEMENTS)
|
|
42
|
+
: node.matches(ge.settings.elements.selector);
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function markElements() {
|
|
45
46
|
if (!elementsEnabled()) { return; }
|
|
46
47
|
|
|
47
|
-
ge.canvas
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
dom.all(ge.canvas, '.column').forEach(function(column) {
|
|
49
|
+
dom.children(column).forEach(function(element) {
|
|
50
|
+
if (!dom.hasClass(element, 'ge-element') && !isElement(element)) { return; }
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
dom.addClass(element, 'ge-element');
|
|
53
|
+
if (!dom.child(element, '.ge-tools-drawer')) { createElementControls(element); }
|
|
54
|
+
});
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
function unmarkElements() {
|
|
57
|
-
ge.canvas
|
|
58
|
-
|
|
59
|
+
dom.all(ge.canvas, '.ge-element').forEach(function(element) {
|
|
60
|
+
dom.removeClass(element, 'ge-element');
|
|
59
61
|
|
|
60
62
|
// A host element that had no class of its own should not come
|
|
61
63
|
// back from getHtml carrying an empty one
|
|
62
|
-
|
|
64
|
+
dom.dropEmptyClass(element);
|
|
63
65
|
});
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
function createElementControls(element) {
|
|
67
|
-
var drawer =
|
|
69
|
+
var drawer = dom.element('div', { 'class': 'ge-tools-drawer ge-element-drawer' });
|
|
70
|
+
element.insertBefore(drawer, element.firstChild);
|
|
68
71
|
|
|
69
72
|
ge.createMoveTool(drawer);
|
|
70
73
|
ge.createTool(drawer, ge.t('tool.element_info', { name: elementName(element) }),
|
|
@@ -78,18 +81,18 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
78
81
|
|
|
79
82
|
ge.createTool(drawer, ge.t('tool.delete_element'), 'ge-delete-element', 'bi bi-trash', function() {
|
|
80
83
|
ge.deleteNode('element', element, ge.t('confirm.delete_element'), function(removed) {
|
|
81
|
-
|
|
84
|
+
dom.shrinkAway(element, 300, removed);
|
|
82
85
|
});
|
|
83
86
|
});
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
function elementName(element) {
|
|
87
|
-
var type = element.
|
|
88
|
-
var label = element.
|
|
90
|
+
var type = element.getAttribute('data-ge-element');
|
|
91
|
+
var label = element.getAttribute('data-ge-label');
|
|
89
92
|
|
|
90
93
|
if (label && type) { return label + ' (' + type + ')'; }
|
|
91
94
|
|
|
92
|
-
return label || type || element
|
|
95
|
+
return label || type || element.tagName.toLowerCase();
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
/**
|
|
@@ -99,11 +102,11 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
99
102
|
* prependTo - with a word to the host.
|
|
100
103
|
*/
|
|
101
104
|
function placementBesideText(options) {
|
|
102
|
-
var placed =
|
|
105
|
+
var placed = Object.assign({}, options);
|
|
103
106
|
|
|
104
107
|
[['appendTo', 'insertAfter'], ['prependTo', 'insertBefore']].forEach(function(pair) {
|
|
105
|
-
var target = options[pair[0]] !== undefined ?
|
|
106
|
-
if (!target || !target.
|
|
108
|
+
var target = options[pair[0]] !== undefined ? nodeFrom(options[pair[0]]) : null;
|
|
109
|
+
if (!target || !target.matches('.ge-content')) { return; }
|
|
107
110
|
|
|
108
111
|
if (!warnedIntoText) {
|
|
109
112
|
warnedIntoText = true;
|
|
@@ -112,21 +115,44 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
delete placed[pair[0]];
|
|
115
|
-
placed[pair[1]] = target.
|
|
118
|
+
placed[pair[1]] = dom.hasClass(target.parentElement, 'ge-text-block') ? target.parentElement : target;
|
|
116
119
|
});
|
|
117
120
|
|
|
118
121
|
return placed;
|
|
119
122
|
}
|
|
120
123
|
|
|
124
|
+
/** A place a caller named: an element, or the first one a selector matches. */
|
|
125
|
+
function nodeFrom(node) {
|
|
126
|
+
if (typeof node === 'string') { return document.querySelector(node); }
|
|
127
|
+
return node && node.nodeType === 1 ? node : null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* What the element holds: html, which is parsed as innerHTML parses so
|
|
132
|
+
* no <script> in it runs, or a node, or a list of nodes.
|
|
133
|
+
*/
|
|
134
|
+
function fill(element, content) {
|
|
135
|
+
if (content === undefined || content === null) { return; }
|
|
136
|
+
|
|
137
|
+
if (typeof content === 'string') {
|
|
138
|
+
dom.parse(content).forEach(function(node) { element.appendChild(node); });
|
|
139
|
+
} else if (content.nodeType) {
|
|
140
|
+
element.appendChild(content);
|
|
141
|
+
} else if (typeof content.length === 'number') {
|
|
142
|
+
Array.prototype.slice.call(content).forEach(function(node) { element.appendChild(node); });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
121
146
|
function apiCreateElement(content, options) {
|
|
122
147
|
options = options || {};
|
|
123
148
|
|
|
124
|
-
var element =
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
;
|
|
149
|
+
var element = dom.element('div', {
|
|
150
|
+
'class': 'ge-element',
|
|
151
|
+
'data-ge-element': options.type || 'element',
|
|
152
|
+
});
|
|
153
|
+
fill(element, content);
|
|
128
154
|
if (options.label !== undefined) {
|
|
129
|
-
element.
|
|
155
|
+
element.setAttribute('data-ge-label', options.label);
|
|
130
156
|
}
|
|
131
157
|
|
|
132
158
|
return ge.place(element, 'element', placementBesideText(options));
|
|
@@ -139,7 +165,7 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
139
165
|
|
|
140
166
|
/** A node this plugin marked is an element, whatever else it is. */
|
|
141
167
|
kindOf: function(node) {
|
|
142
|
-
return
|
|
168
|
+
return dom.hasClass(node, 'ge-element') ? 'element' : null;
|
|
143
169
|
},
|
|
144
170
|
|
|
145
171
|
/**
|
|
@@ -156,7 +182,7 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
156
182
|
// containers - and only the columns
|
|
157
183
|
blocks: '.ge-element',
|
|
158
184
|
accepts: function(region, node) {
|
|
159
|
-
if (
|
|
185
|
+
if (dom.hasClass(node, 'ge-element')) { return dom.is(region, '.column'); }
|
|
160
186
|
|
|
161
187
|
return true;
|
|
162
188
|
},
|
|
@@ -165,5 +191,3 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
165
191
|
onDeinit: unmarkElements,
|
|
166
192
|
};
|
|
167
193
|
};
|
|
168
|
-
|
|
169
|
-
})(jQuery);
|