@themarioga/grid-editor 6.0.0-beta.3 → 6.0.0-beta.5

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.
Files changed (50) hide show
  1. package/BUILDING.md +3 -1
  2. package/CHANGELOG.md +74 -1
  3. package/README.md +71 -5
  4. package/UPGRADING.md +36 -7
  5. package/dist/grideditor.css +60 -0
  6. package/dist/grideditor.min.css +1 -1
  7. package/dist/grideditor.min.css.map +1 -1
  8. package/dist/jquery.grideditor.bundle.min.js +2 -2
  9. package/dist/jquery.grideditor.js +353 -402
  10. package/dist/jquery.grideditor.min.js +1 -1
  11. package/dist/jquery.grideditor.min.js.map +1 -1
  12. package/dist/locales/grideditor.es.js +7 -0
  13. package/dist/locales/grideditor.es.min.js +1 -1
  14. package/dist/locales/grideditor.es.min.js.map +1 -1
  15. package/dist/plugins/grideditor.ckeditor.js +397 -3
  16. package/dist/plugins/grideditor.ckeditor.min.js +1 -1
  17. package/dist/plugins/grideditor.ckeditor.min.js.map +1 -1
  18. package/dist/plugins/grideditor.codemirror-inline.js +190 -0
  19. package/dist/plugins/grideditor.codemirror-inline.min.js +2 -0
  20. package/dist/plugins/grideditor.codemirror-inline.min.js.map +1 -0
  21. package/dist/plugins/grideditor.codemirror.js +79 -0
  22. package/dist/plugins/grideditor.codemirror.min.js +2 -0
  23. package/dist/plugins/grideditor.codemirror.min.js.map +1 -0
  24. package/dist/plugins/grideditor.summernote.js +397 -3
  25. package/dist/plugins/grideditor.summernote.min.js +1 -1
  26. package/dist/plugins/grideditor.summernote.min.js.map +1 -1
  27. package/dist/plugins/grideditor.tinymce.js +397 -3
  28. package/dist/plugins/grideditor.tinymce.min.js +1 -1
  29. package/dist/plugins/grideditor.tinymce.min.js.map +1 -1
  30. package/dist/plugins/grideditor.visibility.js +1 -1
  31. package/dist/plugins/grideditor.visibility.min.js +1 -1
  32. package/dist/plugins/grideditor.visibility.min.js.map +1 -1
  33. package/docs/events.md +17 -2
  34. package/docs/locale-keys.md +25 -3
  35. package/docs/plugins.md +124 -46
  36. package/example/codemirror.html +103 -0
  37. package/example/custom_editor.html +193 -0
  38. package/example/index.html +16 -0
  39. package/example/wrap_content.html +5 -3
  40. package/package.json +1 -1
  41. package/src/js/jquery.grideditor.js +353 -402
  42. package/src/js/locales/grideditor.es.js +7 -0
  43. package/src/js/plugins/grideditor.ckeditor.js +7 -3
  44. package/src/js/plugins/grideditor.codemirror-inline.js +190 -0
  45. package/src/js/plugins/grideditor.codemirror.js +79 -0
  46. package/src/js/plugins/grideditor.summernote.js +7 -3
  47. package/src/js/plugins/grideditor.tinymce.js +7 -3
  48. package/src/js/plugins/grideditor.visibility.js +1 -1
  49. package/src/js/text/grideditor.text.js +389 -0
  50. package/src/less/grideditor.less +71 -0
package/BUILDING.md CHANGED
@@ -23,7 +23,9 @@ the languages and the container plugins it actually wants. See
23
23
 
24
24
  The text editor plugins - tinyMCE, CKEditor and summernote - are built to
25
25
  `dist/plugins/` like the others, and like them are not part of the main
26
- bundle. Up to 5.x the bundle carried a copy of each.
26
+ bundle. Up to 5.x the bundle carried a copy of each. Each one is built as
27
+ `src/js/text/grideditor.text.js`, what every text editor shares, followed by
28
+ the editor's own file: that shared file is never published on its own.
27
29
 
