@themarioga/grid-editor 6.0.0-beta.3 → 6.0.0-beta.4
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/BUILDING.md +3 -1
- package/CHANGELOG.md +50 -1
- package/README.md +16 -5
- package/UPGRADING.md +36 -7
- package/dist/grideditor.css +14 -0
- package/dist/grideditor.min.css +1 -1
- package/dist/grideditor.min.css.map +1 -1
- package/dist/jquery.grideditor.bundle.min.js +2 -2
- package/dist/jquery.grideditor.js +303 -385
- package/dist/jquery.grideditor.min.js +1 -1
- package/dist/jquery.grideditor.min.js.map +1 -1
- package/dist/locales/grideditor.es.js +3 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +1 -1
- package/dist/plugins/grideditor.ckeditor.js +397 -3
- package/dist/plugins/grideditor.ckeditor.min.js +1 -1
- package/dist/plugins/grideditor.ckeditor.min.js.map +1 -1
- package/dist/plugins/grideditor.summernote.js +397 -3
- package/dist/plugins/grideditor.summernote.min.js +1 -1
- package/dist/plugins/grideditor.summernote.min.js.map +1 -1
- package/dist/plugins/grideditor.tinymce.js +397 -3
- package/dist/plugins/grideditor.tinymce.min.js +1 -1
- package/dist/plugins/grideditor.tinymce.min.js.map +1 -1
- package/dist/plugins/grideditor.visibility.js +1 -1
- package/dist/plugins/grideditor.visibility.min.js +1 -1
- package/dist/plugins/grideditor.visibility.min.js.map +1 -1
- package/docs/events.md +11 -2
- package/docs/locale-keys.md +12 -3
- package/docs/plugins.md +109 -46
- package/example/custom_editor.html +193 -0
- package/example/index.html +8 -0
- package/example/wrap_content.html +5 -3
- package/package.json +1 -1
- package/src/js/jquery.grideditor.js +303 -385
- package/src/js/locales/grideditor.es.js +3 -0
- package/src/js/plugins/grideditor.ckeditor.js +7 -3
- package/src/js/plugins/grideditor.summernote.js +7 -3
- package/src/js/plugins/grideditor.tinymce.js +7 -3
- package/src/js/plugins/grideditor.visibility.js +1 -1
- package/src/js/text/grideditor.text.js +389 -0
- package/src/less/grideditor.less +17 -0
package/docs/plugins.md
CHANGED
|
@@ -14,15 +14,18 @@ the one to read first if you are about to write your own.
|
|
|
14
14
|
<script src="dist/plugins/grideditor.elements.min.js"></script>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
There are
|
|
17
|
+
There are three kinds. A **container plugin** builds a type of container — it
|
|
18
18
|
registers under `$.fn.gridEditor.containers`, and the toolbar offers a button
|
|
19
19
|
for it. A **utility plugin** declares families of Bootstrap's responsive
|
|
20
20
|
utility classes — `$.fn.gridEditor.utilities` — and the editor edits them per
|
|
21
|
-
breakpoint. A **
|
|
22
|
-
editor — `$.fn.gridEditor.texts`, one per editor: tinyMCE, CKEditor,
|
|
23
|
-
summernote. A **feature plugin** is anything else the editor can do —
|
|
21
|
+
breakpoint. A **feature plugin** is anything else the editor can do —
|
|
24
22
|
`$.fn.gridEditor.features`, hooks into the canvas, and may contribute methods.
|
|
25
|
-
All
|
|
23
|
+
All three are factories called once per editor with the same handle.
|
|
24
|
+
|
|
25
|
+
Text is a feature plugin too. The core knows the grid and the host's *plain
|
|
26
|
+
content* - the markup it found that is not the grid's - and nothing of text:
|
|
27
|
+
the text editors, tinyMCE, CKEditor and summernote, are plugins, and so is an
|
|
28
|
+
editor a host writes itself. See [Text](#text).
|
|
26
29
|
|
|
27
30
|
The `plugins` setting names which of the loaded ones to use:
|
|
28
31
|
|
|
@@ -60,6 +63,7 @@ $.fn.gridEditor.containers.carousel = function(ge) {
|
|
|
60
63
|
|
|
61
64
|
return {
|
|
62
65
|
labelKey: 'container.add_carousel', // the toolbar button's label
|
|
66
|
+
iconClass: 'bi bi-images', // optional: the button shows it in place of the label
|
|
63
67
|
addPaneKey: 'container.add_slide', // the drawer's add pane tool
|
|
64
68
|
paneKind: 'slide', // the kind its panes report
|
|
65
69
|
|
|
@@ -77,6 +81,9 @@ $.fn.gridEditor.containers.carousel = function(ge) {
|
|
|
77
81
|
})(jQuery);
|
|
78
82
|
```
|
|
79
83
|
|
|
84
|
+
- **`iconClass`**, when given, is the toolbar button's face: the icon alone,
|
|
85
|
+
with the label as its title. Without one the button shows a plus and the
|
|
86
|
+
label.
|
|
80
87
|
- **`create(options)`** returns a detached container. It must carry
|
|
81
88
|
`data-ge-container="<type>"`: that attribute, and never a class, is how the
|
|
82
89
|
editor recognises one.
|
|
@@ -129,6 +136,9 @@ not change without a major version.
|
|
|
129
136
|
| `ge.rowFromLayout(layout)` | A detached row from a layout: `[8, 4]`, `['auto', 'equal']` or `{ row_cols, columns }` |
|
|
130
137
|
| `ge.drawerOf(node)` | A node's drawer: its first child, or for a content area the one beside it in its text block |
|
|
131
138
|
| `ge.textReady(block)` | A text editor has rewritten a content area: whatever the editor and its plugins put in there goes back in |
|
|
139
|
+
| `ge.attachPicker(tool, open)` | Hold a tool, or rest the pointer on it, and `open` is called: how a tool offers a choice |
|
|
140
|
+
| `ge.openPicker(anchor, choices, className?)` | The choice itself, as a strip under `anchor`: one button per `{ label, title, attributes, choose }` |
|
|
141
|
+
| `ge.closePicker()` | Close it; true when one was open, which is also a click's answer |
|
|
132
142
|
| `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` |
|
|
133
143
|
| `ge.toolbarItems(name)` | The toolbar buttons the feature plugin `name` declared, for showing and hiding them |
|
|
134
144
|
| `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 |
|
|
@@ -150,7 +160,10 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
150
160
|
kindOf: function(node) { … }, // what an event calls this node
|
|
151
161
|
onInit: function() { … }, // every init: put the furniture in
|
|
152
162
|
onDeinit: function() { … }, // every deinit: take it out again
|
|
163
|
+
onBeforeDeinit: function() { … }, // every deinit, before the drawers come off: close what you opened
|
|
153
164
|
onContentReady: function(area) { … }, // a rich text editor just took over, or rewrote a text
|
|
165
|
+
textTypes: function() { … }, // the text types this plugin edits, see "Text"
|
|
166
|
+
|
|
154
167
|
cuts: '[data-my-block]', // what cuts a text: a block of the column, never part of a text
|
|
155
168
|
onSortable: function(sortable) { … }, // declare your own sortable lists
|
|
156
169
|
blocks: '.ge-section', // more blocks the canvas and the columns move
|
|
@@ -211,10 +224,17 @@ animation for rows, columns, containers and elements, kept in a
|
|
|
211
224
|
|
|
212
225
|
A node's drawer is built again on every `init`, so a tool reads the node
|
|
213
226
|
rather than remembering anything about it.
|
|
214
|
-
- A **`toolbar`** item can also have an `iconClass`,
|
|
227
|
+
- A **`toolbar`** item can also have an `iconClass`, which it shows alone,
|
|
228
|
+
with the label as its title, where one without shows a plus and the label;
|
|
215
229
|
and a `source` for the add events, `tool` or `dragdrop` otherwise. With
|
|
216
230
|
`align: 'end'` it goes on the right of the toolbar, beside the source and
|
|
217
|
-
preview buttons, as
|
|
231
|
+
preview buttons, always as an icon - `bi bi-plus` when it has none.
|
|
232
|
+
`label`, a string or a function called whenever the toolbar is built, stands
|
|
233
|
+
in for `labelKey` when the label takes parameters; `className` goes on the
|
|
234
|
+
button. With `inColumn: true` what it makes belongs in a column, as a
|
|
235
|
+
container or a text does: a click puts it in a row and a column of its own
|
|
236
|
+
at the end of the canvas, and a drop anywhere but in a column does the
|
|
237
|
+
same where it was dropped.
|
|
218
238
|
|
|
219
239
|
- **`onSortable(sortable)`** is handed the function the editor makes all of its
|
|
220
240
|
own lists with. A plugin describes a list; it never touches the drag toolkit
|
|
@@ -257,53 +277,96 @@ plugin knows which of its parts move: the tabs plugin makes its strip sortable
|
|
|
257
277
|
and puts the panes back in strip order in `afterPaneMove`.
|
|
258
278
|
|
|
259
279
|
|
|
260
|
-
Text
|
|
261
|
-
|
|
280
|
+
Text
|
|
281
|
+
----
|
|
282
|
+
|
|
283
|
+
### Plain content
|
|
284
|
+
|
|
285
|
+
What the editor finds in a column that is not the grid's - loose markup, the
|
|
286
|
+
page it was started on before it had a row - it wraps in a content area with
|
|
287
|
+
no type: the host's **plain content**, `<div class="ge-content">`. While
|
|
288
|
+
editing it is a block with a drawer of two tools, move and delete, and no
|
|
289
|
+
gear; it is edited in the source, with the toolbar's code button, and nothing
|
|
290
|
+
in the editor makes a new one. `getHtml` saves it as it is, and it is plain
|
|
291
|
+
content again when the page comes back. Events call it `kind: 'plain'`.
|
|
262
292
|
|
|
263
|
-
A text
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
293
|
+
A text is a content area with a type on it - `data-ge-content-type` and the
|
|
294
|
+
class `ge-content-type-<type>` - and belongs to the plugin that declares the
|
|
295
|
+
type. A text whose type no plugin declares is a block to move and delete, and
|
|
296
|
+
its drawer says no editor for it is loaded.
|
|
297
|
+
|
|
298
|
+
### textTypes
|
|
299
|
+
|
|
300
|
+
A feature plugin that edits text declares its types, and that is all the
|
|
301
|
+
core asks of it:
|
|
267
302
|
|
|
268
303
|
```javascript
|
|
269
|
-
$.fn.gridEditor.
|
|
304
|
+
$.fn.gridEditor.features.mytext = function(ge) {
|
|
270
305
|
return {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
306
|
+
textTypes: function() {
|
|
307
|
+
return [{
|
|
308
|
+
type: 'mytext', // what data-ge-content-type says
|
|
309
|
+
label: 'My text', // what the choice of editor shows
|
|
310
|
+
available: function() { … }, // optional: false, and missingKey is logged instead
|
|
311
|
+
missingKey: 'error.mytext_missing', // optional
|
|
312
|
+
offered: true, // optional: false owns the type without offering it
|
|
313
|
+
edit: function(block) { … }, // the type is on it: take it over, open the editor
|
|
314
|
+
}];
|
|
315
|
+
},
|
|
278
316
|
};
|
|
279
317
|
};
|
|
280
318
|
```
|
|
281
319
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
the
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
-
|
|
290
|
-
|
|
291
|
-
the
|
|
292
|
-
|
|
293
|
-
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
320
|
+
The core uses them three ways:
|
|
321
|
+
|
|
322
|
+
- **Whose a text is.** A content area of a type declared here is the plugin's:
|
|
323
|
+
the core wraps it in a `.ge-text-block` while editing, as it does plain
|
|
324
|
+
content, and leaves the drawer to the plugin - put one in on `onInit`. Two
|
|
325
|
+
plugins declaring one type: the first one registered has it, and the second
|
|
326
|
+
is warned about once.
|
|
327
|
+
- **What plain content can become.** A click on plain content, with one type
|
|
328
|
+
offered, makes it a text of that type; with several, it offers them, in the
|
|
329
|
+
order the plugins were registered. The core fires `before-convert`, which
|
|
330
|
+
can cancel it, puts the type on the content area - nothing else about it
|
|
331
|
+
changes - takes its plain drawer off, fires `after-convert` and calls
|
|
332
|
+
`edit(block)`. See [events.md](events.md).
|
|
333
|
+
- **What `createColumn(size, { content })` holds.** A text of the first type
|
|
334
|
+
offered, or plain content when there is none.
|
|
335
|
+
|
|
336
|
+
A plugin opens its editor on a click on its own texts - the core only handles
|
|
337
|
+
clicks on plain content - and closes it in `onBeforeDeinit`, which every
|
|
338
|
+
`deinit` runs while the drawers and the text blocks are still there, before
|
|
339
|
+
`getHtml` reads the markup. Whatever the editor put on the content area comes
|
|
340
|
+
off there.
|
|
341
|
+
|
|
342
|
+
### The shipped text editors
|
|
343
|
+
|
|
344
|
+
`grideditor.tinymce.js`, `grideditor.ckeditor.js` and
|
|
345
|
+
`grideditor.summernote.js` each carry what text is to the editor - the text
|
|
346
|
+
block's drawer, the *Text* buttons in the toolbar and the *Add text* tool in
|
|
347
|
+
each column, `createText`, opening an editor on a click and closing it with
|
|
348
|
+
the host's attributes put back, and `textTypes` - from
|
|
349
|
+
`src/js/text/grideditor.text.js`, which the build puts at the top of each.
|
|
350
|
+
However many a page loads, that is installed once.
|
|
351
|
+
|
|
352
|
+
The editors offered are `content_types`, every one loaded by default, in the
|
|
353
|
+
order the page loaded them; the `plugins` setting does not choose them. A
|
|
354
|
+
text of an editor that is loaded but not offered is still edited.
|
|
355
|
+
|
|
356
|
+
### A text editor of your own
|
|
357
|
+
|
|
358
|
+
A feature plugin with `textTypes`, a drawer for its texts, a toolbar item
|
|
359
|
+
with `inColumn: true` if it makes new ones, a click handler that opens its
|
|
360
|
+
editor, and `onBeforeDeinit` to close it.
|
|
361
|
+
[example/custom_editor.html](../example/custom_editor.html) is one, in full,
|
|
362
|
+
on the browser's `contenteditable`, on a page that loads none of the shipped
|
|
363
|
+
editors.
|
|
364
|
+
|
|
365
|
+
Up to 5.x an editor of a host's own registered under
|
|
366
|
+
`$.fn.gridEditor.RTEs`, and in 5.x and the 6.0 betas under
|
|
367
|
+
`$.fn.gridEditor.texts`. 6.0 removes the first - what is registered there is
|
|
368
|
+
ignored, with a warning - and `texts` is the shipped editors' own registry,
|
|
369
|
+
not a contract.
|
|
307
370
|
|
|
308
371
|
|
|
309
372
|
Utility plugins
|
|
@@ -0,0 +1,193 @@
|
|
|
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 -->
|
|
11
|
+
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
|
|
12
|
+
<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
|
+
|
|
14
|
+
<!-- Grid editor CSS -->
|
|
15
|
+
<link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
|
|
16
|
+
|
|
17
|
+
<!-- The editor, and no text editor of the shipped ones: the one this page
|
|
18
|
+
edits text with is written below -->
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
|
20
|
+
<script src="../dist/jquery.grideditor.min.js"></script>
|
|
21
|
+
|
|
22
|
+
<!-- A text editor of the page's own. It is a feature plugin like any
|
|
23
|
+
other: the core knows nothing of text, and asks the plugins through
|
|
24
|
+
textTypes which types there are. This one edits with the browser's
|
|
25
|
+
own contenteditable. -->
|
|
26
|
+
<script id="simpletext-plugin">
|
|
27
|
+
(function($) {
|
|
28
|
+
|
|
29
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
30
|
+
'simpletext.label': 'Simple text',
|
|
31
|
+
'simpletext.add': 'Simple text',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
var TYPE = 'simpletext';
|
|
35
|
+
|
|
36
|
+
$.fn.gridEditor.features.simpletext = function(ge) {
|
|
37
|
+
|
|
38
|
+
/** A content area of this plugin's: its type is on it. */
|
|
39
|
+
function isOurs(area) {
|
|
40
|
+
return area.attr('data-ge-content-type') === TYPE;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function start(area) {
|
|
44
|
+
if (area.hasClass('ge-rte-active')) { return; }
|
|
45
|
+
|
|
46
|
+
area.addClass('ge-rte-active').attr('contenteditable', 'true').trigger('focus');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Whatever start put on the content area comes off: what is
|
|
50
|
+
// left is what getHtml saves
|
|
51
|
+
function stop(area) {
|
|
52
|
+
area.removeClass('ge-rte-active').removeAttr('contenteditable');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A text's drawer. The editor wraps each content area of a
|
|
57
|
+
* column in a .ge-text-block while editing, and leaves the
|
|
58
|
+
* drawer of a type a plugin declares to that plugin.
|
|
59
|
+
*/
|
|
60
|
+
function createDrawer(textBlock) {
|
|
61
|
+
var area = textBlock.children('.ge-content');
|
|
62
|
+
var drawer = $('<div class="ge-tools-drawer ge-text-drawer" />').prependTo(textBlock);
|
|
63
|
+
|
|
64
|
+
ge.createMoveTool(drawer);
|
|
65
|
+
ge.createTool(drawer, ge.t('tool.delete_text'), 'ge-delete-text', 'bi bi-trash', function() {
|
|
66
|
+
ge.deleteNode('text', area, ge.t('confirm.delete_text'), function(removed) {
|
|
67
|
+
stop(area);
|
|
68
|
+
textBlock.slideUp(function() {
|
|
69
|
+
textBlock.remove();
|
|
70
|
+
removed();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function onClick() {
|
|
77
|
+
if (isOurs($(this))) { start($(this)); }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
// The types this plugin edits. The core uses them to know
|
|
82
|
+
// whose a content area is, and to offer them when the
|
|
83
|
+
// host's plain content is clicked: edit() is handed the
|
|
84
|
+
// content area once the core has written the type on it
|
|
85
|
+
textTypes: function() {
|
|
86
|
+
return [{
|
|
87
|
+
type: TYPE,
|
|
88
|
+
label: ge.t('simpletext.label'),
|
|
89
|
+
edit: function(area) {
|
|
90
|
+
var textBlock = area.parent('.ge-text-block');
|
|
91
|
+
if (textBlock.length && !textBlock.children('.ge-tools-drawer').length) {
|
|
92
|
+
createDrawer(textBlock);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
start(area);
|
|
96
|
+
},
|
|
97
|
+
}];
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// A button to make a new text, in a row of its own or
|
|
101
|
+
// where it is dropped in a column
|
|
102
|
+
toolbar: [{
|
|
103
|
+
labelKey: 'simpletext.add',
|
|
104
|
+
iconClass: 'bi bi-fonts',
|
|
105
|
+
kind: 'text',
|
|
106
|
+
inColumn: true,
|
|
107
|
+
create: function() {
|
|
108
|
+
return $('<div class="ge-content" />')
|
|
109
|
+
.addClass('ge-content-type-' + TYPE)
|
|
110
|
+
.attr('data-ge-content-type', TYPE)
|
|
111
|
+
.html('<p>Write here</p>');
|
|
112
|
+
},
|
|
113
|
+
}],
|
|
114
|
+
|
|
115
|
+
onInit: function() {
|
|
116
|
+
ge.canvas.find('.ge-text-block').each(function() {
|
|
117
|
+
var textBlock = $(this);
|
|
118
|
+
if (textBlock.children('.ge-tools-drawer').length) { return; }
|
|
119
|
+
if (isOurs(textBlock.children('.ge-content'))) { createDrawer(textBlock); }
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
ge.canvas.off('click.simpletext').on('click.simpletext', '.ge-content', onClick);
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// Before the drawers and the text blocks come off
|
|
126
|
+
onBeforeDeinit: function() {
|
|
127
|
+
ge.canvas.find('.ge-content').each(function() {
|
|
128
|
+
if (isOurs($(this))) { stop($(this)); }
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
onDeinit: function() {
|
|
133
|
+
ge.canvas.off('click.simpletext');
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
})(jQuery);
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<script>
|
|
142
|
+
$(function() {
|
|
143
|
+
$('#myGrid').gridEditor({
|
|
144
|
+
new_row_layouts: [[12], [6, 6], [4, 4, 4]],
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
$('#output').on('click', function() {
|
|
148
|
+
$('#html').text($('#myGrid').gridEditor('getHtml'));
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<title>Grid Editor example - a text editor of your own</title>
|
|
154
|
+
</head>
|
|
155
|
+
<body>
|
|
156
|
+
<!-- Back to the demo index -->
|
|
157
|
+
<div class="container pt-3">
|
|
158
|
+
<a class="link-secondary" href="index.html"><i class="bi bi-arrow-left"></i> All demos</a>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div class="container py-3">
|
|
162
|
+
<h2>A text editor of your own</h2>
|
|
163
|
+
<p class="text-body-secondary">
|
|
164
|
+
No tinyMCE, CKEditor or summernote on this page: its text editor is
|
|
165
|
+
the plugin in the page's source, a few dozen lines on the browser's
|
|
166
|
+
<code>contenteditable</code>. The markup below had no text editor's
|
|
167
|
+
type on it, so the editor took it for the host's <em>plain
|
|
168
|
+
content</em>: it can be moved and deleted, and a click makes it a
|
|
169
|
+
text of this editor. The second column was saved as one already.
|
|
170
|
+
See <a href="../docs/plugins.md">docs/plugins.md</a>.
|
|
171
|
+
</p>
|
|
172
|
+
|
|
173
|
+
<div id="myGrid">
|
|
174
|
+
<div class="row">
|
|
175
|
+
<div class="col-lg-6">
|
|
176
|
+
<h3>Plain content</h3>
|
|
177
|
+
<p>Loose markup of the page's own. Click it and it is a simple text.</p>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="col-lg-6">
|
|
180
|
+
<div class="ge-content ge-content-type-simpletext" data-ge-content-type="simpletext">
|
|
181
|
+
<p>A simple text, saved as one: a click edits it.</p>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<p class="mt-4">
|
|
188
|
+
<button type="button" class="btn btn-outline-primary btn-sm" id="output">Show getHtml</button>
|
|
189
|
+
</p>
|
|
190
|
+
<pre class="bg-body-tertiary border rounded p-3 small"><code id="html"></code></pre>
|
|
191
|
+
</div>
|
|
192
|
+
</body>
|
|
193
|
+
</html>
|
package/example/index.html
CHANGED
|
@@ -61,6 +61,14 @@
|
|
|
61
61
|
<span class="text-body-secondary">The plugin model, with a container plugin written in the page itself</span>
|
|
62
62
|
</a>
|
|
63
63
|
|
|
64
|
+
<a class="list-group-item list-group-item-action" href="custom_editor.html">
|
|
65
|
+
<div class="d-flex justify-content-between">
|
|
66
|
+
<strong>A text editor of your own</strong>
|
|
67
|
+
<code class="text-body-secondary">custom_editor.html</code>
|
|
68
|
+
</div>
|
|
69
|
+
<span class="text-body-secondary">No shipped text editor: one written in the page as a plugin, on the textTypes hook</span>
|
|
70
|
+
</a>
|
|
71
|
+
|
|
64
72
|
<a class="list-group-item list-group-item-action" href="attributes.html">
|
|
65
73
|
<div class="d-flex justify-content-between">
|
|
66
74
|
<strong>A plugin with a modal</strong>
|
|
@@ -63,9 +63,11 @@
|
|
|
63
63
|
<code>.col-*</code> anywhere. Grid editor does not refuse it: it
|
|
64
64
|
wraps all of it into one row with a single
|
|
65
65
|
<code>col-lg-12</code> column, and from there it is an ordinary
|
|
66
|
-
grid.
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
grid. What was in there is the page's <em>plain content</em>: a
|
|
67
|
+
block to move and delete, edited in the source, until a click
|
|
68
|
+
makes it a text of tinyMCE's. Add rows, split the column, edit the
|
|
69
|
+
text, then press <em>Refresh</em> to see the html that comes out:
|
|
70
|
+
as <code>getHtml</code> returns it, to save and edit again, and as
|
|
69
71
|
<code>getPlainHtml</code> returns it, to publish.
|
|
70
72
|
</p>
|
|
71
73
|
|
package/package.json
CHANGED