@themarioga/grid-editor 8.5.0 → 8.6.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/CHANGELOG.md +33 -0
- package/README.md +78 -4
- package/dist/grideditor.bundle.min.js +3 -3
- package/dist/grideditor.css +15 -4
- package/dist/grideditor.d.ts +59 -3
- package/dist/grideditor.esm.js +200 -36
- package/dist/grideditor.js +200 -36
- package/dist/grideditor.min.css +1 -1
- package/dist/grideditor.min.css.map +1 -1
- package/dist/grideditor.min.js +2 -2
- package/dist/grideditor.min.js.map +3 -3
- package/dist/locales/grideditor.es.esm.js +4 -0
- package/dist/locales/grideditor.es.js +4 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +2 -2
- package/dist/plugins/grideditor.accordion.esm.js +7 -0
- package/dist/plugins/grideditor.accordion.js +7 -0
- package/dist/plugins/grideditor.accordion.min.js +1 -1
- package/dist/plugins/grideditor.accordion.min.js.map +3 -3
- package/dist/plugins/grideditor.autosave.esm.js +309 -0
- package/dist/plugins/grideditor.autosave.js +316 -0
- package/dist/plugins/grideditor.autosave.min.js +1 -0
- package/dist/plugins/grideditor.autosave.min.js.map +7 -0
- package/dist/plugins/grideditor.card.esm.js +10 -0
- package/dist/plugins/grideditor.card.js +10 -0
- package/dist/plugins/grideditor.card.min.js +1 -1
- package/dist/plugins/grideditor.card.min.js.map +3 -3
- package/dist/plugins/grideditor.ckeditor.esm.js +29 -0
- package/dist/plugins/grideditor.ckeditor.js +29 -0
- package/dist/plugins/grideditor.ckeditor.min.js +1 -1
- package/dist/plugins/grideditor.ckeditor.min.js.map +3 -3
- package/dist/plugins/grideditor.clipboard.esm.js +3 -0
- package/dist/plugins/grideditor.clipboard.js +3 -0
- package/dist/plugins/grideditor.clipboard.min.js +1 -1
- package/dist/plugins/grideditor.clipboard.min.js.map +2 -2
- package/dist/plugins/grideditor.codemirror-inline.esm.js +11 -0
- package/dist/plugins/grideditor.codemirror-inline.js +11 -0
- package/dist/plugins/grideditor.codemirror-inline.min.js +1 -1
- package/dist/plugins/grideditor.codemirror-inline.min.js.map +3 -3
- package/dist/plugins/grideditor.elements.esm.js +6 -3
- package/dist/plugins/grideditor.elements.js +6 -3
- package/dist/plugins/grideditor.elements.min.js +1 -1
- package/dist/plugins/grideditor.elements.min.js.map +3 -3
- package/dist/plugins/grideditor.gutters.esm.js +5 -0
- package/dist/plugins/grideditor.gutters.js +5 -0
- package/dist/plugins/grideditor.gutters.min.js +1 -1
- package/dist/plugins/grideditor.gutters.min.js.map +3 -3
- package/dist/plugins/grideditor.inline-style.esm.js +18 -10
- package/dist/plugins/grideditor.inline-style.js +18 -10
- package/dist/plugins/grideditor.inline-style.min.js +3 -3
- package/dist/plugins/grideditor.inline-style.min.js.map +3 -3
- package/dist/plugins/grideditor.order.esm.js +5 -0
- package/dist/plugins/grideditor.order.js +5 -0
- package/dist/plugins/grideditor.order.min.js +1 -1
- package/dist/plugins/grideditor.order.min.js.map +3 -3
- package/dist/plugins/grideditor.popup.esm.js +17 -6
- package/dist/plugins/grideditor.popup.js +17 -6
- package/dist/plugins/grideditor.popup.min.js +1 -1
- package/dist/plugins/grideditor.popup.min.js.map +3 -3
- package/dist/plugins/grideditor.sections.esm.js +6 -3
- package/dist/plugins/grideditor.sections.js +6 -3
- package/dist/plugins/grideditor.sections.min.js +1 -1
- package/dist/plugins/grideditor.sections.min.js.map +3 -3
- package/dist/plugins/grideditor.summernote.esm.js +39 -0
- package/dist/plugins/grideditor.summernote.js +39 -0
- package/dist/plugins/grideditor.summernote.min.js +1 -1
- package/dist/plugins/grideditor.summernote.min.js.map +3 -3
- package/dist/plugins/grideditor.tabs.esm.js +7 -0
- package/dist/plugins/grideditor.tabs.js +7 -0
- package/dist/plugins/grideditor.tabs.min.js +1 -1
- package/dist/plugins/grideditor.tabs.min.js.map +3 -3
- package/dist/plugins/grideditor.tinymce.esm.js +31 -0
- package/dist/plugins/grideditor.tinymce.js +31 -0
- package/dist/plugins/grideditor.tinymce.min.js +1 -1
- package/dist/plugins/grideditor.tinymce.min.js.map +3 -3
- package/docs/events.md +8 -0
- package/docs/locale-keys.md +14 -0
- package/docs/plugins.md +54 -2
- package/example/autosave.html +39 -22
- package/example/index.html +1 -1
- package/example/plugins.html +10 -0
- package/package.json +1 -2
- package/src/js/grideditor.js +242 -28
- package/src/js/inline-style/display.js +4 -3
- package/src/js/inline-style/drawerflow.js +10 -5
- package/src/js/locales/grideditor.es.js +4 -0
- package/src/js/plugins/grideditor.accordion.js +6 -0
- package/src/js/plugins/grideditor.autosave.js +349 -0
- package/src/js/plugins/grideditor.card.js +6 -0
- package/src/js/plugins/grideditor.ckeditor.js +6 -0
- package/src/js/plugins/grideditor.clipboard.js +3 -0
- package/src/js/plugins/grideditor.codemirror-inline.js +7 -0
- package/src/js/plugins/grideditor.elements.js +4 -3
- package/src/js/plugins/grideditor.gutters.js +4 -0
- package/src/js/plugins/grideditor.inline-style.js +2 -0
- package/src/js/plugins/grideditor.order.js +4 -0
- package/src/js/plugins/grideditor.popup.js +15 -6
- package/src/js/plugins/grideditor.sections.js +4 -3
- package/src/js/plugins/grideditor.summernote.js +14 -0
- package/src/js/plugins/grideditor.tabs.js +6 -0
- package/src/js/plugins/grideditor.tinymce.js +8 -0
- package/src/js/text/grideditor.text.js +26 -0
- package/src/less/grideditor.less +16 -8
- package/types/grideditor.d.ts +59 -3
- package/AUTO_SAVE.md +0 -30
package/src/js/grideditor.js
CHANGED
|
@@ -628,30 +628,61 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
628
628
|
return;
|
|
629
629
|
}
|
|
630
630
|
|
|
631
|
+
confirmWith(message, { danger: true }, function(confirmed) {
|
|
632
|
+
if (confirmed) { whenConfirmed(); }
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* ge.confirm(): a question of a plugin's own, in the same modal.
|
|
638
|
+
* `answer` is called once: true for the ok button, false for cancel,
|
|
639
|
+
* the close button or Escape, and null when the question goes
|
|
640
|
+
* unanswered because the modal is taken away - setLocale, destroy, or
|
|
641
|
+
* another question asked over it.
|
|
642
|
+
*/
|
|
643
|
+
function confirmWith(message, options, answer) {
|
|
644
|
+
options = options || {};
|
|
631
645
|
var Modal = modalLibrary();
|
|
632
646
|
|
|
633
647
|
if (!Modal) {
|
|
634
|
-
|
|
648
|
+
answer(window.confirm(message));
|
|
635
649
|
return;
|
|
636
650
|
}
|
|
637
651
|
|
|
638
652
|
var modal = confirmModal();
|
|
639
653
|
var confirmed = false;
|
|
654
|
+
var ok = dom.one(modal, '.ge-confirm-ok');
|
|
655
|
+
|
|
656
|
+
// The question before this one, if it is still up, goes unanswered
|
|
657
|
+
if (pendingAnswer) { pendingAnswer(null); }
|
|
658
|
+
|
|
659
|
+
var settle = function(value) {
|
|
660
|
+
if (pendingAnswer !== settle) { return; }
|
|
661
|
+
pendingAnswer = null;
|
|
662
|
+
answer(value);
|
|
663
|
+
};
|
|
664
|
+
pendingAnswer = settle;
|
|
665
|
+
|
|
666
|
+
dom.one(modal, '.modal-title').textContent = options.title || t('confirm.title');
|
|
667
|
+
dom.one(modal, '.ge-confirm-cancel').textContent = options.cancel || t('confirm.cancel');
|
|
668
|
+
ok.textContent = options.ok || t('confirm.ok');
|
|
669
|
+
dom.toggleClass(ok, 'btn-danger', !!options.danger);
|
|
670
|
+
dom.toggleClass(ok, 'btn-primary', !options.danger);
|
|
640
671
|
|
|
641
672
|
dom.one(modal, '.ge-confirm-message').textContent = message;
|
|
642
|
-
|
|
673
|
+
ok.onclick = function() {
|
|
643
674
|
confirmed = true;
|
|
644
675
|
Modal.getInstance(modal).hide();
|
|
645
676
|
};
|
|
646
677
|
|
|
647
678
|
confirmHandlers.hidden = function() {
|
|
648
679
|
// After the modal is out of the way, so the backdrop is not
|
|
649
|
-
// sitting over the animation
|
|
650
|
-
|
|
680
|
+
// sitting over the animation a delete runs
|
|
681
|
+
settle(confirmed);
|
|
651
682
|
};
|
|
652
683
|
|
|
653
684
|
confirmHandlers.shown = function() {
|
|
654
|
-
|
|
685
|
+
ok.focus();
|
|
655
686
|
};
|
|
656
687
|
|
|
657
688
|
Modal.getOrCreateInstance(modal).show();
|
|
@@ -660,6 +691,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
660
691
|
// What the confirm modal does when Bootstrap says it is shown or
|
|
661
692
|
// hidden: this question's answer, replaced by the next question's
|
|
662
693
|
var confirmHandlers = { hidden: null, shown: null };
|
|
694
|
+
var pendingAnswer = null; // The open question's answer, until it is given
|
|
663
695
|
|
|
664
696
|
/** Built once per instance, and taken away again by destroy(). */
|
|
665
697
|
function confirmModal() {
|
|
@@ -690,11 +722,15 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
690
722
|
dom.one(confirmDialog, '.ge-confirm-ok').textContent = t('confirm.ok');
|
|
691
723
|
|
|
692
724
|
trackModal(confirmDialog);
|
|
725
|
+
// Only while it is the modal asking: one being taken away -
|
|
726
|
+
// setLocale builds another - finishes hiding after the next
|
|
727
|
+
// question is up, and that answer is not its to give
|
|
728
|
+
var asking = confirmDialog;
|
|
693
729
|
confirmDialog.addEventListener('hidden.bs.modal', function() {
|
|
694
|
-
if (confirmHandlers.hidden) { confirmHandlers.hidden(); }
|
|
730
|
+
if (asking === confirmDialog && confirmHandlers.hidden) { confirmHandlers.hidden(); }
|
|
695
731
|
});
|
|
696
732
|
confirmDialog.addEventListener('shown.bs.modal', function() {
|
|
697
|
-
if (confirmHandlers.shown) { confirmHandlers.shown(); }
|
|
733
|
+
if (asking === confirmDialog && confirmHandlers.shown) { confirmHandlers.shown(); }
|
|
698
734
|
});
|
|
699
735
|
|
|
700
736
|
return confirmDialog;
|
|
@@ -709,6 +745,9 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
709
745
|
confirmHandlers.shown = null;
|
|
710
746
|
retireModal(confirmDialog);
|
|
711
747
|
confirmDialog = null;
|
|
748
|
+
|
|
749
|
+
// A plugin's question goes unanswered, and the plugin is told so
|
|
750
|
+
if (pendingAnswer) { pendingAnswer(null); }
|
|
712
751
|
}
|
|
713
752
|
|
|
714
753
|
/**
|
|
@@ -1081,7 +1120,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1081
1120
|
settings.new_row_layouts.forEach(function(layout) {
|
|
1082
1121
|
var grouped = !Array.isArray(layout);
|
|
1083
1122
|
var btn = dom.element('a', {
|
|
1084
|
-
'class': 'btn btn-sm btn-
|
|
1123
|
+
'class': 'btn btn-sm btn-light',
|
|
1085
1124
|
title: grouped
|
|
1086
1125
|
? t('row.add_row_cols', { columns: layout.columns, counts: rowColsText(layout.row_cols) })
|
|
1087
1126
|
: t('row.add', { layout: layout.join('-') }),
|
|
@@ -1126,7 +1165,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1126
1165
|
// buttons next to these ones do
|
|
1127
1166
|
Object.keys(CONTAINERS).forEach(function(type) {
|
|
1128
1167
|
var definition = CONTAINERS[type];
|
|
1129
|
-
var button = labelButton(dom.element('a', { 'class': 'btn btn-sm btn-
|
|
1168
|
+
var button = labelButton(dom.element('a', { 'class': 'btn btn-sm btn-light ge-add-container' }),
|
|
1130
1169
|
t(definition.labelKey), definition.iconClass);
|
|
1131
1170
|
|
|
1132
1171
|
dom.attr(button, { 'data-ge-toolbar': 'container', 'data-ge-container-type': type });
|
|
@@ -1274,7 +1313,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1274
1313
|
names.forEach(function(name) {
|
|
1275
1314
|
var tab = tabs.appendChild(dom.element('button', {
|
|
1276
1315
|
type: 'button',
|
|
1277
|
-
'class': 'btn btn-sm btn-outline-
|
|
1316
|
+
'class': 'btn btn-sm btn-outline-secondary',
|
|
1278
1317
|
role: 'tab',
|
|
1279
1318
|
'data-ge-group': name,
|
|
1280
1319
|
}, groupLabel(name)));
|
|
@@ -1333,7 +1372,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1333
1372
|
*/
|
|
1334
1373
|
function createOverflowMenu(start) {
|
|
1335
1374
|
var more = dom.create('<div class="ge-toolbar-more">' +
|
|
1336
|
-
'<button type="button" class="btn btn-sm btn-
|
|
1375
|
+
'<button type="button" class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button>' +
|
|
1337
1376
|
'<div class="ge-toolbar-overflow">' +
|
|
1338
1377
|
'<div class="ge-addRowGroup btn-group"></div>' +
|
|
1339
1378
|
'<div class="ge-addContainerGroup btn-group"></div>' +
|
|
@@ -1442,7 +1481,10 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1442
1481
|
// A label of its own, worked out when the toolbar is built - and
|
|
1443
1482
|
// built again by setLocale - or the string its labelKey names
|
|
1444
1483
|
var label = typeof item.label === 'function' ? item.label() : (item.label || t(item.labelKey));
|
|
1445
|
-
|
|
1484
|
+
// Grey with the add buttons on the left, blue with the source and
|
|
1485
|
+
// preview buttons on the right
|
|
1486
|
+
var colour = item.align === 'end' ? 'btn-primary' : 'btn-light';
|
|
1487
|
+
var button = labelButton(dom.element('a', { 'class': 'btn btn-sm ' + colour + ' ge-add-container ge-add-feature' }), label, iconClass);
|
|
1446
1488
|
|
|
1447
1489
|
dom.addClass(button, item.className || '');
|
|
1448
1490
|
dom.attr(button, {
|
|
@@ -2090,26 +2132,144 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2090
2132
|
hideDropMarker();
|
|
2091
2133
|
// In case a dialog was opened with no settings panel open
|
|
2092
2134
|
closeDialog();
|
|
2093
|
-
|
|
2135
|
+
removeDrawers(canvas);
|
|
2094
2136
|
pluginFields.clear();
|
|
2095
|
-
unwrapTexts();
|
|
2137
|
+
unwrapTexts(canvas);
|
|
2096
2138
|
plugins('onDeinit');
|
|
2097
2139
|
// After the rich text editors have let go of their content areas:
|
|
2098
2140
|
// one that rebuilt its area's DOM brought the preview styles back
|
|
2099
2141
|
// with it, and the attribute recording them came back too
|
|
2100
2142
|
clearPreviews(canvas);
|
|
2101
|
-
|
|
2143
|
+
clearRowCols(canvas);
|
|
2102
2144
|
unmarkContainers();
|
|
2103
2145
|
removeSortable();
|
|
2104
2146
|
removeResizable();
|
|
2105
|
-
runFilter(false);
|
|
2147
|
+
runFilter(false, canvas);
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
function removeDrawers(root) {
|
|
2151
|
+
dom.all(root, '.ge-tools-drawer').forEach(function(drawer) { drawer.remove(); });
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
function clearRowCols(root) {
|
|
2155
|
+
dom.all(root, '[data-ge-row-cols]').forEach(function(row) { row.removeAttribute('data-ge-row-cols'); });
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
/**
|
|
2159
|
+
* The plugins that cannot be read without the canvas leaving editing:
|
|
2160
|
+
* the ones that put something on the canvas - an unmark, an onDeinit
|
|
2161
|
+
* or an onBeforeDeinit takes it off - and say nothing of how to take
|
|
2162
|
+
* it off a copy.
|
|
2163
|
+
*/
|
|
2164
|
+
function pluginsWithoutCleanMarkup() {
|
|
2165
|
+
var names = [];
|
|
2166
|
+
|
|
2167
|
+
[CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
|
|
2168
|
+
Object.keys(registry).forEach(function(name) {
|
|
2169
|
+
var plugin = registry[name];
|
|
2170
|
+
var marks = plugin.unmark || plugin.onDeinit || plugin.onBeforeDeinit;
|
|
2171
|
+
if (marks && !plugin.cleanMarkup) { names.push(name); }
|
|
2172
|
+
});
|
|
2173
|
+
});
|
|
2174
|
+
|
|
2175
|
+
return names;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
/**
|
|
2179
|
+
* A copy of the canvas, and the way from each of its elements back to
|
|
2180
|
+
* the one it was copied from. The two trees are walked side by side,
|
|
2181
|
+
* which works because a deep clone has the same shape.
|
|
2182
|
+
*/
|
|
2183
|
+
function copyCanvas() {
|
|
2184
|
+
var copy = canvas.cloneNode(true);
|
|
2185
|
+
var toLive = new Map();
|
|
2186
|
+
var toCopy = new Map();
|
|
2187
|
+
var live = document.createTreeWalker(canvas, NodeFilter.SHOW_ELEMENT);
|
|
2188
|
+
var copied = document.createTreeWalker(copy, NodeFilter.SHOW_ELEMENT);
|
|
2189
|
+
var a = live.currentNode;
|
|
2190
|
+
var b = copied.currentNode;
|
|
2191
|
+
|
|
2192
|
+
while (a && b) {
|
|
2193
|
+
toLive.set(b, a);
|
|
2194
|
+
toCopy.set(a, b);
|
|
2195
|
+
a = live.nextNode();
|
|
2196
|
+
b = copied.nextNode();
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
return {
|
|
2200
|
+
root: copy,
|
|
2201
|
+
liveOf: function(node) { return toLive.get(node) || null; },
|
|
2202
|
+
copyOf: function(node) { return toCopy.get(node) || null; },
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
/**
|
|
2207
|
+
* getHtml without the canvas leaving editing: what deinit takes off,
|
|
2208
|
+
* taken off a copy, so the text being typed into, the settings panel
|
|
2209
|
+
* and the focus are where they were. The same markup getHtml gives,
|
|
2210
|
+
* or getHtml itself - with a word, once - when a plugin can only take
|
|
2211
|
+
* its marking off the canvas, or will not this time.
|
|
2212
|
+
*/
|
|
2213
|
+
function snapshotHtml() {
|
|
2214
|
+
// Nothing is being edited to keep: the canvas is out of editing
|
|
2215
|
+
if (sourceOpen) { return getHtml(); }
|
|
2216
|
+
|
|
2217
|
+
var missing = pluginsWithoutCleanMarkup();
|
|
2218
|
+
if (missing.length) {
|
|
2219
|
+
missing.forEach(function(name) {
|
|
2220
|
+
warnOnceHere('snapshot:' + name, 'the "' + name + '" plugin has no cleanMarkup, so the canvas ' +
|
|
2221
|
+
'leaves editing to be read: open texts and settings panels close');
|
|
2222
|
+
});
|
|
2223
|
+
return getHtml();
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
var copy = copyCanvas();
|
|
2227
|
+
var root = copy.root;
|
|
2228
|
+
|
|
2229
|
+
[root].concat(dom.all(root, '.ge-active-target, .ge-settings-target')).forEach(function(node) {
|
|
2230
|
+
dom.removeClass(node, 'ge-active-target ge-settings-target');
|
|
2231
|
+
dom.dropEmptyClass(node);
|
|
2232
|
+
});
|
|
2233
|
+
dom.all(root, '.ge-drop-marker').forEach(function(marker) { marker.remove(); });
|
|
2234
|
+
removeDrawers(root);
|
|
2235
|
+
unwrapTexts(root);
|
|
2236
|
+
|
|
2237
|
+
var refused = null;
|
|
2238
|
+
[CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
|
|
2239
|
+
Object.keys(registry).forEach(function(name) {
|
|
2240
|
+
var plugin = registry[name];
|
|
2241
|
+
if (refused || !plugin.cleanMarkup) { return; }
|
|
2242
|
+
if (plugin.cleanMarkup(root, copy.liveOf) === false) { refused = name; }
|
|
2243
|
+
});
|
|
2244
|
+
});
|
|
2245
|
+
|
|
2246
|
+
if (refused) {
|
|
2247
|
+
warnOnceHere('snapshot-refused:' + refused, 'the "' + refused + '" plugin cannot take its marking off ' +
|
|
2248
|
+
'a copy right now, so the canvas leaves editing to be read');
|
|
2249
|
+
return getHtml();
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
clearPreviews(root);
|
|
2253
|
+
clearRowCols(root);
|
|
2254
|
+
dom.all(root, '[data-ge-container]').forEach(unmarkContainerClasses);
|
|
2255
|
+
sortables.forEach(function(sortableInstance) {
|
|
2256
|
+
var list = copy.copyOf(sortableInstance.el);
|
|
2257
|
+
if (list) { dom.all(list, '[draggable]').forEach(function(node) { node.removeAttribute('draggable'); }); }
|
|
2258
|
+
});
|
|
2259
|
+
removeResizeFurniture(root);
|
|
2260
|
+
runFilter(false, root);
|
|
2261
|
+
stripPixelWidths(root);
|
|
2262
|
+
|
|
2263
|
+
return root.innerHTML;
|
|
2106
2264
|
}
|
|
2107
2265
|
|
|
2108
2266
|
/**
|
|
2109
2267
|
* The markup as a host would save it: no drawers, no editor, no
|
|
2110
2268
|
* sortables. The canvas goes back to editing afterwards.
|
|
2111
2269
|
*/
|
|
2112
|
-
function getHtml() {
|
|
2270
|
+
function getHtml(options) {
|
|
2271
|
+
if (options && options.keepEditing) { return snapshotHtml(); }
|
|
2272
|
+
|
|
2113
2273
|
deinit();
|
|
2114
2274
|
stripPixelWidths(canvas);
|
|
2115
2275
|
var html = canvas.innerHTML;
|
|
@@ -2130,8 +2290,31 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2130
2290
|
}
|
|
2131
2291
|
|
|
2132
2292
|
/** getHtml with grid-editor's own classes and attributes taken off. */
|
|
2133
|
-
function getPlainHtml() {
|
|
2134
|
-
return plainHtml(getHtml());
|
|
2293
|
+
function getPlainHtml(options) {
|
|
2294
|
+
return plainHtml(getHtml(options));
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
/**
|
|
2298
|
+
* ge.setHtml(): the canvas made of other markup, and edited again. Not
|
|
2299
|
+
* an add or a delete of anything, so no events: what was there is
|
|
2300
|
+
* replaced as a whole. innerHTML, as the source view does, so a
|
|
2301
|
+
* <script> in it is markup and does not run in the editor.
|
|
2302
|
+
*/
|
|
2303
|
+
function setHtml(html) {
|
|
2304
|
+
// What is in the textarea is not wanted - html replaces it - but
|
|
2305
|
+
// the source view closes the one way it always does
|
|
2306
|
+
if (sourceOpen) {
|
|
2307
|
+
closeSource();
|
|
2308
|
+
if (mainControls) {
|
|
2309
|
+
dom.all(mainControls, '.gm-edit-mode').forEach(function(button) {
|
|
2310
|
+
dom.removeClass(button, 'active btn-danger');
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
deinit();
|
|
2316
|
+
dom.setHtml(canvas, html);
|
|
2317
|
+
init();
|
|
2135
2318
|
}
|
|
2136
2319
|
|
|
2137
2320
|
/**
|
|
@@ -2141,6 +2324,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2141
2324
|
* as a framework tearing a component down does.
|
|
2142
2325
|
*/
|
|
2143
2326
|
function destroy() {
|
|
2327
|
+
// First, while the editor is whole: a plugin may still read it
|
|
2328
|
+
plugins('onDestroy');
|
|
2144
2329
|
// The html being edited is what the canvas is left with
|
|
2145
2330
|
if (sourceOpen) { closeSource(); }
|
|
2146
2331
|
deinit();
|
|
@@ -2268,6 +2453,11 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2268
2453
|
closeDialog: closeDialog,
|
|
2269
2454
|
rowFromLayout: rowFromLayoutValue,
|
|
2270
2455
|
nodeHtml: nodeHtml,
|
|
2456
|
+
// The markup as getHtml gives it, with the canvas left editing
|
|
2457
|
+
snapshotHtml: snapshotHtml,
|
|
2458
|
+
setHtml: setHtml,
|
|
2459
|
+
// A question in the editor's confirm modal
|
|
2460
|
+
confirm: confirmWith,
|
|
2271
2461
|
// A text editor has rewritten a content area, so whatever the
|
|
2272
2462
|
// editor and its plugins had put in there goes back in
|
|
2273
2463
|
textReady: textReady,
|
|
@@ -2990,11 +3180,15 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2990
3180
|
|
|
2991
3181
|
if (definition) { definition.unmark(container); }
|
|
2992
3182
|
|
|
2993
|
-
|
|
2994
|
-
dom.dropEmptyClass(container);
|
|
3183
|
+
unmarkContainerClasses(container);
|
|
2995
3184
|
});
|
|
2996
3185
|
}
|
|
2997
3186
|
|
|
3187
|
+
function unmarkContainerClasses(container) {
|
|
3188
|
+
dom.removeClass(container, 'ge-container ge-container-' + containerTypeOf(container));
|
|
3189
|
+
dom.dropEmptyClass(container);
|
|
3190
|
+
}
|
|
3191
|
+
|
|
2998
3192
|
/** A new drawer as the first child of `node`. */
|
|
2999
3193
|
function prependDrawer(node, className) {
|
|
3000
3194
|
var drawer = dom.element('div', { 'class': className });
|
|
@@ -4923,10 +5117,14 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
4923
5117
|
}
|
|
4924
5118
|
|
|
4925
5119
|
function removeResizable() {
|
|
4926
|
-
|
|
5120
|
+
removeResizeFurniture(canvas);
|
|
5121
|
+
}
|
|
4927
5122
|
|
|
4928
|
-
|
|
4929
|
-
|
|
5123
|
+
function removeResizeFurniture(root) {
|
|
5124
|
+
dom.all(root, '.ge-resize-handle').forEach(function(handle) { handle.remove(); });
|
|
5125
|
+
|
|
5126
|
+
dom.all(root, '.ge-resize-size').forEach(function(readout) { readout.remove(); });
|
|
5127
|
+
stripPixelWidths(root);
|
|
4930
5128
|
}
|
|
4931
5129
|
|
|
4932
5130
|
/**
|
|
@@ -5252,7 +5450,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
5252
5450
|
* function, or the name of one on window, and gets the canvas and
|
|
5253
5451
|
* whether this is init.
|
|
5254
5452
|
*/
|
|
5255
|
-
function runFilter(isInit) {
|
|
5453
|
+
function runFilter(isInit, root) {
|
|
5256
5454
|
if (!settings.custom_filter || !settings.custom_filter.length) { return; }
|
|
5257
5455
|
|
|
5258
5456
|
var filters = typeof settings.custom_filter === 'string' || typeof settings.custom_filter === 'function'
|
|
@@ -5264,7 +5462,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
5264
5462
|
func = window[func];
|
|
5265
5463
|
}
|
|
5266
5464
|
|
|
5267
|
-
func(canvas, isInit);
|
|
5465
|
+
func(root || canvas, isInit);
|
|
5268
5466
|
});
|
|
5269
5467
|
}
|
|
5270
5468
|
|
|
@@ -5457,8 +5655,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
5457
5655
|
}
|
|
5458
5656
|
|
|
5459
5657
|
/** After the drawers are gone, so a wrapper holds its content area and nothing else. */
|
|
5460
|
-
function unwrapTexts() {
|
|
5461
|
-
dom.all(
|
|
5658
|
+
function unwrapTexts(root) {
|
|
5659
|
+
dom.all(root, '.ge-text-block').forEach(function(textBlock) {
|
|
5462
5660
|
dom.unwrap(textBlock);
|
|
5463
5661
|
});
|
|
5464
5662
|
}
|
|
@@ -5666,6 +5864,22 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
5666
5864
|
// Again, with what the plugins filled in: the text editors'
|
|
5667
5865
|
// content_types when the host gave none
|
|
5668
5866
|
instance.settings = settingsCopy();
|
|
5867
|
+
|
|
5868
|
+
// A feature plugin's methods that are not the editor's own documented
|
|
5869
|
+
// ones - the autosave plugin's - are the instance's too, while the
|
|
5870
|
+
// plugin is there
|
|
5871
|
+
Object.keys(featureMethods).forEach(function(name) {
|
|
5872
|
+
if (Object.prototype.hasOwnProperty.call(own, name) || name in instance) { return; }
|
|
5873
|
+
|
|
5874
|
+
instance[name] = function() {
|
|
5875
|
+
if (destroyed) {
|
|
5876
|
+
warnOnceHere('destroyed:' + name, t('warning.destroyed', { method: name }));
|
|
5877
|
+
return null;
|
|
5878
|
+
}
|
|
5879
|
+
|
|
5880
|
+
return featureMethods[name].apply(null, arguments);
|
|
5881
|
+
};
|
|
5882
|
+
});
|
|
5669
5883
|
setup();
|
|
5670
5884
|
init();
|
|
5671
5885
|
|
|
@@ -177,8 +177,8 @@ export function displayPart(ge, given) {
|
|
|
177
177
|
});
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
function unmark() {
|
|
181
|
-
dom.all(ge.canvas, '.ge-hidden-in-view, [data-ge-hidden-in], [' + SHOWN_ATTR + ']').forEach(function(node) {
|
|
180
|
+
function unmark(root) {
|
|
181
|
+
dom.all(root || ge.canvas, '.ge-hidden-in-view, [data-ge-hidden-in], [' + SHOWN_ATTR + ']').forEach(function(node) {
|
|
182
182
|
dom.removeClass(node, 'ge-hidden-in-view');
|
|
183
183
|
node.removeAttribute('data-ge-hidden-in');
|
|
184
184
|
node.removeAttribute(SHOWN_ATTR);
|
|
@@ -224,6 +224,7 @@ export function displayPart(ge, given) {
|
|
|
224
224
|
},
|
|
225
225
|
|
|
226
226
|
onRefresh: mark,
|
|
227
|
-
onDeinit: unmark,
|
|
227
|
+
onDeinit: function() { unmark(); },
|
|
228
|
+
cleanMarkup: unmark,
|
|
228
229
|
};
|
|
229
230
|
}
|
|
@@ -95,15 +95,19 @@ export function drawerflowPart(ge) {
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
observer = null;
|
|
101
|
-
|
|
102
|
-
dom.all(ge.canvas, '.' + OUT_CLASS).forEach(function(node) {
|
|
98
|
+
function unmarkNodes(root) {
|
|
99
|
+
dom.all(root, '.' + OUT_CLASS).forEach(function(node) {
|
|
103
100
|
dom.removeClass(node, OUT_CLASS);
|
|
104
101
|
node.removeAttribute(OUT_ATTR);
|
|
105
102
|
dom.dropEmptyClass(node);
|
|
106
103
|
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function unmark() {
|
|
107
|
+
if (observer) { observer.disconnect(); }
|
|
108
|
+
observer = null;
|
|
109
|
+
|
|
110
|
+
unmarkNodes(ge.canvas);
|
|
107
111
|
|
|
108
112
|
if (sheet) { sheet.remove(); }
|
|
109
113
|
sheet = null;
|
|
@@ -114,5 +118,6 @@ export function drawerflowPart(ge) {
|
|
|
114
118
|
families: [],
|
|
115
119
|
onRefresh: mark,
|
|
116
120
|
onDeinit: unmark,
|
|
121
|
+
cleanMarkup: unmarkNodes,
|
|
117
122
|
};
|
|
118
123
|
}
|
|
@@ -140,6 +140,10 @@ GridEditor.locales.es = {
|
|
|
140
140
|
'tool.paste': 'Pegar',
|
|
141
141
|
'clipboard.paste_row': 'Pegar fila',
|
|
142
142
|
'clipboard.paste_section': 'Pegar sección',
|
|
143
|
+
'autosave.restore_title': '¿Recuperar el borrador?',
|
|
144
|
+
'autosave.restore_message': 'Hay un borrador de esta página guardado el {date}, con cambios que no se publicaron. ¿Quieres recuperarlo?',
|
|
145
|
+
'autosave.restore': 'Recuperar',
|
|
146
|
+
'autosave.discard': 'Descartar',
|
|
143
147
|
'utility.col_from_row': 'De la fila: {count}',
|
|
144
148
|
'utility.row_cols': 'Columnas por fila',
|
|
145
149
|
'badge.row_cols': '{count} por fila',
|
|
@@ -206,6 +206,12 @@ GridEditor.containers.accordion = function(ge) {
|
|
|
206
206
|
ge.unwrapLabels(container);
|
|
207
207
|
},
|
|
208
208
|
|
|
209
|
+
// The same, on a copy of the canvas: unmark only touches markup
|
|
210
|
+
cleanMarkup: function(root) {
|
|
211
|
+
var definition = this;
|
|
212
|
+
dom.all(root, '[data-ge-container="accordion"]').forEach(function(container) { definition.unmark(container); });
|
|
213
|
+
},
|
|
214
|
+
|
|
209
215
|
afterPaneMove: function(container, item) {
|
|
210
216
|
reparentAccordionItem(container, item);
|
|
211
217
|
},
|