@themarioga/grid-editor 8.5.0 → 8.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -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 +226 -38
- package/dist/grideditor.js +226 -38
- 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 +86 -2
- package/example/autosave.html +39 -22
- package/example/index.html +1 -1
- package/example/plugins.html +10 -0
- package/package.json +1 -3
- package/src/js/grideditor.js +280 -30
- 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/dist/grideditor.css
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
min-height: 22px;
|
|
4
4
|
margin-bottom: 10px;
|
|
5
|
+
/* The add buttons on the left are grey, so the blue is left to the
|
|
6
|
+
source, preview and layout buttons on the right */
|
|
5
7
|
/* toolbar_groups: the tabs choosing which category of add buttons
|
|
6
8
|
shows, at the start of the line. Never squeezed, and never behind the
|
|
7
9
|
more button */
|
|
@@ -23,16 +25,25 @@
|
|
|
23
25
|
z-index: 20;
|
|
24
26
|
top: 0;
|
|
25
27
|
}
|
|
26
|
-
.ge-mainControls .ge-addRowGroup .btn.btn-
|
|
28
|
+
.ge-mainControls .ge-addRowGroup .btn.btn-light,
|
|
29
|
+
.ge-mainControls .ge-addContainerGroup .btn.btn-light,
|
|
30
|
+
.ge-mainControls .ge-toolbar-more > .btn.btn-light {
|
|
27
31
|
background: #f4f4f4;
|
|
28
32
|
color: #666;
|
|
29
33
|
border-color: #999;
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
34
|
}
|
|
33
|
-
.ge-mainControls .ge-addRowGroup .btn.btn-
|
|
35
|
+
.ge-mainControls .ge-addRowGroup .btn.btn-light:hover,
|
|
36
|
+
.ge-mainControls .ge-addContainerGroup .btn.btn-light:hover,
|
|
37
|
+
.ge-mainControls .ge-toolbar-more > .btn.btn-light:hover,
|
|
38
|
+
.ge-mainControls .ge-addRowGroup .btn.btn-light:active,
|
|
39
|
+
.ge-mainControls .ge-addContainerGroup .btn.btn-light:active,
|
|
40
|
+
.ge-mainControls .ge-toolbar-more > .btn.btn-light:active {
|
|
34
41
|
background: #E3E3E3;
|
|
35
42
|
}
|
|
43
|
+
.ge-mainControls .ge-addRowGroup .btn.btn-light {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
}
|
|
36
47
|
.ge-mainControls .ge-addRowGroup .ge-row-icon {
|
|
37
48
|
width: 48px;
|
|
38
49
|
/* A button shrinks to its content, and an equal column has none */
|
package/dist/grideditor.d.ts
CHANGED
|
@@ -126,6 +126,8 @@ export interface GridEditorOptions {
|
|
|
126
126
|
/** The tabs plugin: the variant of the tabs containers made new. */
|
|
127
127
|
tabs?: TabsOptions;
|
|
128
128
|
elements?: { enabled?: boolean | 'auto'; selector?: string; auto?: boolean; types?: ElementType[] };
|
|
129
|
+
/** The autosave plugin: what is edited, kept in the browser's storage as it changes. */
|
|
130
|
+
autosave?: AutosaveOptions;
|
|
129
131
|
custom_filter?: CustomFilter | CustomFilter[] | '';
|
|
130
132
|
valid_col_sizes?: ColumnSize[];
|
|
131
133
|
valid_col_offsets?: number[];
|
|
@@ -151,6 +153,50 @@ export interface GridEditorOptions {
|
|
|
151
153
|
[plugin: string]: unknown;
|
|
152
154
|
}
|
|
153
155
|
|
|
156
|
+
/** The autosave plugin's options. */
|
|
157
|
+
export interface AutosaveOptions {
|
|
158
|
+
/** Saving from the start; the methods turn it on and off. Default true. */
|
|
159
|
+
enabled?: boolean;
|
|
160
|
+
/** localStorage or sessionStorage. Default 'local'. */
|
|
161
|
+
storage?: 'local' | 'session';
|
|
162
|
+
/** Where the draft is kept. Default 'grideditor.autosave:' + the page's path + '#' + the canvas's id. One per document on a page that loads several. */
|
|
163
|
+
key?: string | null;
|
|
164
|
+
/** Milliseconds after the last change. Default 1000. */
|
|
165
|
+
delay?: number;
|
|
166
|
+
/** Milliseconds a draft is offered for; null, the default, for ever. */
|
|
167
|
+
maxAge?: number | null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** A draft the autosave plugin kept. */
|
|
171
|
+
export interface AutosaveDraft {
|
|
172
|
+
html: string;
|
|
173
|
+
/** When, as an ISO 8601 date. */
|
|
174
|
+
savedAt: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface GetHtmlOptions {
|
|
178
|
+
/** Read the canvas without it leaving editing: open texts and settings panels stay open. */
|
|
179
|
+
keepEditing?: boolean;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface AutosavePayload {
|
|
183
|
+
canvas: HTMLElement;
|
|
184
|
+
html: string;
|
|
185
|
+
savedAt: string;
|
|
186
|
+
source: 'change' | 'pagehide' | 'api' | 'destroy';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface RestoreDraftPayload {
|
|
190
|
+
canvas: HTMLElement;
|
|
191
|
+
html: string;
|
|
192
|
+
savedAt: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface AutosaveErrorPayload {
|
|
196
|
+
canvas: HTMLElement;
|
|
197
|
+
error: unknown;
|
|
198
|
+
}
|
|
199
|
+
|
|
154
200
|
/** Where a node was, or went: its parent and its index among the blocks there. */
|
|
155
201
|
export interface Position {
|
|
156
202
|
parent: HTMLElement;
|
|
@@ -271,6 +317,9 @@ export interface GridEditorEventMap {
|
|
|
271
317
|
'grideditor:popup-orphan': PopupOrphanPayload;
|
|
272
318
|
'grideditor:view-change': ViewChangePayload;
|
|
273
319
|
'grideditor:target-change': TargetChangePayload;
|
|
320
|
+
'grideditor:after-autosave': AutosavePayload;
|
|
321
|
+
'grideditor:after-restore-draft': RestoreDraftPayload;
|
|
322
|
+
'grideditor:autosave-error': AutosaveErrorPayload;
|
|
274
323
|
}
|
|
275
324
|
|
|
276
325
|
/** An event the editor dispatches on its canvas: a CustomEvent whose detail is the payload. */
|
|
@@ -362,10 +411,10 @@ export declare class GridEditor {
|
|
|
362
411
|
/** A read-only copy of the settings the editor runs with. */
|
|
363
412
|
readonly settings: Readonly<GridEditorOptions>;
|
|
364
413
|
|
|
365
|
-
/** The html to save: no drawers, no editor classes, no inline styles. */
|
|
366
|
-
getHtml(): string;
|
|
414
|
+
/** The html to save: no drawers, no editor classes, no inline styles. keepEditing reads it without the canvas leaving editing. */
|
|
415
|
+
getHtml(options?: GetHtmlOptions): string;
|
|
367
416
|
/** getHtml without grid-editor's marking, for publishing. It cannot be edited again as it was. */
|
|
368
|
-
getPlainHtml(): string;
|
|
417
|
+
getPlainHtml(options?: GetHtmlOptions): string;
|
|
369
418
|
/** Run the editing pass over the canvas again, after markup was put in. */
|
|
370
419
|
init(): this;
|
|
371
420
|
/** Take the editing furniture off, leaving the markup. */
|
|
@@ -395,6 +444,13 @@ export declare class GridEditor {
|
|
|
395
444
|
getUtility(node: Target, family: string, view?: View): string | null;
|
|
396
445
|
/** Write one through the events; null is inherit. False when canceled or nothing changed. */
|
|
397
446
|
setUtility(node: Target, family: string, value: string | number | null, view?: View): boolean;
|
|
447
|
+
/** The autosave plugin's, when it is loaded: false when the browser gives it no storage. */
|
|
448
|
+
enableAutosave?(): boolean;
|
|
449
|
+
disableAutosave?(): boolean;
|
|
450
|
+
/** Save now, if it changed: true when it was written. */
|
|
451
|
+
saveDraft?(): boolean;
|
|
452
|
+
getDraft?(): AutosaveDraft | null;
|
|
453
|
+
clearDraft?(): boolean;
|
|
398
454
|
}
|
|
399
455
|
|
|
400
456
|
export default GridEditor;
|
package/dist/grideditor.esm.js
CHANGED
|
@@ -652,6 +652,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
652
652
|
var refitToolbar = function() {
|
|
653
653
|
};
|
|
654
654
|
var addButtons = [];
|
|
655
|
+
var shownToolbar = {};
|
|
655
656
|
var toolbarGroup = null;
|
|
656
657
|
var warnedHere = {};
|
|
657
658
|
var sortables = [];
|
|
@@ -762,31 +763,53 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
762
763
|
whenConfirmed();
|
|
763
764
|
return;
|
|
764
765
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
if (window.confirm(message)) {
|
|
766
|
+
confirmWith(message, { danger: true }, function(confirmed) {
|
|
767
|
+
if (confirmed) {
|
|
768
768
|
whenConfirmed();
|
|
769
769
|
}
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
function confirmWith(message, options, answer) {
|
|
773
|
+
options = options || {};
|
|
774
|
+
var Modal = modalLibrary();
|
|
775
|
+
if (!Modal) {
|
|
776
|
+
answer(window.confirm(message));
|
|
770
777
|
return;
|
|
771
778
|
}
|
|
772
779
|
var modal = confirmModal();
|
|
773
780
|
var confirmed = false;
|
|
781
|
+
var ok = one(modal, ".ge-confirm-ok");
|
|
782
|
+
if (pendingAnswer) {
|
|
783
|
+
pendingAnswer(null);
|
|
784
|
+
}
|
|
785
|
+
var settle = function(value) {
|
|
786
|
+
if (pendingAnswer !== settle) {
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
pendingAnswer = null;
|
|
790
|
+
answer(value);
|
|
791
|
+
};
|
|
792
|
+
pendingAnswer = settle;
|
|
793
|
+
one(modal, ".modal-title").textContent = options.title || t("confirm.title");
|
|
794
|
+
one(modal, ".ge-confirm-cancel").textContent = options.cancel || t("confirm.cancel");
|
|
795
|
+
ok.textContent = options.ok || t("confirm.ok");
|
|
796
|
+
toggleClass(ok, "btn-danger", !!options.danger);
|
|
797
|
+
toggleClass(ok, "btn-primary", !options.danger);
|
|
774
798
|
one(modal, ".ge-confirm-message").textContent = message;
|
|
775
|
-
|
|
799
|
+
ok.onclick = function() {
|
|
776
800
|
confirmed = true;
|
|
777
801
|
Modal.getInstance(modal).hide();
|
|
778
802
|
};
|
|
779
803
|
confirmHandlers.hidden = function() {
|
|
780
|
-
|
|
781
|
-
whenConfirmed();
|
|
782
|
-
}
|
|
804
|
+
settle(confirmed);
|
|
783
805
|
};
|
|
784
806
|
confirmHandlers.shown = function() {
|
|
785
|
-
|
|
807
|
+
ok.focus();
|
|
786
808
|
};
|
|
787
809
|
Modal.getOrCreateInstance(modal).show();
|
|
788
810
|
}
|
|
789
811
|
var confirmHandlers = { hidden: null, shown: null };
|
|
812
|
+
var pendingAnswer = null;
|
|
790
813
|
function confirmModal() {
|
|
791
814
|
if (confirmDialog) {
|
|
792
815
|
return confirmDialog;
|
|
@@ -800,13 +823,14 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
800
823
|
one(confirmDialog, ".ge-confirm-cancel").textContent = t("confirm.cancel");
|
|
801
824
|
one(confirmDialog, ".ge-confirm-ok").textContent = t("confirm.ok");
|
|
802
825
|
trackModal(confirmDialog);
|
|
826
|
+
var asking = confirmDialog;
|
|
803
827
|
confirmDialog.addEventListener("hidden.bs.modal", function() {
|
|
804
|
-
if (confirmHandlers.hidden) {
|
|
828
|
+
if (asking === confirmDialog && confirmHandlers.hidden) {
|
|
805
829
|
confirmHandlers.hidden();
|
|
806
830
|
}
|
|
807
831
|
});
|
|
808
832
|
confirmDialog.addEventListener("shown.bs.modal", function() {
|
|
809
|
-
if (confirmHandlers.shown) {
|
|
833
|
+
if (asking === confirmDialog && confirmHandlers.shown) {
|
|
810
834
|
confirmHandlers.shown();
|
|
811
835
|
}
|
|
812
836
|
});
|
|
@@ -820,6 +844,9 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
820
844
|
confirmHandlers.shown = null;
|
|
821
845
|
retireModal(confirmDialog);
|
|
822
846
|
confirmDialog = null;
|
|
847
|
+
if (pendingAnswer) {
|
|
848
|
+
pendingAnswer(null);
|
|
849
|
+
}
|
|
823
850
|
}
|
|
824
851
|
function retireModal(panel) {
|
|
825
852
|
var Modal = modalLibrary();
|
|
@@ -1114,7 +1141,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1114
1141
|
settings.new_row_layouts.forEach(function(layout) {
|
|
1115
1142
|
var grouped = !Array.isArray(layout);
|
|
1116
1143
|
var btn = element("a", {
|
|
1117
|
-
"class": "btn btn-sm btn-
|
|
1144
|
+
"class": "btn btn-sm btn-light",
|
|
1118
1145
|
title: grouped ? t("row.add_row_cols", { columns: layout.columns, counts: rowColsText(layout.row_cols) }) : t("row.add", { layout: layout.join("-") }),
|
|
1119
1146
|
// What this button makes, in the markup rather than in
|
|
1120
1147
|
// memory: a drag works on a clone of it
|
|
@@ -1149,7 +1176,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1149
1176
|
Object.keys(CONTAINERS).forEach(function(type) {
|
|
1150
1177
|
var definition = CONTAINERS[type];
|
|
1151
1178
|
var button = labelButton(
|
|
1152
|
-
element("a", { "class": "btn btn-sm btn-
|
|
1179
|
+
element("a", { "class": "btn btn-sm btn-light ge-add-container" }),
|
|
1153
1180
|
t(definition.labelKey),
|
|
1154
1181
|
definition.iconClass
|
|
1155
1182
|
);
|
|
@@ -1170,8 +1197,10 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1170
1197
|
addButtons.push({ button, home: addContainerGroup, group: toolbarGroupOf(definition.group) || "content" });
|
|
1171
1198
|
});
|
|
1172
1199
|
var endItems = [];
|
|
1200
|
+
shownToolbar = {};
|
|
1173
1201
|
Object.keys(FEATURES).forEach(function(name) {
|
|
1174
|
-
|
|
1202
|
+
shownToolbar[name] = toolbarOf(FEATURES[name]);
|
|
1203
|
+
shownToolbar[name].forEach(function(item, index) {
|
|
1175
1204
|
var button = featureButton(name, item, index);
|
|
1176
1205
|
if (item.align === "end") {
|
|
1177
1206
|
endItems.push(button);
|
|
@@ -1270,7 +1299,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1270
1299
|
names.forEach(function(name) {
|
|
1271
1300
|
var tab = tabs.appendChild(element("button", {
|
|
1272
1301
|
type: "button",
|
|
1273
|
-
"class": "btn btn-sm btn-outline-
|
|
1302
|
+
"class": "btn btn-sm btn-outline-secondary",
|
|
1274
1303
|
role: "tab",
|
|
1275
1304
|
"data-ge-group": name
|
|
1276
1305
|
}, groupLabel(name)));
|
|
@@ -1307,6 +1336,22 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1307
1336
|
return !closest(entry.button, ".ge-toolbar-stash");
|
|
1308
1337
|
});
|
|
1309
1338
|
}
|
|
1339
|
+
function toolbarOf(feature) {
|
|
1340
|
+
var items = typeof feature.toolbar === "function" ? feature.toolbar() : feature.toolbar;
|
|
1341
|
+
return Array.isArray(items) ? items : [];
|
|
1342
|
+
}
|
|
1343
|
+
function refreshToolbar() {
|
|
1344
|
+
if (!mainControls || destroyed) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
var previewing = !!one(mainControls, ".gm-preview.active");
|
|
1348
|
+
removeMainControls();
|
|
1349
|
+
createMainControls();
|
|
1350
|
+
if (previewing) {
|
|
1351
|
+
addClass(one(mainControls, ".gm-preview"), "active btn-danger");
|
|
1352
|
+
}
|
|
1353
|
+
onScroll();
|
|
1354
|
+
}
|
|
1310
1355
|
function removeMainControls() {
|
|
1311
1356
|
if (toolbarLifetime) {
|
|
1312
1357
|
toolbarLifetime.abort();
|
|
@@ -1319,7 +1364,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1319
1364
|
mainControls.remove();
|
|
1320
1365
|
}
|
|
1321
1366
|
function createOverflowMenu(start) {
|
|
1322
|
-
var more = create('<div class="ge-toolbar-more"><button type="button" class="btn btn-sm btn-
|
|
1367
|
+
var more = create('<div class="ge-toolbar-more"><button type="button" class="btn btn-sm btn-light"><i class="bi bi-three-dots"></i></button><div class="ge-toolbar-overflow"><div class="ge-addRowGroup btn-group"></div><div class="ge-addContainerGroup btn-group"></div></div></div>');
|
|
1323
1368
|
start.parentNode.insertBefore(more, start.nextSibling);
|
|
1324
1369
|
var toggle2 = one(more, "button");
|
|
1325
1370
|
var panel = one(more, ".ge-toolbar-overflow");
|
|
@@ -1410,7 +1455,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1410
1455
|
function featureButton(name, item, index) {
|
|
1411
1456
|
var iconClass = item.iconClass || (item.align === "end" ? "bi bi-plus" : null);
|
|
1412
1457
|
var label = typeof item.label === "function" ? item.label() : item.label || t(item.labelKey);
|
|
1413
|
-
var
|
|
1458
|
+
var colour = item.align === "end" ? "btn-primary" : "btn-light";
|
|
1459
|
+
var button = labelButton(element("a", { "class": "btn btn-sm " + colour + " ge-add-container ge-add-feature" }), label, iconClass);
|
|
1414
1460
|
addClass(button, item.className || "");
|
|
1415
1461
|
attr(button, {
|
|
1416
1462
|
"data-ge-toolbar": "feature",
|
|
@@ -1532,7 +1578,10 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1532
1578
|
return { region, before };
|
|
1533
1579
|
}
|
|
1534
1580
|
function insertFeatureFromToolbar(button, where, source) {
|
|
1535
|
-
var item =
|
|
1581
|
+
var item = (shownToolbar[button.getAttribute("data-ge-feature")] || [])[parseInt(button.getAttribute("data-ge-item"), 10)];
|
|
1582
|
+
if (!item) {
|
|
1583
|
+
return null;
|
|
1584
|
+
}
|
|
1536
1585
|
var made = item.create();
|
|
1537
1586
|
if (!made) {
|
|
1538
1587
|
return null;
|
|
@@ -1918,22 +1967,122 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1918
1967
|
closeSizePicker();
|
|
1919
1968
|
hideDropMarker();
|
|
1920
1969
|
closeDialog();
|
|
1921
|
-
|
|
1922
|
-
drawer.remove();
|
|
1923
|
-
});
|
|
1970
|
+
removeDrawers(canvas);
|
|
1924
1971
|
pluginFields.clear();
|
|
1925
|
-
unwrapTexts();
|
|
1972
|
+
unwrapTexts(canvas);
|
|
1926
1973
|
plugins("onDeinit");
|
|
1927
1974
|
clearPreviews(canvas);
|
|
1928
|
-
|
|
1929
|
-
row.removeAttribute("data-ge-row-cols");
|
|
1930
|
-
});
|
|
1975
|
+
clearRowCols(canvas);
|
|
1931
1976
|
unmarkContainers();
|
|
1932
1977
|
removeSortable();
|
|
1933
1978
|
removeResizable();
|
|
1934
|
-
runFilter(false);
|
|
1979
|
+
runFilter(false, canvas);
|
|
1980
|
+
}
|
|
1981
|
+
function removeDrawers(root) {
|
|
1982
|
+
all(root, ".ge-tools-drawer").forEach(function(drawer) {
|
|
1983
|
+
drawer.remove();
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
function clearRowCols(root) {
|
|
1987
|
+
all(root, "[data-ge-row-cols]").forEach(function(row) {
|
|
1988
|
+
row.removeAttribute("data-ge-row-cols");
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
function pluginsWithoutCleanMarkup() {
|
|
1992
|
+
var names = [];
|
|
1993
|
+
[CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
|
|
1994
|
+
Object.keys(registry).forEach(function(name) {
|
|
1995
|
+
var plugin = registry[name];
|
|
1996
|
+
var marks = plugin.unmark || plugin.onDeinit || plugin.onBeforeDeinit;
|
|
1997
|
+
if (marks && !plugin.cleanMarkup) {
|
|
1998
|
+
names.push(name);
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
});
|
|
2002
|
+
return names;
|
|
2003
|
+
}
|
|
2004
|
+
function copyCanvas() {
|
|
2005
|
+
var copy = canvas.cloneNode(true);
|
|
2006
|
+
var toLive = /* @__PURE__ */ new Map();
|
|
2007
|
+
var toCopy = /* @__PURE__ */ new Map();
|
|
2008
|
+
var live = document.createTreeWalker(canvas, NodeFilter.SHOW_ELEMENT);
|
|
2009
|
+
var copied = document.createTreeWalker(copy, NodeFilter.SHOW_ELEMENT);
|
|
2010
|
+
var a = live.currentNode;
|
|
2011
|
+
var b = copied.currentNode;
|
|
2012
|
+
while (a && b) {
|
|
2013
|
+
toLive.set(b, a);
|
|
2014
|
+
toCopy.set(a, b);
|
|
2015
|
+
a = live.nextNode();
|
|
2016
|
+
b = copied.nextNode();
|
|
2017
|
+
}
|
|
2018
|
+
return {
|
|
2019
|
+
root: copy,
|
|
2020
|
+
liveOf: function(node) {
|
|
2021
|
+
return toLive.get(node) || null;
|
|
2022
|
+
},
|
|
2023
|
+
copyOf: function(node) {
|
|
2024
|
+
return toCopy.get(node) || null;
|
|
2025
|
+
}
|
|
2026
|
+
};
|
|
2027
|
+
}
|
|
2028
|
+
function snapshotHtml() {
|
|
2029
|
+
if (sourceOpen) {
|
|
2030
|
+
return getHtml();
|
|
2031
|
+
}
|
|
2032
|
+
var missing = pluginsWithoutCleanMarkup();
|
|
2033
|
+
if (missing.length) {
|
|
2034
|
+
missing.forEach(function(name) {
|
|
2035
|
+
warnOnceHere("snapshot:" + name, 'the "' + name + '" plugin has no cleanMarkup, so the canvas leaves editing to be read: open texts and settings panels close');
|
|
2036
|
+
});
|
|
2037
|
+
return getHtml();
|
|
2038
|
+
}
|
|
2039
|
+
var copy = copyCanvas();
|
|
2040
|
+
var root = copy.root;
|
|
2041
|
+
[root].concat(all(root, ".ge-active-target, .ge-settings-target")).forEach(function(node) {
|
|
2042
|
+
removeClass(node, "ge-active-target ge-settings-target");
|
|
2043
|
+
dropEmptyClass(node);
|
|
2044
|
+
});
|
|
2045
|
+
all(root, ".ge-drop-marker").forEach(function(marker) {
|
|
2046
|
+
marker.remove();
|
|
2047
|
+
});
|
|
2048
|
+
removeDrawers(root);
|
|
2049
|
+
unwrapTexts(root);
|
|
2050
|
+
var refused = null;
|
|
2051
|
+
[CONTAINERS, FEATURES, UTILITIES].forEach(function(registry) {
|
|
2052
|
+
Object.keys(registry).forEach(function(name) {
|
|
2053
|
+
var plugin = registry[name];
|
|
2054
|
+
if (refused || !plugin.cleanMarkup) {
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
if (plugin.cleanMarkup(root, copy.liveOf) === false) {
|
|
2058
|
+
refused = name;
|
|
2059
|
+
}
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
2062
|
+
if (refused) {
|
|
2063
|
+
warnOnceHere("snapshot-refused:" + refused, 'the "' + refused + '" plugin cannot take its marking off a copy right now, so the canvas leaves editing to be read');
|
|
2064
|
+
return getHtml();
|
|
2065
|
+
}
|
|
2066
|
+
clearPreviews(root);
|
|
2067
|
+
clearRowCols(root);
|
|
2068
|
+
all(root, "[data-ge-container]").forEach(unmarkContainerClasses);
|
|
2069
|
+
sortables.forEach(function(sortableInstance) {
|
|
2070
|
+
var list = copy.copyOf(sortableInstance.el);
|
|
2071
|
+
if (list) {
|
|
2072
|
+
all(list, "[draggable]").forEach(function(node) {
|
|
2073
|
+
node.removeAttribute("draggable");
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
});
|
|
2077
|
+
removeResizeFurniture(root);
|
|
2078
|
+
runFilter(false, root);
|
|
2079
|
+
stripPixelWidths(root);
|
|
2080
|
+
return root.innerHTML;
|
|
1935
2081
|
}
|
|
1936
|
-
function getHtml() {
|
|
2082
|
+
function getHtml(options) {
|
|
2083
|
+
if (options && options.keepEditing) {
|
|
2084
|
+
return snapshotHtml();
|
|
2085
|
+
}
|
|
1937
2086
|
deinit();
|
|
1938
2087
|
stripPixelWidths(canvas);
|
|
1939
2088
|
var html = canvas.innerHTML;
|
|
@@ -1947,10 +2096,24 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
1947
2096
|
init();
|
|
1948
2097
|
return html;
|
|
1949
2098
|
}
|
|
1950
|
-
function getPlainHtml() {
|
|
1951
|
-
return plainHtml(getHtml());
|
|
2099
|
+
function getPlainHtml(options) {
|
|
2100
|
+
return plainHtml(getHtml(options));
|
|
2101
|
+
}
|
|
2102
|
+
function setHtml2(html) {
|
|
2103
|
+
if (sourceOpen) {
|
|
2104
|
+
closeSource();
|
|
2105
|
+
if (mainControls) {
|
|
2106
|
+
all(mainControls, ".gm-edit-mode").forEach(function(button) {
|
|
2107
|
+
removeClass(button, "active btn-danger");
|
|
2108
|
+
});
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
deinit();
|
|
2112
|
+
setHtml(canvas, html);
|
|
2113
|
+
init();
|
|
1952
2114
|
}
|
|
1953
2115
|
function destroy() {
|
|
2116
|
+
plugins("onDestroy");
|
|
1954
2117
|
if (sourceOpen) {
|
|
1955
2118
|
closeSource();
|
|
1956
2119
|
}
|
|
@@ -2063,6 +2226,11 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2063
2226
|
closeDialog,
|
|
2064
2227
|
rowFromLayout: rowFromLayoutValue,
|
|
2065
2228
|
nodeHtml,
|
|
2229
|
+
// The markup as getHtml gives it, with the canvas left editing
|
|
2230
|
+
snapshotHtml,
|
|
2231
|
+
setHtml: setHtml2,
|
|
2232
|
+
// A question in the editor's confirm modal
|
|
2233
|
+
confirm: confirmWith,
|
|
2066
2234
|
// A text editor has rewritten a content area, so whatever the
|
|
2067
2235
|
// editor and its plugins had put in there goes back in
|
|
2068
2236
|
textReady,
|
|
@@ -2075,6 +2243,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2075
2243
|
// A node's drawer: its first child, or for a content area the
|
|
2076
2244
|
// one beside it in its text block
|
|
2077
2245
|
drawerOf,
|
|
2246
|
+
// The toolbar built again, from the plugins' toolbars as they are now
|
|
2247
|
+
refreshToolbar,
|
|
2078
2248
|
toolbarItems: function(name) {
|
|
2079
2249
|
return mainControls ? all(mainControls, '[data-ge-toolbar="feature"][data-ge-feature="' + name + '"]') : [];
|
|
2080
2250
|
}
|
|
@@ -2585,10 +2755,13 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
2585
2755
|
if (definition) {
|
|
2586
2756
|
definition.unmark(container);
|
|
2587
2757
|
}
|
|
2588
|
-
|
|
2589
|
-
dropEmptyClass(container);
|
|
2758
|
+
unmarkContainerClasses(container);
|
|
2590
2759
|
});
|
|
2591
2760
|
}
|
|
2761
|
+
function unmarkContainerClasses(container) {
|
|
2762
|
+
removeClass(container, "ge-container ge-container-" + containerTypeOf(container));
|
|
2763
|
+
dropEmptyClass(container);
|
|
2764
|
+
}
|
|
2592
2765
|
function prependDrawer(node, className) {
|
|
2593
2766
|
var drawer = element("div", { "class": className });
|
|
2594
2767
|
node.insertBefore(drawer, node.firstChild);
|
|
@@ -3989,13 +4162,16 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
3989
4162
|
on(handle, "pointerup pointercancel", onUp);
|
|
3990
4163
|
}
|
|
3991
4164
|
function removeResizable() {
|
|
3992
|
-
|
|
4165
|
+
removeResizeFurniture(canvas);
|
|
4166
|
+
}
|
|
4167
|
+
function removeResizeFurniture(root) {
|
|
4168
|
+
all(root, ".ge-resize-handle").forEach(function(handle) {
|
|
3993
4169
|
handle.remove();
|
|
3994
4170
|
});
|
|
3995
|
-
all(
|
|
4171
|
+
all(root, ".ge-resize-size").forEach(function(readout) {
|
|
3996
4172
|
readout.remove();
|
|
3997
4173
|
});
|
|
3998
|
-
stripPixelWidths(
|
|
4174
|
+
stripPixelWidths(root);
|
|
3999
4175
|
}
|
|
4000
4176
|
function snapUnits(col, pixels) {
|
|
4001
4177
|
var units = Math.round(pixels / rowContentWidth(col.parentElement) * MAX_COL_SIZE);
|
|
@@ -4203,7 +4379,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
4203
4379
|
setOffset(column, tier, wanted.offset);
|
|
4204
4380
|
return column;
|
|
4205
4381
|
}
|
|
4206
|
-
function runFilter(isInit) {
|
|
4382
|
+
function runFilter(isInit, root) {
|
|
4207
4383
|
if (!settings.custom_filter || !settings.custom_filter.length) {
|
|
4208
4384
|
return;
|
|
4209
4385
|
}
|
|
@@ -4212,7 +4388,7 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
4212
4388
|
if (typeof func == "string") {
|
|
4213
4389
|
func = window[func];
|
|
4214
4390
|
}
|
|
4215
|
-
func(canvas, isInit);
|
|
4391
|
+
func(root || canvas, isInit);
|
|
4216
4392
|
});
|
|
4217
4393
|
}
|
|
4218
4394
|
function textCutter() {
|
|
@@ -4332,8 +4508,8 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
4332
4508
|
}
|
|
4333
4509
|
});
|
|
4334
4510
|
}
|
|
4335
|
-
function unwrapTexts() {
|
|
4336
|
-
all(
|
|
4511
|
+
function unwrapTexts(root) {
|
|
4512
|
+
all(root, ".ge-text-block").forEach(function(textBlock) {
|
|
4337
4513
|
unwrap(textBlock);
|
|
4338
4514
|
});
|
|
4339
4515
|
}
|
|
@@ -4506,6 +4682,18 @@ function build(instance, baseElem, optionsOrMethod) {
|
|
|
4506
4682
|
instances.set(canvas, instance);
|
|
4507
4683
|
loadPlugins();
|
|
4508
4684
|
instance.settings = settingsCopy();
|
|
4685
|
+
Object.keys(featureMethods).forEach(function(name) {
|
|
4686
|
+
if (Object.prototype.hasOwnProperty.call(own, name) || name in instance) {
|
|
4687
|
+
return;
|
|
4688
|
+
}
|
|
4689
|
+
instance[name] = function() {
|
|
4690
|
+
if (destroyed) {
|
|
4691
|
+
warnOnceHere("destroyed:" + name, t("warning.destroyed", { method: name }));
|
|
4692
|
+
return null;
|
|
4693
|
+
}
|
|
4694
|
+
return featureMethods[name].apply(null, arguments);
|
|
4695
|
+
};
|
|
4696
|
+
});
|
|
4509
4697
|
setup();
|
|
4510
4698
|
init();
|
|
4511
4699
|
GridEditor._created.forEach(function(hook) {
|
|
@@ -4521,7 +4709,7 @@ GridEditor.t = translate;
|
|
|
4521
4709
|
GridEditor._plainHtml = plainHtml;
|
|
4522
4710
|
GridEditor.Sortable = null;
|
|
4523
4711
|
GridEditor.bootstrap = null;
|
|
4524
|
-
GridEditor.version = false ? "dev" : "8.
|
|
4712
|
+
GridEditor.version = false ? "dev" : "8.7.0";
|
|
4525
4713
|
GridEditor.locales = {
|
|
4526
4714
|
en: {
|
|
4527
4715
|
"tool.move": "Move",
|