28
30
  One more file comes out of it: `dist/jquery.grideditor.bundle.min.js`, the
29
31
  minified editor concatenated with the copy of SortableJS in `node_modules`,
package/CHANGELOG.md CHANGED
@@ -5,6 +5,79 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
 
8
+ ## [6.0.0-beta.5] - 2026-09-28
9
+ ### Added
10
+ - `edit_source`: whether the toolbar has its source button, `true` by
11
+ default.
12
+ - The codemirror plugin, `grideditor.codemirror.js`: the source view in
13
+ CodeMirror 5, highlighted and with line numbers, where it was a plain
14
+ textarea; `codemirror.config` for CodeMirror's own options. See
15
+ [example/codemirror.html](example/codemirror.html).
16
+ - `onSourceOpen` and `onSourceClose` for a feature plugin: the source view
17
+ opening, with the canvas's html in the textarea, and closing.
18
+ - The codemirror-inline plugin, `grideditor.codemirror-inline.js`: a </> tool
19
+ in the drawer of every row, column, text, element, section and container,
20
+ and of the host's plain content, that edits the block's html in place in
21
+ CodeMirror - the block itself and everything in it - and puts what was
22
+ written in its place on *Apply*, through the new `before-edit-html`
23
+ (cancelable) and `after-edit-html` events.
24
+ - `plainTools` for a feature plugin: tools in the drawer of the host's plain
25
+ content, which has no `drawerTools`.
26
+
27
+ ### Fixed
28
+ - `destroy` with the source view open left the canvas hidden and the html
29
+ being written unused; it closes the source first.
30
+
31
+
32
+ ## [6.0.0-beta.4] - 2026-09-28
33
+ ### Added
34
+ - `iconClass` for a container plugin and a text editor plugin: their toolbar
35
+ button shows the icon alone, with the label as its title, where it showed a
36
+ plus and the label.
37
+ - **Plain content.** What the editor wraps that is not the grid's - loose
38
+ markup in a column, a page with no row - is the host's plain content: a
39
+ content area with no text type, `<div class="ge-content">`. A block to move
40
+ and delete, with no gear, edited in the source, and never made by the
41
+ editor's tools; `kind: 'plain'` in the events. With a text editor loaded a
42
+ click makes it a text of that editor, or of the one chosen when several are
43
+ offered, through the new `before-convert` (cancelable) and `after-convert`
44
+ events. See [docs/plugins.md](docs/plugins.md#text).
45
+ - `textTypes` for a feature plugin: the text types it edits, which is how the
46
+ core knows whose a text is and what plain content can be made.
47
+ [example/custom_editor.html](example/custom_editor.html) is a text editor
48
+ written that way, with none of the shipped ones.
49
+ - `onBeforeDeinit` for a plugin, run by every `deinit` before the drawers come
50
+ off; `inColumn`, `label` and `className` for a feature plugin's toolbar
51
+ item; `ge.attachPicker`, `ge.openPicker` and `ge.closePicker` in the handle.
52
+
53
+ ### Changed
54
+ - **Text is out of the core.** The text block's drawer, the *Text* buttons,
55
+ the *Add text* tool, `createText`, opening and closing an editor and the
56
+ `content_types`, `text_tools` and `text_classes` settings are the text
57
+ editor plugins': each of `grideditor.tinymce.js`, `grideditor.ckeditor.js`
58
+ and `grideditor.summernote.js` carries them, installed once however many a
59
+ page loads. Without one, `createText` warns and returns null.
60
+ - **New columns start empty**, whatever makes them: the add column tool, the
61
+ row buttons, `createRow`, `createColumn`, a container's or a pane's region.
62
+ `createColumn(size, { content })` holds its content as a text of the first
63
+ editor offered, or as plain content with none.
64
+ - Loose content was wrapped as a text of the first `content_types`; it is
65
+ plain content now, and a click makes it a text.
66
+ - `content_types` defaults to every text editor loaded, in the order the page
67
+ loaded them, where it was `['tinymce']`.
68
+ - A text whose type no plugin declares has a drawer of move, the missing
69
+ editor's notice and delete, with no gear, whatever else is loaded.
70
+ - The *Text* buttons stand after the containers' in the toolbar.
71
+ - A feature plugin's toolbar item with an `iconClass` shows the icon alone,
72
+ with its label as the title, wherever it is in the toolbar. It showed the
73
+ icon and the label unless it had `align: 'end'`.
74
+
75
+ ### Removed
76
+ - `$.fn.gridEditor.RTEs`, 5.x's registry of text editors: what is registered
77
+ there is ignored, with a warning. `$.fn.gridEditor.texts` is no longer a
78
+ documented contract: it is the shipped editors' own registry.
79
+
80
+
8
81
  ## [6.0.0-beta.3] - 2026-09-23
9
82
  ### Changed
10
83
  - Which editor edits a text is shown first in its settings, as a read-only
@@ -120,7 +193,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
120
193
  `$.fn.gridEditor.texts`, with a contract a host can write its own editor to:
121
194
  `start`, `stop`, `initialContent`, `available`, and `ge.textReady` in the
122
195
  handle. They are chosen by `content_types`, not by the `plugins` setting.
123
- See [docs/plugins.md](docs/plugins.md#text-editor-plugins).
196
+ See [docs/plugins.md](docs/plugins.md#text).
124
197
 
125
198
  ### Deprecated
126
199
  - The copies of the three text editors in the main bundle. A page that edits
package/README.md CHANGED
@@ -120,10 +120,10 @@ $('#myGrid').gridEditor('method', argument);
120
120
  | `getView` | — | `String` | The view the editor is in |
121
121
  | `setLocale` | `code` | `this` | Switch language and re-render the controls |
122
122
  | `createRow` | `layout?`, `options?` | `jQuery` | A row, optionally with columns: `createRow([8, 4])`, `createRow(['auto', 'equal'])`, `createRow({ row_cols: { xs: 1, md: 3 }, columns: 6 })` |
123
- | `createColumn` | `size`, `options?` | `jQuery` | A column: units, `'equal'` or `'auto'`; no size into a row with row-cols takes the row's share. `options`: `offset`, `content` |
123
+ | `createColumn` | `size`, `options?` | `jQuery` | An empty column: units, `'equal'` or `'auto'`; no size into a row with row-cols takes the row's share. `options`: `offset`, `content` - a text of the first editor offered, or plain content with none |
124
124
  | `createSection` | `options?` | `jQuery` | A section, with the sections plugin. `options`: `width` (`'fixed'`, `'fluid'` or a breakpoint), `rows` (layouts), and a placement |
125
125
  | `createElement` | `content`, `options?` | `jQuery` | Host markup wrapped as an element. `options`: `type`, `label` |
126
- | `createText` | `type?`, `options?` | `jQuery` | A content area for a text editor, the first one offered by default. `options`: `content`, and a placement. `null` if the editor is not loaded |
126
+ | `createText` | `type?`, `options?` | `jQuery` | A content area for a text editor, the first one offered by default. `options`: `content`, and a placement. `null` if the editor is not loaded, or no text editor is |
127
127
  | `createContainer` | `type`, `options?` | `jQuery` | `'tabs'`, `'accordion'` or `'popup'` |
128
128
  | `addTab` | `container`, `options?` | `jQuery` | Appends a tab, returns its pane |
129
129
  | `addAccordionItem` | `container`, `options?` | `jQuery` | Appends an item, returns its body |
@@ -444,6 +444,16 @@ $('#myGrid').gridEditor('createText', { content: '<p>Hello</p>', appendTo: '#myC
444
444
  A text whose editor's plugin is not loaded is still a block, to move and
445
445
  delete, and its drawer says it cannot be edited.
446
446
 
447
+ What the editor finds in a column that is not the grid's - loose markup, or a
448
+ page that had no row at all - is the host's *plain content*: a content area
449
+ with no text editor's type on it. It moves and deletes like any block, is
450
+ edited in the source (the toolbar's code button, or the codemirror-inline
451
+ plugin's </> tool), and nothing in the editor makes a new one. With a text editor loaded, a click makes it a text of that
452
+ editor - of the one chosen, when there are several - through the
453
+ `before-convert` and `after-convert` events. New columns start empty, and
454
+ `createColumn(size, { content })` holds its content as a text of the first
455
+ editor offered, or as plain content with none.
456
+
447
457
  __`text_tools`:__ Extra tools on every text drawer, same shape as `row_tools`.
448
458
 
449
459
  __`text_classes`:__ Preset class toggles on a text's settings panel, as `row_classes`.
@@ -698,6 +708,61 @@ $('form.myForm').on('submit', function() {
698
708
  });
699
709
  ```
700
710
 
711
+ ### Source view
712
+
713
+ The toolbar's <i>code</i> button turns the canvas into its html, to edit by
714
+ hand, and back again with what was written.
715
+
716
+ __`edit_source`:__ Whether the toolbar has that button. Default value: `true`.
717
+
718
+ ```javascript
719
+ $('#myGrid').gridEditor({
720
+ edit_source: false,
721
+ });
722
+ ```
723
+
724
+ The html is edited in a plain textarea. With the codemirror plugin it is
725
+ edited in [CodeMirror 5](https://codemirror.net/5/), highlighted and with line
726
+ numbers - load CodeMirror, its `htmlmixed` mode and the modes it is made of,
727
+ then the plugin ([example](example/codemirror.html)):
728
+
729
+ ```html
730
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/lib/codemirror.min.css">
731
+ <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/lib/codemirror.min.js"></script>
732
+ <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/xml/xml.min.js"></script>
733
+ <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/javascript/javascript.min.js"></script>
734
+ <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/css/css.min.js"></script>
735
+ <script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/htmlmixed/htmlmixed.min.js"></script>
736
+ <script src="grid-editor/dist/plugins/grideditor.codemirror.min.js"></script>
737
+ ```
738
+
739
+ __`codemirror.config`:__ Anything `CodeMirror.fromTextArea` takes, over the
740
+ plugin's defaults: `mode: 'htmlmixed'`, `lineNumbers`, `lineWrapping`, a tab
741
+ of 2.
742
+
743
+ ```javascript
744
+ $('#myGrid').gridEditor({
745
+ codemirror: { config: { theme: 'monokai' } },
746
+ });
747
+ ```
748
+
749
+ CodeMirror 5 rather than 6: 6 comes as ES modules, for a bundler, where 5
750
+ loads from a script tag like the rest of the page. Without CodeMirror loaded
751
+ the source view is the textarea, and the console says why.
752
+
753
+ The codemirror-inline plugin edits one block's html instead of the whole
754
+ canvas's: a </> tool in the drawer of every row, column, text, element,
755
+ section and container, and of the host's plain content, opens the block's
756
+ html - the block itself and everything in it - in CodeMirror where the block
757
+ was, and *Apply* puts what was written in its place, through the
758
+ `before-edit-html` and `after-edit-html` events. A tab or an accordion item
759
+ has no tool of its own: its html is its container's. It uses CodeMirror the
760
+ same way, `codemirror.config` included, and a textarea without it.
761
+
762
+ ```html
763
+ <script src="grid-editor/dist/plugins/grideditor.codemirror-inline.min.js"></script>
764
+ ```
765
+
701
766
  ### Rich text editor options
702
767
 
703
768
  Grid editor comes with support for the following rich text editors (RTEs), each a plugin of its own to load after the editor:
@@ -708,10 +773,11 @@ Grid editor comes with support for the following rich text editors (RTEs), each
708
773
  A text editor is chosen by `content_types`, not by the `plugins` setting: a page
709
774
  that names its containers in `plugins` still has its editor. Summernote 0.9.1
710
775
  calls `$.now()`, which jQuery 4 removed; its plugin gives it back, and only if
711
- it is missing. [docs/plugins.md](docs/plugins.md#text-editor-plugins) says how
712
- to write a plugin for another editor.
776
+ it is missing. Another editor is a plugin of your own:
777
+ [docs/plugins.md](docs/plugins.md#text) says how, and
778
+ [example/custom_editor.html](example/custom_editor.html) is one.
713
779
 
714
- __`content_types`:__ Specify the RTE to use. Valid values: `['tinymce']`, `['summernote']`, `['ckeditor']`, or the name of a text editor plugin of your own. Default value: `['tinymce']`.
780
+ __`content_types`:__ Specify the RTEs to offer, in order. Valid values: any of `'tinymce'`, `'summernote'`, `'ckeditor'` whose plugin is loaded. Default value: every text editor loaded, in the order the page loaded them.
715
781
 
716
782
  ```javascript
717
783
  $('#myGrid').gridEditor({
package/UPGRADING.md CHANGED
@@ -1,9 +1,11 @@
1
1
  Upgrading from grid-editor `5.*` to `6.*`
2
2
  =========================================
3
3
 
4
- Two changes make it a major: **elements are blocks of the column**, no longer
5
- part of a text, and **the text editors are not in the main bundle**. Markup
6
- 5.x saved loads as it is, and `getPlainHtml` publishes the same from it.
4
+ Three changes make it a major: **elements are blocks of the column**, no longer
5
+ part of a text, **the text editors are not in the main bundle** - text itself
6
+ is theirs, not the core's - and **what is not the grid's is the host's plain
7
+ content**. Markup 5.x saved loads as it is, and `getPlainHtml` publishes the
8
+ same from it.
7
9
 
8
10
  * __Load your text editor as a plugin.__ tinyMCE, CKEditor and summernote are
9
11
  plugins in `dist/plugins/`, loaded after the editor:
@@ -62,10 +64,37 @@ part of a text, and **the text editors are not in the main bundle**. Markup
62
64
  element's attributes through tinyMCE's `undoManager.transact` can write them
63
65
  with a plain `attr()`.
64
66
 
65
- * __An integration of your own under `$.fn.gridEditor.RTEs`__ still works,
66
- wrapped, with a warning that it is deprecated. Register it under
67
- `$.fn.gridEditor.texts` instead; [docs/plugins.md](docs/plugins.md#text-editor-plugins)
68
- has the contract. `RTEs` goes in 7.0.
67
+ * __Loose content is plain content, not a text.__ Up to 5.x the markup the
68
+ editor found loose in a column - or a whole page with no row - was wrapped
69
+ as a text of the first `content_types`, `<div class="ge-content"
70
+ data-ge-content-type="tinymce">`. Now it is wrapped with no type, as the
71
+ host's plain content: a block to move and delete, edited in the source, and
72
+ a click with a text editor loaded makes it a text, through
73
+ `before-convert` and `after-convert`. Markup 5.x saved, with its content
74
+ areas typed, loads as texts, as before. What to do: nothing, unless you
75
+ read the saved markup expecting every content area to carry a type.
76
+
77
+ * __New columns are empty.__ A column the add column tool, a row button,
78
+ `createRow` or `createColumn` makes - and a new container's or pane's
79
+ region - has no content area in it. Add a text with the column's *Add text*
80
+ tool, the toolbar's *Text* button or `createText`. `createColumn(size, {
81
+ content })` still holds its content: as a text of the first editor
82
+ offered, or as plain content with none.
83
+
84
+ * __`content_types` defaults to every text editor loaded__, in the order the
85
+ page loaded them, where it was `['tinymce']`. A page that loads one editor
86
+ needs no `content_types`; one that loads several and wants one names it.
87
+
88
+ * __`text_tools`, `text_classes` and `createText` are the text editors'.__
89
+ They work as before with any of the shipped editors loaded; with none,
90
+ `createText` warns and returns null.
91
+
92
+ * __An integration of your own under `$.fn.gridEditor.RTEs`__ is ignored,
93
+ with a warning, and so is one under `$.fn.gridEditor.texts` on a page
94
+ that loads none of the shipped editors: `texts` is their own registry. An
95
+ editor of your own is a feature plugin that declares its type with
96
+ `textTypes`; [docs/plugins.md](docs/plugins.md#text) has the contract, and
97
+ [example/custom_editor.html](example/custom_editor.html) is one in full.
69
98
 
70
99
 
71
100
  Upgrading from grid-editor `4.*` to `5.*`
@@ -65,6 +65,52 @@
65
65
  width: 100%;
66
66
  display: none;
67
67
  }
68
+ /* A block's html edited in place, with the codemirror-inline plugin: the
69
+ block is hidden behind its editor while it is open */
70
+ .ge-canvas.ge-editing .ge-code-hidden {
71
+ display: none !important;
72
+ }
73
+ .ge-canvas.ge-editing .ge-tools-drawer.ge-code-inline {
74
+ position: relative;
75
+ width: 100%;
76
+ margin: 0 0 5px;
77
+ padding: 4px;
78
+ background: #f8f9fa;
79
+ border: 1px solid #ced4da;
80
+ border-radius: 4px;
81
+ cursor: auto;
82
+ -webkit-user-select: text;
83
+ user-select: text;
84
+ }
85
+ .ge-canvas.ge-editing .ge-tools-drawer.ge-code-inline > .ge-code-inline-source {
86
+ width: 100%;
87
+ min-height: 120px;
88
+ font-family: monospace;
89
+ font-size: 13px;
90
+ }
91
+ .ge-canvas.ge-editing .ge-tools-drawer.ge-code-inline .CodeMirror {
92
+ height: auto;
93
+ border: 1px solid #ced4da;
94
+ font-size: 13px;
95
+ }
96
+ .ge-canvas.ge-editing .ge-tools-drawer.ge-code-inline .CodeMirror-scroll {
97
+ min-height: 120px;
98
+ max-height: 60vh;
99
+ }
100
+ .ge-canvas.ge-editing .ge-tools-drawer.ge-code-inline > .ge-code-inline-bar {
101
+ display: flex;
102
+ gap: 4px;
103
+ justify-content: flex-end;
104
+ padding-top: 4px;
105
+ }
106
+ /* The source view in a code editor, with the codemirror plugin: where the
107
+ textarea was, and as wide */
108
+ .ge-code-editor {
109
+ width: 100%;
110
+ border: 1px solid #ced4da;
111
+ border-radius: 4px;
112
+ font-size: 13px;
113
+ }
68
114
  /* Not editing */
69
115
  .ge-canvas .ge-tools-drawer {
70
116
  display: none;
@@ -295,6 +341,8 @@
295
341
  rather than solid, so a page full of them still reads as content */
296
342
  /* A text block: a content area and, beside it rather than inside,
297
343
  where the text editor would take it, its drawer */
344
+ /* The host's plain content: a block to move and delete, edited in the
345
+ source - greyer than a text, which an editor edits in place */
298
346
  /* A column with nothing in it but its drawer still has room to drop a
299
347
  block into */
300
348
  /* Sorting. The dragged node stays in the list and shows where it would
@@ -567,6 +615,8 @@
567
615
  /* Except when something in it is in use: its settings, a choice it
568
616
  offers, a drag */
569
617
  /* With its settings open it spans the text, so the panel has room */
618
+ /* The choice of editor a click on plain content offers hangs off
619
+ the drawer, which sits at the right: so it opens leftwards */
570
620
  }
571
621
  .ge-canvas.ge-editing .ge-text-block > .ge-text-drawer {
572
622
  position: absolute;
@@ -615,6 +665,16 @@
615
665
  left: 0;
616
666
  border-radius: 0;
617
667
  }
668
+ .ge-canvas.ge-editing .ge-text-block > .ge-text-drawer > .ge-convert-picker {
669
+ left: auto;
670
+ right: 0;
671
+ }
672
+ .ge-canvas.ge-editing .ge-text-block.ge-plain-block {
673
+ outline-color: rgba(0, 0, 0, 0.25);
674
+ }
675
+ .ge-canvas.ge-editing .ge-text-block.ge-plain-block > .ge-text-drawer {
676
+ background: #e9ecef;
677
+ }
618
678
  .ge-canvas.ge-editing .column:not(:has( > :not(.ge-tools-drawer, .ge-resize-handle)))::after {
619
679
  content: '';
620
680
  display: block;