@themarioga/grid-editor 3.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.
Files changed (52) hide show
  1. package/AUTO_SAVE.md +30 -0
  2. package/BUILDING.md +68 -0
  3. package/CHANGELOG.md +362 -0
  4. package/LICENSE +23 -0
  5. package/README.md +521 -0
  6. package/UPGRADING.md +88 -0
  7. package/dist/grideditor.css +3875 -0
  8. package/dist/grideditor.min.css +2 -0
  9. package/dist/grideditor.min.css.map +1 -0
  10. package/dist/jquery.grideditor.js +2996 -0
  11. package/dist/jquery.grideditor.min.js +2 -0
  12. package/dist/jquery.grideditor.min.js.map +1 -0
  13. package/dist/locales/grideditor.es.js +74 -0
  14. package/dist/locales/grideditor.es.min.js +2 -0
  15. package/dist/locales/grideditor.es.min.js.map +1 -0
  16. package/dist/plugins/grideditor.accordion.js +185 -0
  17. package/dist/plugins/grideditor.accordion.min.js +2 -0
  18. package/dist/plugins/grideditor.accordion.min.js.map +1 -0
  19. package/dist/plugins/grideditor.elements.js +141 -0
  20. package/dist/plugins/grideditor.elements.min.js +2 -0
  21. package/dist/plugins/grideditor.elements.min.js.map +1 -0
  22. package/dist/plugins/grideditor.popup.js +143 -0
  23. package/dist/plugins/grideditor.popup.min.js +2 -0
  24. package/dist/plugins/grideditor.popup.min.js.map +1 -0
  25. package/dist/plugins/grideditor.tabs.js +140 -0
  26. package/dist/plugins/grideditor.tabs.min.js +2 -0
  27. package/dist/plugins/grideditor.tabs.min.js.map +1 -0
  28. package/docs/events.md +158 -0
  29. package/docs/locale-keys.md +140 -0
  30. package/docs/plugins.md +163 -0
  31. package/example/autosave.html +89 -0
  32. package/example/basic.html +93 -0
  33. package/example/breakpoints.html +94 -0
  34. package/example/ckeditor.html +104 -0
  35. package/example/containers.html +214 -0
  36. package/example/elements.html +147 -0
  37. package/example/index.html +119 -0
  38. package/example/locale.html +84 -0
  39. package/example/plugins.html +217 -0
  40. package/example/summernote.html +106 -0
  41. package/example/wrap_content.html +44 -0
  42. package/package.json +66 -0
  43. package/src/js/jquery.grideditor.ckeditor.js +77 -0
  44. package/src/js/jquery.grideditor.js +2711 -0
  45. package/src/js/jquery.grideditor.summernote.js +72 -0
  46. package/src/js/jquery.grideditor.tinymce.js +135 -0
  47. package/src/js/locales/grideditor.es.js +74 -0
  48. package/src/js/plugins/grideditor.accordion.js +185 -0
  49. package/src/js/plugins/grideditor.elements.js +141 -0
  50. package/src/js/plugins/grideditor.popup.js +143 -0
  51. package/src/js/plugins/grideditor.tabs.js +140 -0
  52. package/src/less/grideditor.less +594 -0
