@themarioga/grid-editor 6.0.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTO_SAVE.md +2 -2
- package/BUILDING.md +45 -29
- package/CHANGELOG.md +59 -0
- package/README.md +163 -87
- package/UPGRADING.md +119 -0
- 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 -168
- 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 +484 -449
- 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 +493 -427
- 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 +502 -490
- 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 +6 -0
- package/docs/plugins.md +47 -25
- package/example/adapter.html +112 -0
- package/example/attributes.html +89 -62
- package/example/autocols.html +9 -9
- package/example/autosave.html +18 -16
- package/example/basic.html +8 -6
- package/example/breakpoints.html +5 -6
- package/example/ckeditor.html +4 -5
- package/example/clipboard.html +15 -11
- package/example/codemirror.html +13 -8
- package/example/containers.html +11 -9
- package/example/custom_editor.html +53 -34
- package/example/elements.html +14 -12
- 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 +13 -10
- package/package.json +44 -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 -156
- 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 +148 -140
- package/src/js/plugins/grideditor.visibility.js +24 -25
- package/src/js/register.js +18 -0
- package/src/js/text/grideditor.text.js +77 -56
- 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
package/docs/plugins.md
CHANGED
|
@@ -7,7 +7,7 @@ what turns the feature on. `grideditor.card.js` is the shortest of them, and
|
|
|
7
7
|
the one to read first if you are about to write your own.
|
|
8
8
|
|
|
9
9
|
```html
|
|
10
|
-
<script src="dist/
|
|
10
|
+
<script src="dist/grideditor.min.js"></script>
|
|
11
11
|
<script src="dist/plugins/grideditor.tabs.min.js"></script>
|
|
12
12
|
<script src="dist/plugins/grideditor.popup.min.js"></script>
|
|
13
13
|
<script src="dist/plugins/grideditor.card.min.js"></script>
|
|
@@ -15,11 +15,11 @@ the one to read first if you are about to write your own.
|
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
There are three kinds. A **container plugin** builds a type of container — it
|
|
18
|
-
registers under
|
|
18
|
+
registers under `GridEditor.containers`, and the toolbar offers a button
|
|
19
19
|
for it. A **utility plugin** declares families of Bootstrap's responsive
|
|
20
|
-
utility classes —
|
|
20
|
+
utility classes — `GridEditor.utilities` — and the editor edits them per
|
|
21
21
|
breakpoint. A **feature plugin** is anything else the editor can do —
|
|
22
|
-
|
|
22
|
+
`GridEditor.features`, hooks into the canvas, and may contribute methods.
|
|
23
23
|
All three are factories called once per editor with the same handle.
|
|
24
24
|
|
|
25
25
|
Text is a feature plugin too. The core knows the grid and the host's *plain
|
|
@@ -50,14 +50,12 @@ A plugin registers a **factory** under the type it builds. The factory is
|
|
|
50
50
|
called once per editor, with the handle below, and returns the definition:
|
|
51
51
|
|
|
52
52
|
```javascript
|
|
53
|
-
(
|
|
54
|
-
|
|
55
|
-
$.extend($.fn.gridEditor.locales.en, {
|
|
53
|
+
Object.assign(GridEditor.locales.en, {
|
|
56
54
|
'container.add_carousel': 'Carousel',
|
|
57
55
|
'container.carousel_label': 'Slide {number}',
|
|
58
56
|
});
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
GridEditor.containers.carousel = function(ge) {
|
|
61
59
|
|
|
62
60
|
function addSlideTo(container, options) { … }
|
|
63
61
|
|
|
@@ -77,10 +75,28 @@ $.fn.gridEditor.containers.carousel = function(ge) {
|
|
|
77
75
|
onDeinit: function() { … }, // optional, per canvas deinit
|
|
78
76
|
};
|
|
79
77
|
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
That is a classic script, loaded after `grideditor.js`, with `GridEditor` on
|
|
81
|
+
window. The same plugin as an ES module imports the editor and registers as
|
|
82
|
+
it is imported, which is how the shipped plugins' modules work:
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
import { GridEditor } from '@themarioga/grid-editor';
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
GridEditor.containers.carousel = function(ge) { … };
|
|
82
88
|
```
|
|
83
89
|
|
|
90
|
+
A page or an app imports it for that side effect, after the editor:
|
|
91
|
+
`import './carousel.js'`. Either way there is one registry per page, and the
|
|
92
|
+
editors made after a plugin registered have it.
|
|
93
|
+
|
|
94
|
+
Everything the editor hands a plugin, and everything a plugin hands back, is
|
|
95
|
+
DOM: elements, and arrays of them where there may be several. Up to 6.x it was
|
|
96
|
+
jQuery objects; a plugin written for 6.x is ported by taking that out, and
|
|
97
|
+
[UPGRADING.md](../UPGRADING.md) says how. The shipped plugins are written in
|
|
98
|
+
plain DOM, and a plugin of your own is free to use whatever it likes.
|
|
99
|
+
|
|
84
100
|
- **`iconClass`**, when given, is the toolbar button's face: the icon alone,
|
|
85
101
|
with the label as its title. Without one the button shows a plus and the
|
|
86
102
|
label.
|
|
@@ -102,7 +118,9 @@ The handle
|
|
|
102
118
|
|
|
103
119
|
Everything a plugin needs from the editor comes through the handle its factory
|
|
104
120
|
is called with. It is the plugin contract: these names, and what they do, do
|
|
105
|
-
not change without a major version.
|
|
121
|
+
not change without a major version. 7.0 was one: every node it takes or gives
|
|
122
|
+
is an element, and where 6.x gave a jQuery set that may hold several, an
|
|
123
|
+
array.
|
|
106
124
|
|
|
107
125
|
| | |
|
|
108
126
|
| --- | --- |
|
|
@@ -112,10 +130,10 @@ not change without a major version.
|
|
|
112
130
|
| `ge.warn(message)` | A console warning, prefixed like the editor's own |
|
|
113
131
|
| `ge.containerId(type)` | A generated id, stable across a reset, for Bootstrap's toggles |
|
|
114
132
|
| `ge.defaultRegion()` | A row with one full width column: what an empty pane starts as |
|
|
115
|
-
| `ge.createTool(drawer, title, className, iconClass, handlers)` | A tool in a drawer |
|
|
116
|
-
| `ge.createMoveTool(drawer)` | The drag handle, unless `drag_handle` says the whole drawer is one |
|
|
133
|
+
| `ge.createTool(drawer, title, className, iconClass, handlers)` | A tool in a drawer, which it returns. `handlers` is a click handler or `{ eventName: handler }`; each gets the DOM event, with `this` the tool |
|
|
134
|
+
| `ge.createMoveTool(drawer)` | The drag handle, unless `drag_handle` says the whole drawer is one; the tool, or null |
|
|
117
135
|
| `ge.addSettingsTool(drawer, node, presets)` | The gear, and the id and class panel it opens. Returns the panel, to add fields to |
|
|
118
|
-
| `ge.detailsOf(node)` | A node's settings panel, wherever it is: in its drawer, or open in the offcanvas, popover or modal `settings_panel` names, outside the canvas. Find a panel's fields through it, never through the drawer |
|
|
136
|
+
| `ge.detailsOf(node)` | A node's settings panel, wherever it is: in its drawer, or open in the offcanvas, popover or modal `settings_panel` names, outside the canvas. Find a panel's fields through it, never through the drawer. Null for a node with none |
|
|
119
137
|
| `ge.deleteNode(kind, node, confirmText, animate)` | Remove a node: ask, animate, announce |
|
|
120
138
|
| `ge.place(node, kind, options)` | Put a created node where `appendTo` and friends say, through the add events. `options.source` is the payload's `source`, `api` by default |
|
|
121
139
|
| `ge.createPaneControls(pane, kind, hostTools, confirmText, remove)` | The drawer a pane gets: move, the host's tools, delete |
|
|
@@ -132,15 +150,15 @@ not change without a major version.
|
|
|
132
150
|
| `ge.breakpoints` | Every breakpoint key, smallest first |
|
|
133
151
|
| `ge.getUtility(node, family, view?)` | A utility's value, as in the public method |
|
|
134
152
|
| `ge.setUtility(node, family, value, options?)` | Write one through the events. `options` is a view key or `{ view, source }` |
|
|
135
|
-
| `ge.utilityField(node, family)` | A panel field for one family, for a plugin that builds its own panel |
|
|
153
|
+
| `ge.utilityField(node, family)` | A panel field for one family, for a plugin that builds its own panel; null for a family no plugin declares |
|
|
136
154
|
| `ge.rowFromLayout(layout)` | A detached row from a layout: `[8, 4]`, `['auto', 'equal']` or `{ row_cols, columns }` |
|
|
137
|
-
| `ge.drawerOf(node)` | A node's drawer: its first child, or for a content area the one beside it in its text block |
|
|
155
|
+
| `ge.drawerOf(node)` | A node's drawer: its first child, or for a content area the one beside it in its text block; null when it has none |
|
|
138
156
|
| `ge.textReady(block)` | A text editor has rewritten a content area: whatever the editor and its plugins put in there goes back in |
|
|
139
157
|
| `ge.attachPicker(tool, open)` | Hold a tool, or rest the pointer on it, and `open` is called: how a tool offers a choice |
|
|
140
158
|
| `ge.openPicker(anchor, choices, className?)` | The choice itself, as a strip under `anchor`: one button per `{ label, title, attributes, choose }` |
|
|
141
159
|
| `ge.closePicker()` | Close it; true when one was open, which is also a click's answer |
|
|
142
160
|
| `ge.nodeHtml(node)` | One node's markup as `getHtml` would give it. The canvas leaves editing to read it and comes back, as it does for `getHtml` |
|
|
143
|
-
| `ge.toolbarItems(name)` |
|
|
161
|
+
| `ge.toolbarItems(name)` | An array of the toolbar buttons the feature plugin `name` declared, for showing and hiding them |
|
|
144
162
|
| `ge.bareStyle(node, family, property)` | A css property's value on the node with none of the family's classes: what a preview shows when no class applies and that is not a constant |
|
|
145
163
|
|
|
146
164
|
The add, delete and move events for a container and its panes are fired by the
|
|
@@ -154,7 +172,7 @@ Feature plugins
|
|
|
154
172
|
A feature plugin returns hooks rather than a container definition:
|
|
155
173
|
|
|
156
174
|
```javascript
|
|
157
|
-
|
|
175
|
+
GridEditor.features.elements = function(ge) {
|
|
158
176
|
return {
|
|
159
177
|
methods: { createElement: … }, // added to the editor's own methods
|
|
160
178
|
kindOf: function(node) { … }, // what an event calls this node
|
|
@@ -246,7 +264,7 @@ rather than remembering anything about it.
|
|
|
246
264
|
|
|
247
265
|
```javascript
|
|
248
266
|
onSortable: function(sortable) {
|
|
249
|
-
sortable(ge.canvas.
|
|
267
|
+
sortable(Array.from(ge.canvas.querySelectorAll('.ge-content')), {
|
|
250
268
|
draggable: '> .ge-element', // which children move
|
|
251
269
|
group: 'element', // lists sharing a group connect
|
|
252
270
|
});
|
|
@@ -316,7 +334,7 @@ A feature plugin that edits text declares its types, and that is all the
|
|
|
316
334
|
core asks of it:
|
|
317
335
|
|
|
318
336
|
```javascript
|
|
319
|
-
|
|
337
|
+
GridEditor.features.mytext = function(ge) {
|
|
320
338
|
return {
|
|
321
339
|
textTypes: function() {
|
|
322
340
|
return [{
|
|
@@ -361,8 +379,12 @@ off there.
|
|
|
361
379
|
block's drawer, the *Text* buttons in the toolbar, `createText`, opening an
|
|
362
380
|
editor on a click and closing it with
|
|
363
381
|
the host's attributes put back, and `textTypes` - from
|
|
364
|
-
`src/js/text/grideditor.text.js`, which
|
|
365
|
-
However many a page loads, that is installed once.
|
|
382
|
+
`src/js/text/grideditor.text.js`, which each of them imports, so its script
|
|
383
|
+
carries it. However many a page loads, that is installed once.
|
|
384
|
+
|
|
385
|
+
Each registers on `GridEditor.texts`, the text feature's own registry, with a
|
|
386
|
+
factory whose `start(contentAreas)` and `stop(contentAreas)` get an array of
|
|
387
|
+
content areas.
|
|
366
388
|
|
|
367
389
|
The editors offered are `content_types`, every one loaded by default, in the
|
|
368
390
|
order the page loaded them; the `plugins` setting does not choose them. A
|
|
@@ -379,9 +401,9 @@ editors.
|
|
|
379
401
|
|
|
380
402
|
Up to 5.x an editor of a host's own registered under
|
|
381
403
|
`$.fn.gridEditor.RTEs`, and in 5.x and the 6.0 betas under
|
|
382
|
-
`$.fn.gridEditor.texts`. 6.0
|
|
383
|
-
|
|
384
|
-
|
|
404
|
+
`$.fn.gridEditor.texts`. 6.0 ignored the first, with a warning, and 7.0 has
|
|
405
|
+
neither: `GridEditor.texts` is the shipped editors' own registry, not a
|
|
406
|
+
contract.
|
|
385
407
|
|
|
386
408
|
|
|
387
409
|
Utility plugins
|
|
@@ -393,7 +415,7 @@ ones spelled `{property}-{breakpoint}-{value}`, like `order-md-2` or
|
|
|
393
415
|
and the editor reads, writes, previews and announces them:
|
|
394
416
|
|
|
395
417
|
```javascript
|
|
396
|
-
|
|
418
|
+
GridEditor.utilities.order = function(ge) {
|
|
397
419
|
return {
|
|
398
420
|
families: [{
|
|
399
421
|
name: 'order', // what events and setUtility call it
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
5
|
+
|
|
6
|
+
<!-- CSS dependencies -->
|
|
7
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
|
8
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css">
|
|
9
|
+
|
|
10
|
+
<!-- Javascript dependencies: jQuery 4, which this page's own code is
|
|
11
|
+
written in, as a page for grid-editor 6 was -->
|
|
12
|
+
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
|
|
13
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
|
14
|
+
|
|
15
|
+
<!-- Grid editor CSS -->
|
|
16
|
+
<link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
|
|
17
|
+
<!-- Grid editor javascript: the editor, then the jQuery API on top of
|
|
18
|
+
it, then the plugins - which are 7.0's, like the editor -->
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
|
20
|
+
<script src="../dist/grideditor.min.js"></script>
|
|
21
|
+
<script src="../dist/grideditor.jquery.min.js"></script>
|
|
22
|
+
<script src="../dist/plugins/grideditor.tabs.min.js"></script>
|
|
23
|
+
<script src="../dist/plugins/grideditor.card.min.js"></script>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
// Everything below is grid-editor 6 code, unchanged
|
|
27
|
+
$(function() {
|
|
28
|
+
$('#myGrid').gridEditor({
|
|
29
|
+
new_row_layouts: [[12], [6, 6], [4, 4, 4]],
|
|
30
|
+
content_types: [],
|
|
31
|
+
|
|
32
|
+
// A callback gets the payload with jQuery objects in it
|
|
33
|
+
callbacks: {
|
|
34
|
+
after_add_row: function(payload) {
|
|
35
|
+
$('#last').text('A row was added, with ' +
|
|
36
|
+
payload.node.children('.column').length + ' columns');
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// And so does a jQuery event listener, as its second argument
|
|
42
|
+
$('#myGrid').on('grideditor:before-delete', function(e, payload) {
|
|
43
|
+
if (payload.node.hasClass('locked')) {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
$('#last').text('That row is locked: it stays');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
$('#output').on('click', function() {
|
|
50
|
+
$('#html').text($('#myGrid').gridEditor('getHtml'));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<title>Grid Editor jQuery API example</title>
|
|
56
|
+
</head>
|
|
57
|
+
<body>
|
|
58
|
+
<!-- Back to the demo index -->
|
|
59
|
+
<div class="container pt-3">
|
|
60
|
+
<a class="link-secondary" href="index.html"><i class="bi bi-arrow-left"></i> All demos</a>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
<div class="container">
|
|
65
|
+
|
|
66
|
+
<div class="row my-3">
|
|
67
|
+
<div class="col-lg-8">
|
|
68
|
+
<h1 class="h4">The jQuery API</h1>
|
|
69
|
+
<p class="form-text">
|
|
70
|
+
grid-editor needs no jQuery since 7.0. A page written for
|
|
71
|
+
6.x loads jQuery 4 and <code>grideditor.jquery.js</code>
|
|
72
|
+
after the editor, and its code runs as it did:
|
|
73
|
+
<code>$('#myGrid').gridEditor(...)</code>, the methods by
|
|
74
|
+
name, jQuery event listeners and callbacks with jQuery
|
|
75
|
+
objects in their payloads. The plugins are 7.0's; a plugin
|
|
76
|
+
written for 6.x is the one thing to port, as
|
|
77
|
+
<code>UPGRADING.md</code> explains.
|
|
78
|
+
</p>
|
|
79
|
+
<p class="form-text">
|
|
80
|
+
Add a row and the callback counts its columns. The first
|
|
81
|
+
row carries a <code>locked</code> class, which the event
|
|
82
|
+
listener reads to turn its delete away.
|
|
83
|
+
</p>
|
|
84
|
+
<button class="btn btn-sm btn-secondary" id="output" type="button">Show the html this produces</button>
|
|
85
|
+
<p class="form-text" id="last"></p>
|
|
86
|
+
<pre id="html" class="form-text"></pre>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div id="myGrid">
|
|
91
|
+
|
|
92
|
+
<div class="row locked">
|
|
93
|
+
<div class="col-lg-12">
|
|
94
|
+
<h2 class="h5">A locked row</h2>
|
|
95
|
+
<p>Its delete is canceled by the page's own jQuery listener.</p>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<div class="row">
|
|
100
|
+
<div class="col-lg-6">
|
|
101
|
+
<p>An ordinary column.</p>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="col-lg-6">
|
|
104
|
+
<p>And another.</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
</div> <!-- /#myGrid -->
|
|
109
|
+
</div> <!-- /.container -->
|
|
110
|
+
|
|
111
|
+
</body>
|
|
112
|
+
</html>
|
package/example/attributes.html
CHANGED
|
@@ -8,15 +8,14 @@
|
|
|
8
8
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css">
|
|
9
9
|
|
|
10
10
|
<!-- Javascript dependencies -->
|
|
11
|
-
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
|
|
12
11
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
|
13
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/
|
|
12
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/7.9.3/tinymce.min.js"></script>
|
|
14
13
|
|
|
15
14
|
<!-- Grid editor CSS -->
|
|
16
15
|
<link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
|
|
17
16
|
<!-- Grid editor javascript -->
|
|
18
17
|
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
|
19
|
-
<script src="../dist/
|
|
18
|
+
<script src="../dist/grideditor.min.js"></script>
|
|
20
19
|
<!-- The text editor is a plugin of its own, loaded after the editor -->
|
|
21
20
|
<script src="../dist/plugins/grideditor.tinymce.min.js"></script>
|
|
22
21
|
<script src="../dist/plugins/grideditor.card.min.js"></script>
|
|
@@ -34,9 +33,9 @@
|
|
|
34
33
|
<!-- A plugin of this page's own: a drawer tool that opens a modal, and
|
|
35
34
|
what the user chooses there saved as an attribute on the node. -->
|
|
36
35
|
<script id="animation-plugin">
|
|
37
|
-
(function(
|
|
36
|
+
(function() {
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
Object.assign(GridEditor.locales.en, {
|
|
40
39
|
'animation.tool': 'Animation',
|
|
41
40
|
'animation.title': 'Animate on scroll',
|
|
42
41
|
'animation.effect': 'Effect',
|
|
@@ -56,49 +55,67 @@
|
|
|
56
55
|
var ATTRIBUTE = 'data-animation';
|
|
57
56
|
var EFFECTS = ['fade', 'slide', 'zoom'];
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
GridEditor.features.animation = function(ge) {
|
|
60
59
|
|
|
61
60
|
var modal = null;
|
|
62
61
|
|
|
63
62
|
function read(node) {
|
|
64
63
|
try {
|
|
65
|
-
return JSON.parse(node.
|
|
64
|
+
return JSON.parse(node.getAttribute(ATTRIBUTE) || 'null');
|
|
66
65
|
} catch (error) {
|
|
67
66
|
return null;
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
/**
|
|
72
|
-
* A plain
|
|
73
|
-
* text editor since 6.0, and a text's own attributes, given
|
|
71
|
+
* A plain setAttribute on any node: an element is never inside
|
|
72
|
+
* a text editor since 6.0, and a text's own attributes, given
|
|
74
73
|
* while its editor is open, are kept by grid-editor when the
|
|
75
74
|
* editor closes.
|
|
76
75
|
*/
|
|
77
76
|
function write(node, value) {
|
|
78
77
|
if (value) {
|
|
79
|
-
node.
|
|
78
|
+
node.setAttribute(ATTRIBUTE, JSON.stringify(value));
|
|
80
79
|
} else {
|
|
81
|
-
node.
|
|
80
|
+
node.removeAttribute(ATTRIBUTE);
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
|
|
84
|
+
function make(tag, className, text) {
|
|
85
|
+
var node = document.createElement(tag);
|
|
86
|
+
if (className) { node.className = className; }
|
|
87
|
+
if (text !== undefined) { node.textContent = text; }
|
|
88
|
+
return node;
|
|
89
|
+
}
|
|
90
|
+
|
|
85
91
|
/** Built once, outside the canvas, so it is never part of getHtml. */
|
|
86
92
|
function dialog() {
|
|
87
93
|
if (modal) { return modal; }
|
|
88
94
|
|
|
89
|
-
var effects =
|
|
90
|
-
|
|
95
|
+
var effects = make('select', 'form-select');
|
|
96
|
+
effects.name = 'effect';
|
|
97
|
+
var none = make('option', null, ge.t('animation.none'));
|
|
98
|
+
none.value = '';
|
|
99
|
+
effects.appendChild(none);
|
|
91
100
|
EFFECTS.forEach(function(effect) {
|
|
92
|
-
|
|
101
|
+
var option = make('option', null, ge.t('animation.' + effect));
|
|
102
|
+
option.value = effect;
|
|
103
|
+
effects.appendChild(option);
|
|
93
104
|
});
|
|
94
105
|
|
|
95
106
|
var field = function(label, input) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
var wrapper = make('div', 'mb-3');
|
|
108
|
+
wrapper.appendChild(make('label', 'form-label', ge.t(label)));
|
|
109
|
+
if (typeof input === 'string') {
|
|
110
|
+
wrapper.insertAdjacentHTML('beforeend', input);
|
|
111
|
+
} else {
|
|
112
|
+
wrapper.appendChild(input);
|
|
113
|
+
}
|
|
114
|
+
return wrapper;
|
|
99
115
|
};
|
|
100
116
|
|
|
101
|
-
|
|
117
|
+
var holder = document.createElement('div');
|
|
118
|
+
holder.innerHTML =
|
|
102
119
|
'<div class="modal fade my-animation-modal" tabindex="-1" aria-hidden="true">' +
|
|
103
120
|
'<div class="modal-dialog modal-dialog-centered"><form class="modal-content">' +
|
|
104
121
|
'<div class="modal-header">' +
|
|
@@ -111,46 +128,52 @@
|
|
|
111
128
|
'<button type="submit" class="btn btn-primary"></button>' +
|
|
112
129
|
'</div>' +
|
|
113
130
|
'</form></div>' +
|
|
114
|
-
'</div>'
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
modal.
|
|
118
|
-
modal.
|
|
119
|
-
modal.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
'</div>';
|
|
132
|
+
modal = document.body.appendChild(holder.firstChild);
|
|
133
|
+
|
|
134
|
+
modal.querySelector('.modal-title').textContent = ge.t('animation.title');
|
|
135
|
+
modal.querySelector('.modal-footer .btn-secondary').textContent = ge.t('animation.cancel');
|
|
136
|
+
modal.querySelector('.modal-footer .btn-primary').textContent = ge.t('animation.save');
|
|
137
|
+
|
|
138
|
+
var once = make('div', 'form-check');
|
|
139
|
+
once.innerHTML = '<input class="form-check-input" type="checkbox" name="once" id="my-animation-once">';
|
|
140
|
+
var onceLabel = make('label', 'form-check-label', ge.t('animation.once'));
|
|
141
|
+
onceLabel.setAttribute('for', 'my-animation-once');
|
|
142
|
+
once.appendChild(onceLabel);
|
|
143
|
+
|
|
144
|
+
var body = modal.querySelector('.modal-body');
|
|
145
|
+
body.appendChild(field('animation.effect', effects));
|
|
146
|
+
body.appendChild(field('animation.duration', '<input class="form-control" type="number" name="duration" min="0" step="100">'));
|
|
147
|
+
body.appendChild(field('animation.delay', '<input class="form-control" type="number" name="delay" min="0" step="100">'));
|
|
148
|
+
body.appendChild(once);
|
|
127
149
|
|
|
128
150
|
return modal;
|
|
129
151
|
}
|
|
130
152
|
|
|
131
153
|
function open(node, kind, tool) {
|
|
132
|
-
var form = dialog().
|
|
154
|
+
var form = dialog().querySelector('form');
|
|
133
155
|
var current = read(node) || {};
|
|
134
156
|
|
|
135
|
-
form.
|
|
136
|
-
form.
|
|
137
|
-
form.
|
|
138
|
-
form.
|
|
157
|
+
form.elements.effect.value = current.effect || '';
|
|
158
|
+
form.elements.duration.value = current.duration || 600;
|
|
159
|
+
form.elements.delay.value = current.delay || 0;
|
|
160
|
+
form.elements.once.checked = current.once !== false;
|
|
139
161
|
|
|
140
|
-
|
|
162
|
+
// One handler at a time: this node's, until the next open
|
|
163
|
+
form.onsubmit = function(e) {
|
|
141
164
|
e.preventDefault();
|
|
142
165
|
|
|
143
|
-
var effect = form.
|
|
166
|
+
var effect = form.elements.effect.value;
|
|
144
167
|
var value = effect ? {
|
|
145
168
|
effect: effect,
|
|
146
|
-
duration: parseInt(form.
|
|
147
|
-
delay: parseInt(form.
|
|
148
|
-
once: form.
|
|
169
|
+
duration: parseInt(form.elements.duration.value, 10) || 0,
|
|
170
|
+
delay: parseInt(form.elements.delay.value, 10) || 0,
|
|
171
|
+
once: form.elements.once.checked,
|
|
149
172
|
} : null;
|
|
150
173
|
|
|
151
174
|
var from = read(node);
|
|
152
175
|
write(node, value);
|
|
153
|
-
tool.
|
|
176
|
+
tool.classList.toggle('my-animation-set', !!value);
|
|
154
177
|
|
|
155
178
|
// Announced like the editor's own changes, for a host
|
|
156
179
|
// that listens: grideditor:animation-change
|
|
@@ -158,10 +181,10 @@
|
|
|
158
181
|
source: 'tool', from: from, to: value,
|
|
159
182
|
}));
|
|
160
183
|
|
|
161
|
-
window.bootstrap.Modal.getInstance(modal
|
|
162
|
-
}
|
|
184
|
+
window.bootstrap.Modal.getInstance(modal).hide();
|
|
185
|
+
};
|
|
163
186
|
|
|
164
|
-
window.bootstrap.Modal.getOrCreateInstance(modal
|
|
187
|
+
window.bootstrap.Modal.getOrCreateInstance(modal).show();
|
|
165
188
|
}
|
|
166
189
|
|
|
167
190
|
return {
|
|
@@ -169,46 +192,50 @@
|
|
|
169
192
|
// a row, a column, an element, a container's type, a pane
|
|
170
193
|
drawerTools: function(drawer, node, kind) {
|
|
171
194
|
var animated = ['row', 'column', 'section', 'text', 'element'].indexOf(kind) !== -1 ||
|
|
172
|
-
|
|
195
|
+
!!GridEditor.containers[kind];
|
|
173
196
|
if (!animated) { return; }
|
|
174
197
|
|
|
175
|
-
ge.createTool(drawer, ge.t('animation.tool'), 'my-animation-tool', 'bi bi-magic', function() {
|
|
198
|
+
var tool = ge.createTool(drawer, ge.t('animation.tool'), 'my-animation-tool', 'bi bi-magic', function() {
|
|
176
199
|
open(node, kind, tool);
|
|
177
200
|
});
|
|
178
201
|
|
|
179
202
|
// Drawers are built again on every init, so the tool
|
|
180
203
|
// reads the node rather than remembering anything
|
|
181
|
-
|
|
182
|
-
.toggleClass('my-animation-set', !!read(node));
|
|
204
|
+
tool.classList.toggle('my-animation-set', !!read(node));
|
|
183
205
|
},
|
|
184
206
|
};
|
|
185
207
|
};
|
|
186
208
|
|
|
187
|
-
})(
|
|
209
|
+
})();
|
|
188
210
|
</script>
|
|
189
211
|
|
|
190
212
|
<script>
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
214
|
+
document.getElementById('animation-source').textContent =
|
|
215
|
+
document.getElementById('animation-plugin').textContent.trim().replace(/^ {8}/gm, '');
|
|
193
216
|
|
|
194
|
-
|
|
217
|
+
var editor = new GridEditor('#myGrid', {
|
|
195
218
|
new_row_layouts: [[12], [6, 6], [4, 4, 4]],
|
|
196
219
|
content_types: ['tinymce'],
|
|
220
|
+
// tinyMCE 7 is GPL-2.0-or-later: 'gpl' accepts that licence.
|
|
221
|
+
// A commercial licence passes its own key here instead.
|
|
222
|
+
tinymce: { config: { license_key: 'gpl' } },
|
|
197
223
|
});
|
|
198
224
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
225
|
+
document.getElementById('myGrid').addEventListener('grideditor:animation-change', function(e) {
|
|
226
|
+
var payload = e.detail;
|
|
227
|
+
document.getElementById('log').textContent = 'The ' + payload.kind + ' now animates: ' +
|
|
228
|
+
(payload.to ? payload.to.effect : 'no');
|
|
202
229
|
});
|
|
203
230
|
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
document.getElementById('output').addEventListener('click', function() {
|
|
232
|
+
document.getElementById('html').textContent = editor.getPlainHtml();
|
|
206
233
|
});
|
|
207
234
|
|
|
208
235
|
// The published page: the plain html, and a few lines of the
|
|
209
236
|
// host's own that read data-animation. Nothing of grid-editor.
|
|
210
|
-
|
|
211
|
-
var html =
|
|
237
|
+
document.getElementById('published').addEventListener('click', function() {
|
|
238
|
+
var html = editor.getPlainHtml();
|
|
212
239
|
var page = window.open('', '_blank');
|
|
213
240
|
|
|
214
241
|
page.document.write(
|
|
@@ -227,7 +254,7 @@
|
|
|
227
254
|
'Scroll down: each node animates as it comes into view' +
|
|
228
255
|
'</div>' +
|
|
229
256
|
'<div class="container">' + html + '</div>' +
|
|
230
|
-
'<script>' +
|
|
257
|
+
'<script>' + document.getElementById('runtime').textContent + '<\/script>' +
|
|
231
258
|
'</body></html>'
|
|
232
259
|
);
|
|
233
260
|
page.document.close();
|
|
@@ -280,7 +307,7 @@
|
|
|
280
307
|
text, from its drawer, while you are typing: the attribute
|
|
281
308
|
is kept when the editor closes, although tinyMCE puts back
|
|
282
309
|
the attributes it found when it opened. The plugin does
|
|
283
|
-
nothing special for that - a plain <code>
|
|
310
|
+
nothing special for that - a plain <code>setAttribute()</code> -
|
|
284
311
|
and nothing special for the quote either, which is an
|
|
285
312
|
element: a block beside the texts, never inside one.
|
|
286
313
|
</p>
|
package/example/autocols.html
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css">
|
|
9
9
|
|
|
10
10
|
<!-- Javascript dependencies -->
|
|
11
|
-
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
|
|
12
11
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
|
13
12
|
|
|
14
13
|
<!-- Grid editor CSS -->
|
|
@@ -17,12 +16,12 @@
|
|
|
17
16
|
<!-- The editor, and the sections plugin: equal and auto sizes and
|
|
18
17
|
columns per row are the editor's own, sections are a plugin -->
|
|
19
18
|
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
|
20
|
-
<script src="../dist/
|
|
19
|
+
<script src="../dist/grideditor.min.js"></script>
|
|
21
20
|
<script src="../dist/plugins/grideditor.sections.min.js"></script>
|
|
22
21
|
|
|
23
22
|
<script>
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
24
|
+
var editor = new GridEditor('#myGrid', {
|
|
26
25
|
content_types: [],
|
|
27
26
|
|
|
28
27
|
// Sizes are numbers, 'equal' (col) or 'auto' (col-auto), and a
|
|
@@ -36,17 +35,18 @@
|
|
|
36
35
|
});
|
|
37
36
|
|
|
38
37
|
// A width chosen anywhere - tools, edge, panel - is a resize
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
document.getElementById('myGrid').addEventListener('grideditor:after-resize', function(e) {
|
|
39
|
+
var payload = e.detail;
|
|
40
|
+
document.getElementById('last').textContent = 'width at ' + payload.breakpoint + ': ' +
|
|
41
41
|
(payload.from === null ? 'from the row' : payload.from) + ' → ' +
|
|
42
42
|
(payload.to === null ? 'inherit' : payload.to) +
|
|
43
43
|
(payload.cleared && payload.cleared.length ? ' (took off ' + payload.cleared.map(function(entry) {
|
|
44
44
|
return entry.breakpoint;
|
|
45
|
-
}).join(', ') + ')' : '')
|
|
45
|
+
}).join(', ') + ')' : '');
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
document.getElementById('output').addEventListener('click', function() {
|
|
49
|
+
document.getElementById('html').textContent = editor.getHtml();
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
</script>
|