@@ -0,0 +1,140 @@
1
+ grid-editor locale keys
2
+ =======================
3
+
4
+ Every user-visible string in grid-editor goes through `t(key)`, and every key
5
+ is listed here. The list is hand-written on purpose — it is prose a reviewer
6
+ can read — and `test/locales.js` holds it to the source in both directions: a
7
+ key in the code that is missing here fails the build, and so does a key here
8
+ that no longer exists in the code.
9
+
10
+ English lives in `$.fn.gridEditor.locales.en`, inside the main bundle, and is
11
+ where every lookup ends. Shipped locales (currently `es`) translate all of it,
12
+ and `test/locales.js` fails the build when one falls behind. The files are in
13
+ `src/js/locales/`.
14
+
15
+ Lookup order for a key is `locale_strings` → `locales[locale]` → `locales.en` →
16
+ the key itself. A key nothing defines is shown as the key, and logs once.
17
+
18
+ `{name}` placeholders are filled from the parameters the call passes.
19
+
20
+
21
+ tool.*
22
+ ------
23
+
24
+ The tools in a drawer, and the buttons in the toolbar above the canvas.
25
+
26
+ | Key | English | Where |
27
+ | --- | --- | --- |
28
+ | `tool.move` | Move | Drag handle in the row and column drawers |
29
+ | `tool.settings` | Settings | Opens the settings panel in a drawer |
30
+ | `tool.add_row` | Add row | Column drawer, adds a nested row |
31
+ | `tool.add_column` | Add column\n(hold to choose the width) | Row drawer. A click adds a column, holding the tool offers the widths. Two lines |
32
+ | `tool.column_size` | {size} of 12 | Tooltip of a width in that picker |
33
+ | `tool.delete_row` | Remove row | Row drawer |
34
+ | `tool.delete_column` | Remove col | Column drawer |
35
+ | `tool.delete_element` | Remove element | Element drawer |
36
+ | `tool.delete_container` | Remove container | Container drawer |
37
+ | `tool.delete_pane` | Remove pane | Drawer of a tab or an accordion item |
38
+ | `tool.rename` | Double click to rename | Tooltip of a pane's label, which is edited in place |
39
+ | `tool.toggle_popup` | Fold this popup away while editing | Popup drawer. Editing shows a popup unfolded, and this folds it away |
40
+ | `tool.element_info` | Element: {name} | Tooltip of the element drawer's info tool. `{name}` is the element's `data-ge-label`, its `data-ge-element` type, or both |
41
+ | `tool.column_narrower` | Make column narrower\n(hold shift for min) | Column drawer, the `-` tool. Two lines |
42
+ | `tool.column_wider` | Make column wider\n(hold shift for max) | Column drawer, the `+` tool. Two lines |
43
+ | `tool.indent_decrease` | Decrease indent\n(hold shift for none) | Column drawer, removes offset units |
44
+ | `tool.indent_increase` | Increase indent\n(hold shift for max) | Column drawer, adds offset units |
45
+ | `tool.edit_source` | Edit Source Code | Toolbar, swaps the canvas for its html |
46
+ | `tool.preview` | Preview | Toolbar, hides the editing furniture while held |
47
+ | `tool.id_placeholder` | id | Placeholder of the id input in the settings panel |
48
+ | `tool.id_title` | Set a unique identifier | Tooltip of that input |
49
+ | `tool.classes_placeholder` | classes | Placeholder of the css class input beside it |
50
+ | `tool.classes_title` | Css classes, separated by spaces | Tooltip of that input |
51
+ | `tool.toggle_class` | Toggle "{label}" styling | Tooltip of a `row_classes`/`col_classes` button. `{label}` is the host's label |
52
+
53
+
54
+ row.*
55
+ -----
56
+
57
+ | Key | English | Where |
58
+ | --- | --- | --- |
59
+ | `row.add` | Add row {layout} | Tooltip of each toolbar add-row button. `{layout}` is the column layout, as in `6-6` |
60
+
61
+
62
+ container.*
63
+ -----------
64
+
65
+ The containers: tabs, accordions and popups, and the panes inside them.
66
+
67
+ | Key | English | Where |
68
+ | --- | --- | --- |
69
+ | `container.add_tabs` | Tabs | Toolbar button that adds a tabs container |
70
+ | `container.add_tab` | Add tab | Container drawer, adds a pane |
71
+ | `container.tab_label` | Tab {number} | Label of a new tab. `{number}` is its position |
72
+ | `container.add_accordion` | Accordion | Toolbar button that adds an accordion |
73
+ | `container.add_accordion_item` | Add item | Container drawer, adds an item |
74
+ | `container.accordion_label` | Item {number} | Label of a new accordion item |
75
+ | `container.add_popup` | Popup | Toolbar button that adds a popup |
76
+ | `container.popup_title` | Title | Title of a new popup, in its modal header |
77
+ | `container.popup_trigger` | Open | Label of the button a popup makes to open itself |
78
+
79
+
80
+ confirm.*
81
+ ---------
82
+
83
+ Shown by `window.confirm` unless the host sets `confirm_delete: false` or
84
+ cancels `grideditor:before-delete` and asks in its own way.
85
+
86
+ The question is asked in a Bootstrap modal the editor builds outside the
87
+ canvas; a page that loaded Bootstrap's css but not its javascript gets the
88
+ browser's own confirm instead.
89
+
90
+ | Key | English | Where |
91
+ | --- | --- | --- |
92
+ | `confirm.title` | Confirm | Title of the confirmation modal |
93
+ | `confirm.ok` | Delete | The button that goes through with it |
94
+ | `confirm.cancel` | Cancel | The button that does not, and the close button's label |
95
+ | `confirm.delete_row` | Delete row? | Before a row is removed |
96
+ | `confirm.delete_column` | Delete column? | Before a column is removed |
97
+ | `confirm.delete_element` | Delete element? | Before an element is removed |
98
+ | `confirm.delete_container` | Delete this container and everything in it? | Before a container is removed |
99
+ | `confirm.delete_tab` | Delete this tab and everything in it? | Before a tab and its pane are removed |
100
+ | `confirm.delete_accordion_item` | Delete this item and everything in it? | Before an accordion item is removed |
101
+
102
+
103
+ view.*
104
+ ------
105
+
106
+ The layout mode dropdown: one key per view the build offers, used for both the
107
+ dropdown item and the button that shows the current mode. The key is the view
108
+ key, so a locale covers a new breakpoint by adding `view.<key>`. Short strings
109
+ — they share a line with the other toolbar buttons.
110
+
111
+ | Key | English | Where |
112
+ | --- | --- | --- |
113
+ | `view.all` | All sizes | The default view, which writes every breakpoint at once |
114
+ | `view.xs` | Phone | Layout mode writing `col-*` and `offset-*` |
115
+ | `view.sm` | Tablet | Layout mode writing `col-sm-*` and `offset-sm-*` |
116
+ | `view.md` | Small desktop | Layout mode writing `col-md-*` and `offset-md-*` |
117
+ | `view.lg` | Desktop | Layout mode writing `col-lg-*` and `offset-lg-*` |
118
+ | `view.xl` | Large desktop | Layout mode writing `col-xl-*` and `offset-xl-*` |
119
+ | `view.xxl` | Widescreen | Layout mode writing `col-xxl-*` and `offset-xxl-*` |
120
+
121
+
122
+ error.*
123
+ -------
124
+
125
+ Console messages for the host developer, not the page's user, but translated
126
+ all the same: the developer reading them is the one who chose the locale.
127
+
128
+ | Key | English | Where |
129
+ | --- | --- | --- |
130
+ | `error.tinymce_missing` | tinyMCE not available! … | `content_types: ['tinymce']` with no tinyMCE loaded |
131
+ | `error.ckeditor_missing` | CKEditor not available! … | `content_types: ['ckeditor']` with no CKEditor loaded |
132
+ | `error.summernote_missing` | Summernote not available! … | `content_types: ['summernote']` with no Summernote loaded |
133
+
134
+
135
+ Namespaces not in use yet
136
+ -------------------------
137
+
138
+ `element.*` and `column.*` are reserved and have no keys yet: the element and
139
+ offset strings that exist live under `tool.*` and `confirm.*`, next to the
140
+ tools they belong to.
@@ -0,0 +1,163 @@
1
+ Writing a plugin
2
+ ================
3
+
4
+ Tabs, accordions, popups and the element level controls are not built into
5
+ grid-editor: each is a file you load beside it, and loading the file is what
6
+ turns the feature on.
7
+
8
+ ```html
9
+ <script src="dist/jquery.grideditor.min.js"></script>
10
+ <script src="dist/plugins/grideditor.tabs.min.js"></script>
11
+ <script src="dist/plugins/grideditor.popup.min.js"></script>
12
+ <script src="dist/plugins/grideditor.elements.min.js"></script>
13
+ ```
14
+
15
+ There are two kinds. A **container plugin** builds a type of container — it
16
+ registers under `$.fn.gridEditor.containers`, and the toolbar offers a button
17
+ for it. A **feature plugin** is anything else the editor can do —
18
+ `$.fn.gridEditor.features`, hooks into the canvas, and may contribute methods.
19
+ Both are factories called once per editor with the same handle.
20
+
21
+ The `plugins` setting names which of the loaded ones to use:
22
+
23
+ ```javascript
24
+ $('#myGrid').gridEditor({ plugins: ['tabs', 'elements'] });
25
+ ```
26
+
27
+ Every loaded plugin is used when the setting is not given. A name that was
28
+ never loaded logs one warning and changes nothing else. A container in the
29
+ markup whose plugin is not loaded is left alone: no drawer, no tools, and
30
+ `getHtml` gives it back as it found it.
31
+
32
+ [example/plugins.html](../example/plugins.html) is this page as a working
33
+ editor: the shipped plugins, a container plugin written in the page itself,
34
+ and a checkbox per plugin so you can watch the toolbar and the canvas change.
35
+
36
+
37
+ The shape of a plugin
38
+ ---------------------
39
+
40
+ A plugin registers a **factory** under the type it builds. The factory is
41
+ called once per editor, with the handle below, and returns the definition:
42
+
43
+ ```javascript
44
+ (function($) {
45
+
46
+ $.extend($.fn.gridEditor.locales.en, {
47
+ 'container.add_carousel': 'Carousel',
48
+ 'container.carousel_label': 'Slide {number}',
49
+ });
50
+
51
+ $.fn.gridEditor.containers.carousel = function(ge) {
52
+
53
+ function addSlideTo(container, options) { … }
54
+
55
+ return {
56
+ labelKey: 'container.add_carousel', // the toolbar button's label
57
+ addPaneKey: 'container.add_slide', // the drawer's add pane tool
58
+ paneKind: 'slide', // the kind its panes report
59
+
60
+ create: function(options) { … }, // returns the container
61
+ addPane: addSlideTo, // returns the new pane
62
+ mark: function(container) { … }, // editing furniture on
63
+ unmark: function(container) { … }, // and off again
64
+ afterPaneMove: function(container, pane) { … }, // optional
65
+ tools: function(drawer, container) { … }, // optional, extra tools
66
+ onInit: function() { … }, // optional, per canvas init
67
+ onDeinit: function() { … }, // optional, per canvas deinit
68
+ };
69
+ };
70
+
71
+ })(jQuery);
72
+ ```
73
+
74
+ - **`create(options)`** returns a detached container. It must carry
75
+ `data-ge-container="<type>"`: that attribute, and never a class, is how the
76
+ editor recognises one.
77
+ - **`mark(container)`** is called on every `init`. It adds the drawers, labels
78
+ and editing attributes, and must be safe to run twice.
79
+ - **`unmark(container)`** is called on every `deinit`, which is what `getHtml`
80
+ runs before reading the markup. Whatever `mark` added comes off here. What
81
+ is left is what the host ships.
82
+ - **`onInit`/`onDeinit`** are for work that is about the whole canvas rather
83
+ than one container — the popup plugin wires up the host's
84
+ `data-ge-popup-target` triggers there.
85
+
86
+
87
+ The handle
88
+ ----------
89
+
90
+ Everything a plugin needs from the editor comes through the handle its factory
91
+ is called with. It is the plugin contract: these names, and what they do, do
92
+ not change without a major version.
93
+
94
+ | | |
95
+ | --- | --- |
96
+ | `ge.canvas` | The canvas element |
97
+ | `ge.settings` | The live settings, for the host's own tool lists |
98
+ | `ge.t(key, params)` | A string from the locale |
99
+ | `ge.warn(message)` | A console warning, prefixed like the editor's own |
100
+ | `ge.containerId(type)` | A generated id, stable across a reset, for Bootstrap's toggles |
101
+ | `ge.defaultRegion()` | A row with one full width column: what an empty pane starts as |
102
+ | `ge.createTool(drawer, title, className, iconClass, handlers)` | A tool in a drawer |
103
+ | `ge.createMoveTool(drawer)` | The drag handle, unless `drag_handle` says the whole drawer is one |
104
+ | `ge.addSettingsTool(drawer, node, presets)` | The gear, and the id and class panel it opens |
105
+ | `ge.deleteNode(kind, node, confirmText, animate)` | Remove a node: ask, animate, announce |
106
+ | `ge.place(node, kind, options)` | Put a created node where `appendTo` and friends say, through the add events |
107
+ | `ge.createPaneControls(pane, kind, hostTools, confirmText, remove)` | The drawer a pane gets: move, the host's tools, delete |
108
+ | `ge.makeLabelEditable(label)` | Rename in place, with the Bootstrap toggle suspended while typing |
109
+ | `ge.labelIn(button)` | The label span inside a button, wrapped if it is not already |
110
+ | `ge.unwrapLabels(scope)` | Take those wrappers off again, for `unmark` |
111
+ | `ge.suspendToggles(scope)` / `ge.resumeToggles(scope)` | Move `data-bs-toggle` aside while editing, and back on the way out |
112
+ | `ge.emit(name, payload)` | Fire an event and its callbacks; false means a handler canceled |
113
+ | `ge.payloadFor(kind, node, extra)` | Build a payload the documented way |
114
+ | `ge.operate(body)` | Run `body` as one operation, so a handler calling back in is queued |
115
+
116
+ The add, delete and move events for a container and its panes are fired by the
117
+ editor, not by the plugin: `createPaneControls` handles a pane's delete, and
118
+ the toolbar and the drawer handle the adds.
119
+
120
+
121
+ Feature plugins
122
+ ---------------
123
+
124
+ A feature plugin returns hooks rather than a container definition:
125
+
126
+ ```javascript
127
+ $.fn.gridEditor.features.elements = function(ge) {
128
+ return {
129
+ methods: { createElement: … }, // added to the editor's own methods
130
+ kindOf: function(node) { … }, // what an event calls this node
131
+ onInit: function() { … }, // every init: put the furniture in
132
+ onDeinit: function() { … }, // every deinit: take it out again
133
+ onContentReady: function(area) { … }, // a rich text editor just took over
134
+ onSortable: function(shared) { … }, // make your own sortables
135
+ };
136
+ };
137
+ ```
138
+
139
+ - **`onSortable(shared)`** is handed the options the editor's own sortables
140
+ use — the handle, the cancel selector, the start and stop handlers — so a
141
+ plugin's sortables answer to `drag_handle` and fire the move events like
142
+ everything else.
143
+ - **`methods`** are added to the instance handle. A method the editor
144
+ documents but a plugin implements — `createElement` — warns and returns null
145
+ when the plugin is not loaded.
146
+ - **`kindOf(node)`** returns the `kind` an event should carry for a node the
147
+ plugin owns, or null.
148
+
149
+ The core's own sortables and the plugins' are taken down together: jQuery UI
150
+ marks what it made, so a plugin does not have to unmake it.
151
+
152
+
153
+ What the editor does for you
154
+ ----------------------------
155
+
156
+ Panes are ordinary canvas regions. `init()` walks the whole canvas, so rows,
157
+ columns, content areas and elements nest inside a pane exactly as they do at
158
+ the top level, and containers nest inside each other, with nothing asked of
159
+ the plugin.
160
+
161
+ Sorting is the one thing a plugin sets up itself, in `mark`, because only the
162
+ plugin knows which of its parts move: the tabs plugin makes its strip sortable
163
+ and puts the panes back in strip order in `afterPaneMove`.
@@ -0,0 +1,89 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Grid Editor example - auto save and import/export</title>
6
+
7
+ <!-- CSS dependencies -->
8
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.css">
10
+
11
+ <!-- JS dependencies -->
12
+ <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
13
+ <script src="https://code.jquery.com/ui/1.14.2/jquery-ui.min.js"></script>
14
+ <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>
15
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/6.8.6/tinymce.min.js"></script>
16
+
17
+ <!-- Grid editor CSS -->
18
+ <link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
19
+ <!-- Grid editor javascript -->
20
+ <script src="../dist/jquery.grideditor.min.js"></script>
21
+ </head>
22
+ <body>
23
+ <div class="container py-3">
24
+ <h2>Grid Editor example - auto save and import/export</h2>
25
+ <div class="mb-3">
26
+ <button id="exportBtn" class="btn btn-primary">Export layout</button>
27
+ <input type="file" id="importInput" class="btn btn-secondary" accept=".html">
28
+ <button id="resetBtn" class="btn btn-danger">Clear draft</button>
29
+ </div>
30
+
31
+ <form id="editorForm">
32
+ <div id="myGrid"></div>
33
+ </form>
34
+ </div>
35
+ <script>
36
+ const LOCAL_STORAGE_KEY = 'gridEditorLayout';
37
+
38
+ function initEditor(initialContent = '') {
39
+ const $grid = $('#myGrid');
40
+ $grid.html(initialContent);
41
+ $grid.gridEditor({
42
+ new_row_layouts: [[12], [6,6], [4,4,4]],
43
+ content_types: ['tinymce']
44
+ });
45
+ }
46
+
47
+ function autoSave() {
48
+ const html = $('#myGrid').gridEditor('getHtml');
49
+ localStorage.setItem(LOCAL_STORAGE_KEY, html);
50
+ }
51
+
52
+ $(function () {
53
+ // Restore the previous draft, falling back to whatever markup is in the page
54
+ const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
55
+ initEditor(saved || $('#myGrid').html());
56
+
57
+ setInterval(autoSave, 5000);
58
+
59
+ $('#exportBtn').on('click', () => {
60
+ const html = $('#myGrid').gridEditor('getHtml');
61
+ const blob = new Blob([html], { type: 'text/html' });
62
+ const url = URL.createObjectURL(blob);
63
+ const a = document.createElement('a');
64
+ a.href = url;
65
+ a.download = 'layout.html';
66
+ a.click();
67
+ URL.revokeObjectURL(url);
68
+ });
69
+
70
+ $('#importInput').on('change', function (e) {
71
+ const file = e.target.files[0];
72
+ if (!file) return;
73
+ const reader = new FileReader();
74
+ reader.onload = function (e) {
75
+ $('#myGrid').gridEditor('remove');
76
+ initEditor(e.target.result);
77
+ autoSave();
78
+ };
79
+ reader.readAsText(file);
80
+ });
81
+
82
+ $('#resetBtn').on('click', function () {
83
+ localStorage.removeItem(LOCAL_STORAGE_KEY);
84
+ location.reload();
85
+ });
86
+ });
87
+ </script>
88
+ </body>
89
+ </html>
@@ -0,0 +1,93 @@
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://code.jquery.com/ui/1.14.2/jquery-ui.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
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/6.8.6/tinymce.min.js"></script>
15
+
16
+ <!-- Grid editor CSS -->
17
+ <link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
18
+ <!-- Grid editor javascript -->
19
+ <script src="../dist/jquery.grideditor.min.js"></script>
20
+
21
+ <script>
22
+ $(function() {
23
+ // Initialize grid editor
24
+ $('#myGrid').gridEditor({
25
+ drag_handle: 'drawer',
26
+ new_row_layouts: [[12], [6,6], [9,3]],
27
+ content_types: ['tinymce'],
28
+ });
29
+
30
+ // // Get resulting html
31
+ // var html = $('#myGrid').gridEditor('getHtml');
32
+ // console.log(html);
33
+ });
34
+ </script>
35
+
36
+ <title>Grid Editor example</title>
37
+ </head>
38
+ <body>
39
+
40
+ <div class="container">
41
+ <div id="myGrid">
42
+
43
+ <div class="row">
44
+ <div class="col-lg-12">
45
+ <h1>Lorem ipsum dolor sit amet, consectetur</h1>
46
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit exercitationem eaque aperiam rem quia quibusdam dolor ducimus quo similique eos pariatur nostrum aliquam nam eius, doloremque quis voluptatum unde. Porro voluptates aspernatur voluptate ipsam, magni vero. Accusamus, iusto tempore id!</p>
47
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae laboriosam, excepturi quas.</p>
48
+ </div>
49
+ </div>
50
+
51
+ <div class="row">
52
+ <div class="col-lg-4">
53
+ <h2>Lorem ipsum dolor</h2>
54
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea facilis vel aliquam aspernatur dolor placeat totam saepe perferendis. Odio quia vel sed eveniet cupiditate, illum doloremque sint veniam eum? Corporis?</p>
55
+ </div>
56
+ <div class="col-lg-4">
57
+ <h2>Pariatur reprehenderit</h2>
58
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo adipisci ipsa, consequuntur cum, sunt dolores veniam. Enim inventore in dolore deserunt vitae sequi nemo!</p>
59
+ </div>
60
+ <div class="col-lg-4">
61
+ <h2>Pariatur reprehenderit</h2>
62
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea excepturi ducimus numquam aut error corporis aspernatur ipsum quos eius culpa!</p>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="row">
67
+ <div class="col-lg-8">
68
+ <h2>Lorem ipsum dolor.</h2>
69
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro distinctio atque molestiae optio, consequuntur? Iusto ratione cumque dolor aut dolore!</p>
70
+
71
+ <div class="row">
72
+ <div class="col-lg-6">
73
+ <hr>
74
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Debitis facilis molestias voluptatum laudantium fuga ratione tempora rem dolor dicta rerum vero ut, suscipit ex qui amet quam vel cupiditate quaerat minus assumenda reiciendis, similique omnis delectus! Autem, repudiandae cumque eaque?</p>
75
+ </div>
76
+ <div class="col-lg-6">
77
+ <hr>
78
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet molestiae quaerat illum, consequuntur iusto aspernatur quam provident? Possimus!</p>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="col-lg-4">
84
+ <h2>Lusto ratione</h2>
85
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis fugit quasi officiis id laudantium error aut ut aperiam dicta saepe non vel, cupiditate illum ipsam velit deleniti natus incidunt impedit molestias dolore quos dolores enim. Aliquid ipsam eaque consequuntur quaerat, suscipit a in. Praesentium repudiandae quibusdam recusandae sequi eligendi quos, dignissimos, officiis officia minima necessitatibus eaque consequatur in id adipisci qui minus voluptatum quae debitis, quas maxime iure. Tempore vero unde quia reiciendis ad beatae voluptate omnis, ipsa expedita ab, quasi, neque. Doloribus, pariatur. Aut hic voluptate.</p>
86
+ </div>
87
+ </div>
88
+
89
+ </div> <!-- /#myGrid -->
90
+ </div> <!-- /.container -->
91
+
92
+ </body>
93
+ </html>
@@ -0,0 +1,94 @@
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://code.jquery.com/ui/1.14.2/jquery-ui.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 -->
18
+ <script src="../dist/jquery.grideditor.min.js"></script>
19
+
20
+ <script>
21
+ $(function() {
22
+ $('#myGrid').gridEditor({
23
+ new_row_layouts: [[12], [6,6], [4,4,4], [8,4]],
24
+ content_types: [],
25
+
26
+ // The default: every size and offset change is written to all
27
+ // six breakpoints at once. Switch the dropdown to a single
28
+ // breakpoint to tune that one on its own.
29
+ default_view: 'all',
30
+
31
+ // A host that wants the old three-mode feel can offer three
32
+ // layout_modes: ['all', 'lg', 'sm', 'xs'],
33
+ });
34
+
35
+ $('#output').on('click', function() {
36
+ $('#html').text($('#myGrid').gridEditor('getHtml'));
37
+ });
38
+ });
39
+ </script>
40
+
41
+ <title>Grid Editor breakpoints example</title>
42
+ </head>
43
+ <body>
44
+
45
+ <div class="container">
46
+
47
+ <div class="row my-3">
48
+ <div class="col-lg-8">
49
+ <h1 class="h4">Six breakpoints, and "all sizes"</h1>
50
+ <p class="form-text">
51
+ The dropdown on the right of the toolbar picks the layout
52
+ mode. In <strong>All sizes</strong> the canvas renders as
53
+ the browser would, and the width and indent tools write
54
+ every breakpoint at once. Pick a single breakpoint and the
55
+ canvas narrows to that tier's width, that tier's classes
56
+ become the effective ones whatever your window is doing,
57
+ and the tools write only that tier.
58
+ </p>
59
+ <p class="form-text">
60
+ The row below starts with a different size per tier, so
61
+ switching modes visibly changes it: 3 units on phone, 4 on
62
+ tablet, 6 on desktop, 8 on widescreen. The second row shows
63
+ offsets, which are indented per tier in the same way.
64
+ </p>
65
+ <button class="btn btn-sm btn-secondary" id="output" type="button">Show the html this produces</button>
66
+ <pre id="html" class="form-text"></pre>
67
+ </div>
68
+ </div>
69
+
70
+ <div id="myGrid">
71
+
72
+ <div class="row">
73
+ <div class="col-3 col-sm-4 col-md-5 col-lg-6 col-xl-7 col-xxl-8">
74
+ <h2 class="h5">Sized per tier</h2>
75
+ <p>3 on phone, 4 on tablet, 5 on small desktop, 6 on desktop, 7 on large, 8 on widescreen.</p>
76
+ </div>
77
+ <div class="col-9 col-sm-8 col-md-7 col-lg-6 col-xl-5 col-xxl-4">
78
+ <h2 class="h5">And the rest of the row</h2>
79
+ <p>The two columns always add up to twelve units.</p>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="row">
84
+ <div class="col-8 offset-2 col-lg-4 offset-lg-8">
85
+ <h2 class="h5">Indented</h2>
86
+ <p>Centred on phone, pushed to the right on desktop.</p>
87
+ </div>
88
+ </div>
89
+
90
+ </div> <!-- /#myGrid -->
91
+ </div> <!-- /.container -->
92
+
93
+ </body>
94
+ </html>