@themarioga/grid-editor 6.0.0-beta.4 → 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.
- package/CHANGELOG.md +24 -0
- package/README.md +57 -2
- package/dist/grideditor.css +46 -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 +53 -20
- package/dist/jquery.grideditor.min.js +1 -1
- package/dist/jquery.grideditor.min.js.map +1 -1
- package/dist/locales/grideditor.es.js +4 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +1 -1
- package/dist/plugins/grideditor.codemirror-inline.js +190 -0
- package/dist/plugins/grideditor.codemirror-inline.min.js +2 -0
- package/dist/plugins/grideditor.codemirror-inline.min.js.map +1 -0
- package/dist/plugins/grideditor.codemirror.js +79 -0
- package/dist/plugins/grideditor.codemirror.min.js +2 -0
- package/dist/plugins/grideditor.codemirror.min.js.map +1 -0
- package/docs/events.md +6 -0
- package/docs/locale-keys.md +13 -0
- package/docs/plugins.md +18 -3
- package/example/codemirror.html +103 -0
- package/example/index.html +8 -0
- package/package.json +1 -1
- package/src/js/jquery.grideditor.js +53 -20
- package/src/js/locales/grideditor.es.js +4 -0
- package/src/js/plugins/grideditor.codemirror-inline.js +190 -0
- package/src/js/plugins/grideditor.codemirror.js +79 -0
- package/src/less/grideditor.less +54 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A block's html, edited in place with CodeMirror.
|
|
3
|
+
*
|
|
4
|
+
* A feature plugin: load this file after the editor, and CodeMirror 5 with
|
|
5
|
+
* its html mode after or before it, and every drawer of a row, a column, a
|
|
6
|
+
* text, the host's plain content, an element, a section or a container has a
|
|
7
|
+
* </> tool. It opens the block's html - the block itself and everything in
|
|
8
|
+
* it, as getHtml would give it - in CodeMirror where the block was, and
|
|
9
|
+
* Apply puts what was written in the block's place. What it can ask the
|
|
10
|
+
* editor for is the handle its factory is called with, described in
|
|
11
|
+
* docs/plugins.md.
|
|
12
|
+
*
|
|
13
|
+
* <link rel="stylesheet" href="codemirror/lib/codemirror.css">
|
|
14
|
+
* <script src="codemirror/lib/codemirror.js"></script>
|
|
15
|
+
* <script src="codemirror/mode/xml/xml.js"></script>
|
|
16
|
+
* <script src="codemirror/mode/javascript/javascript.js"></script>
|
|
17
|
+
* <script src="codemirror/mode/css/css.js"></script>
|
|
18
|
+
* <script src="codemirror/mode/htmlmixed/htmlmixed.js"></script>
|
|
19
|
+
* <script src="dist/jquery.grideditor.min.js"></script>
|
|
20
|
+
* <script src="dist/plugins/grideditor.codemirror-inline.min.js"></script>
|
|
21
|
+
*
|
|
22
|
+
* Without CodeMirror on the page the html is edited in a plain textarea.
|
|
23
|
+
* CodeMirror's options are the codemirror plugin's, codemirror.config.
|
|
24
|
+
*/
|
|
25
|
+
(function($) {
|
|
26
|
+
|
|
27
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
28
|
+
'tool.edit_html': 'Edit html',
|
|
29
|
+
'codemirror.apply': 'Apply',
|
|
30
|
+
'codemirror.cancel': 'Cancel',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
/** What has html of its own to edit: a pane's is split between its button and its body. */
|
|
34
|
+
var KINDS = ['row', 'column', 'text', 'plain', 'element', 'section'];
|
|
35
|
+
|
|
36
|
+
$.fn.gridEditor.features['codemirror-inline'] = function(ge) {
|
|
37
|
+
|
|
38
|
+
var open = []; // The blocks being edited: { node, kind, from, wrapper, textarea, editor }
|
|
39
|
+
|
|
40
|
+
function options() {
|
|
41
|
+
var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};
|
|
42
|
+
|
|
43
|
+
return $.extend({
|
|
44
|
+
mode: 'htmlmixed',
|
|
45
|
+
lineNumbers: true,
|
|
46
|
+
lineWrapping: true,
|
|
47
|
+
tabSize: 2,
|
|
48
|
+
indentUnit: 2,
|
|
49
|
+
// As tall as what it holds, up to the css's limit
|
|
50
|
+
viewportMargin: Infinity,
|
|
51
|
+
}, own);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** What stands for the node in its column: a text's text block, or the node. */
|
|
55
|
+
function anchorOf(node) {
|
|
56
|
+
var textBlock = node.parent('.ge-text-block');
|
|
57
|
+
return textBlock.length ? textBlock : node;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function entryOf(node) {
|
|
61
|
+
return open.filter(function(entry) { return entry.node[0] === node[0]; })[0] || null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function editable(node, kind) {
|
|
65
|
+
return KINDS.indexOf(kind) !== -1 || node.is('[data-ge-container]');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** The editor where the block was, the block hidden behind it. */
|
|
69
|
+
function show(entry) {
|
|
70
|
+
var anchor = anchorOf(entry.node).addClass('ge-code-hidden');
|
|
71
|
+
entry.wrapper.insertAfter(anchor);
|
|
72
|
+
if (entry.editor) { entry.editor.refresh(); }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function hide(entry) {
|
|
76
|
+
entry.wrapper.detach();
|
|
77
|
+
anchorOf(entry.node).removeClass('ge-code-hidden');
|
|
78
|
+
entry.node.removeClass('ge-code-hidden');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function close(entry) {
|
|
82
|
+
hide(entry);
|
|
83
|
+
if (entry.editor) { entry.editor.toTextArea(); }
|
|
84
|
+
entry.wrapper.remove();
|
|
85
|
+
open.splice(open.indexOf(entry), 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function openEditor(node) {
|
|
89
|
+
if (entryOf(node)) { return; }
|
|
90
|
+
|
|
91
|
+
var entry = {
|
|
92
|
+
node: node,
|
|
93
|
+
kind: ge.kindOf(node),
|
|
94
|
+
// As getHtml gives it: no drawers, no editor open in it
|
|
95
|
+
from: ge.nodeHtml(node),
|
|
96
|
+
// A drawer, to the editor: never content, never a block to move
|
|
97
|
+
wrapper: $('<div class="ge-tools-drawer ge-code-inline" />'),
|
|
98
|
+
editor: null,
|
|
99
|
+
};
|
|
100
|
+
entry.textarea = $('<textarea class="ge-code-inline-source" />').val(entry.from).appendTo(entry.wrapper);
|
|
101
|
+
|
|
102
|
+
var bar = $('<div class="ge-code-inline-bar" />').appendTo(entry.wrapper);
|
|
103
|
+
$('<button type="button" class="btn btn-sm btn-primary ge-code-apply" />')
|
|
104
|
+
.text(ge.t('codemirror.apply'))
|
|
105
|
+
.on('click', function() { apply(entry); })
|
|
106
|
+
.appendTo(bar);
|
|
107
|
+
$('<button type="button" class="btn btn-sm btn-outline-secondary ge-code-cancel" />')
|
|
108
|
+
.text(ge.t('codemirror.cancel'))
|
|
109
|
+
.on('click', function() { close(entry); })
|
|
110
|
+
.appendTo(bar);
|
|
111
|
+
|
|
112
|
+
open.push(entry);
|
|
113
|
+
show(entry);
|
|
114
|
+
|
|
115
|
+
if (window.CodeMirror) {
|
|
116
|
+
entry.editor = window.CodeMirror.fromTextArea(entry.textarea[0], options());
|
|
117
|
+
$(entry.editor.getWrapperElement()).addClass('ge-code-editor');
|
|
118
|
+
entry.editor.focus();
|
|
119
|
+
} else {
|
|
120
|
+
entry.textarea.trigger('focus');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* What was written, in the block's place, through the edit-html events.
|
|
126
|
+
* The canvas leaves editing to take it in and comes back, as it does for
|
|
127
|
+
* getHtml, so what was written is read as the editor reads any markup.
|
|
128
|
+
*/
|
|
129
|
+
function apply(entry) {
|
|
130
|
+
var to = entry.editor ? entry.editor.getValue() : entry.textarea.val();
|
|
131
|
+
var payload = ge.payloadFor(entry.kind, entry.node, { source: 'tool', from: entry.from, to: to });
|
|
132
|
+
|
|
133
|
+
// Canceled, the editor stays open with what was written in it
|
|
134
|
+
if (!ge.emit('before-edit-html', payload)) { return; }
|
|
135
|
+
|
|
136
|
+
close(entry);
|
|
137
|
+
|
|
138
|
+
var instance = ge.canvas.data('grideditor');
|
|
139
|
+
instance.deinit();
|
|
140
|
+
|
|
141
|
+
var made = $('<div />').html(to).contents();
|
|
142
|
+
entry.node.replaceWith(made);
|
|
143
|
+
|
|
144
|
+
instance.init();
|
|
145
|
+
|
|
146
|
+
ge.emit('after-edit-html', ge.payloadFor(entry.kind, made.filter('*'), {
|
|
147
|
+
source: 'tool',
|
|
148
|
+
from: entry.from,
|
|
149
|
+
to: to,
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function tool(drawer, node) {
|
|
154
|
+
ge.createTool(drawer, ge.t('tool.edit_html'), 'ge-edit-html', 'bi bi-code-slash', function() {
|
|
155
|
+
openEditor(node);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
drawerTools: function(drawer, node, kind) {
|
|
161
|
+
if (editable(node, kind)) { tool(drawer, node); }
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
// Plain content has no gear, and so none of the drawerTools: its
|
|
165
|
+
// html is what there is to edit about it
|
|
166
|
+
plainTools: tool,
|
|
167
|
+
|
|
168
|
+
// Every deinit - getHtml's among them - takes the editors off the
|
|
169
|
+
// canvas, whatever is in them, and every init puts them back where
|
|
170
|
+
// their block is. A block that is gone takes its editor with it.
|
|
171
|
+
onBeforeDeinit: function() {
|
|
172
|
+
open.forEach(hide);
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
onInit: function() {
|
|
176
|
+
open.slice().forEach(function(entry) {
|
|
177
|
+
if (!$.contains(document.documentElement, entry.node[0])) {
|
|
178
|
+
if (entry.editor) { entry.editor.toTextArea(); }
|
|
179
|
+
entry.wrapper.remove();
|
|
180
|
+
open.splice(open.indexOf(entry), 1);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
show(entry);
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
})(jQuery);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(l=>{l.extend(l.fn.gridEditor.locales.en,{"tool.edit_html":"Edit html","codemirror.apply":"Apply","codemirror.cancel":"Cancel"});var s=["row","column","text","plain","element","section"];l.fn.gridEditor.features["codemirror-inline"]=function(i){var t=[];function r(e){var o=e.parent(".ge-text-block");return o.length?o:e}function d(e){var o=r(e.node).addClass("ge-code-hidden");e.wrapper.insertAfter(o),e.editor&&e.editor.refresh()}function o(e){e.wrapper.detach(),r(e.node).removeClass("ge-code-hidden"),e.node.removeClass("ge-code-hidden")}function a(e){o(e),e.editor&&e.editor.toTextArea(),e.wrapper.remove(),t.splice(t.indexOf(e),1)}function n(e){var o,n;o=e,t.filter(function(e){return e.node[0]===o[0]})[0]||((n={node:e,kind:i.kindOf(e),from:i.nodeHtml(e),wrapper:l('<div class="ge-tools-drawer ge-code-inline" />'),editor:null}).textarea=l('<textarea class="ge-code-inline-source" />').val(n.from).appendTo(n.wrapper),e=l('<div class="ge-code-inline-bar" />').appendTo(n.wrapper),l('<button type="button" class="btn btn-sm btn-primary ge-code-apply" />').text(i.t("codemirror.apply")).on("click",function(){var e,o,t,r;t=(e=n).editor?e.editor.getValue():e.textarea.val(),r=i.payloadFor(e.kind,e.node,{source:"tool",from:e.from,to:t}),i.emit("before-edit-html",r)&&(a(e),(r=i.canvas.data("grideditor")).deinit(),o=l("<div />").html(t).contents(),e.node.replaceWith(o),r.init(),i.emit("after-edit-html",i.payloadFor(e.kind,o.filter("*"),{source:"tool",from:e.from,to:t})))}).appendTo(e),l('<button type="button" class="btn btn-sm btn-outline-secondary ge-code-cancel" />').text(i.t("codemirror.cancel")).on("click",function(){a(n)}).appendTo(e),t.push(n),d(n),window.CodeMirror?(n.editor=window.CodeMirror.fromTextArea(n.textarea[0],(e=i.settings.codemirror&&i.settings.codemirror.config||{},l.extend({mode:"htmlmixed",lineNumbers:!0,lineWrapping:!0,tabSize:2,indentUnit:2,viewportMargin:1/0},e))),l(n.editor.getWrapperElement()).addClass("ge-code-editor"),n.editor.focus()):n.textarea.trigger("focus"))}function c(e,o){i.createTool(e,i.t("tool.edit_html"),"ge-edit-html","bi bi-code-slash",function(){n(o)})}return{drawerTools:function(e,o,t){var r;r=o,-1===s.indexOf(t)&&!r.is("[data-ge-container]")||c(e,o)},plainTools:c,onBeforeDeinit:function(){t.forEach(o)},onInit:function(){t.slice().forEach(function(e){l.contains(document.documentElement,e.node[0])?d(e):(e.editor&&e.editor.toTextArea(),e.wrapper.remove(),t.splice(t.indexOf(e),1))})}}}})(jQuery);
|
|
2
|
+
//# sourceMappingURL=grideditor.codemirror-inline.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grideditor.codemirror-inline.min.js","sources":["../../src/js/plugins/grideditor.codemirror-inline.js"],"names":["$","extend","fn","gridEditor","locales","en","tool.edit_html","codemirror.apply","codemirror.cancel","KINDS","features","ge","open","anchorOf","node","textBlock","parent","length","show","entry","anchor","addClass","wrapper","insertAfter","editor","refresh","hide","detach","removeClass","close","toTextArea","remove","splice","indexOf","openEditor","filter","kind","kindOf","from","nodeHtml","textarea","val","appendTo","bar","text","t","on","made","to","payload","getValue","payloadFor","source","emit","instance","canvas","data","deinit","html","contents","replaceWith","init","push","window","CodeMirror","fromTextArea","own","settings","codemirror","config","mode","lineNumbers","lineWrapping","tabSize","indentUnit","viewportMargin","Infinity","getWrapperElement","focus","trigger","tool","drawer","createTool","drawerTools","is","plainTools","onBeforeDeinit","forEach","onInit","slice","contains","document","documentElement","jQuery"],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeMirror for grid-editor's source view.
|
|
3
|
+
*
|
|
4
|
+
* A feature plugin: load this file after the editor, and CodeMirror 5 with
|
|
5
|
+
* its html mode after or before it, and the toolbar's source button edits the
|
|
6
|
+
* canvas's html in CodeMirror - highlighted, with line numbers - rather than
|
|
7
|
+
* in a plain textarea. What it can ask the editor for is the handle its
|
|
8
|
+
* factory is called with, described in docs/plugins.md.
|
|
9
|
+
*
|
|
10
|
+
* <link rel="stylesheet" href="codemirror/lib/codemirror.css">
|
|
11
|
+
* <script src="codemirror/lib/codemirror.js"></script>
|
|
12
|
+
* <script src="codemirror/mode/xml/xml.js"></script>
|
|
13
|
+
* <script src="codemirror/mode/javascript/javascript.js"></script>
|
|
14
|
+
* <script src="codemirror/mode/css/css.js"></script>
|
|
15
|
+
* <script src="codemirror/mode/htmlmixed/htmlmixed.js"></script>
|
|
16
|
+
* <script src="dist/jquery.grideditor.min.js"></script>
|
|
17
|
+
* <script src="dist/plugins/grideditor.codemirror.min.js"></script>
|
|
18
|
+
*
|
|
19
|
+
* CodeMirror 5 rather than 6: 6 comes as ES modules only, for a bundler,
|
|
20
|
+
* where 5 loads from a script tag like the rest of the page. Without
|
|
21
|
+
* CodeMirror on the page the source view is the textarea, as before, and
|
|
22
|
+
* the console says why.
|
|
23
|
+
*/
|
|
24
|
+
(function($) {
|
|
25
|
+
|
|
26
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
27
|
+
'error.codemirror_missing': 'CodeMirror not available! Make sure you loaded the CodeMirror js file; the source is edited in a plain textarea without it.',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
$.fn.gridEditor.features.codemirror = function(ge) {
|
|
31
|
+
|
|
32
|
+
var editor = null;
|
|
33
|
+
var warned = false;
|
|
34
|
+
|
|
35
|
+
function options() {
|
|
36
|
+
var own = (ge.settings.codemirror && ge.settings.codemirror.config) || {};
|
|
37
|
+
|
|
38
|
+
return $.extend({
|
|
39
|
+
mode: 'htmlmixed',
|
|
40
|
+
lineNumbers: true,
|
|
41
|
+
lineWrapping: true,
|
|
42
|
+
tabSize: 2,
|
|
43
|
+
indentUnit: 2,
|
|
44
|
+
}, own);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
// Over the textarea the editor fills with the canvas's html: it goes
|
|
49
|
+
// where the textarea was, as tall as the editor made the textarea
|
|
50
|
+
onSourceOpen: function(textarea) {
|
|
51
|
+
if (!window.CodeMirror) {
|
|
52
|
+
if (!warned) {
|
|
53
|
+
warned = true;
|
|
54
|
+
ge.warn(ge.t('error.codemirror_missing'));
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var height = textarea.height();
|
|
60
|
+
|
|
61
|
+
editor = window.CodeMirror.fromTextArea(textarea[0], options());
|
|
62
|
+
$(editor.getWrapperElement()).addClass('ge-code-editor');
|
|
63
|
+
editor.setSize(null, height);
|
|
64
|
+
editor.focus();
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// What it holds goes back in the textarea, which is what the canvas
|
|
68
|
+
// is made of again, and the textarea is left as it found it
|
|
69
|
+
onSourceClose: function() {
|
|
70
|
+
if (!editor) { return; }
|
|
71
|
+
|
|
72
|
+
editor.save();
|
|
73
|
+
editor.toTextArea();
|
|
74
|
+
editor = null;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
})(jQuery);
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(t=>{t.extend(t.fn.gridEditor.locales.en,{"error.codemirror_missing":"CodeMirror not available! Make sure you loaded the CodeMirror js file; the source is edited in a plain textarea without it."}),t.fn.gridEditor.features.codemirror=function(o){var i=null,n=!1;return{onSourceOpen:function(e){var r;window.CodeMirror?(r=e.height(),i=window.CodeMirror.fromTextArea(e[0],(e=o.settings.codemirror&&o.settings.codemirror.config||{},t.extend({mode:"htmlmixed",lineNumbers:!0,lineWrapping:!0,tabSize:2,indentUnit:2},e))),t(i.getWrapperElement()).addClass("ge-code-editor"),i.setSize(null,r),i.focus()):n||(n=!0,o.warn(o.t("error.codemirror_missing")))},onSourceClose:function(){i&&(i.save(),i.toTextArea(),i=null)}}}})(jQuery);
|
|
2
|
+
//# sourceMappingURL=grideditor.codemirror.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grideditor.codemirror.min.js","sources":["../../src/js/plugins/grideditor.codemirror.js"],"names":["$","extend","fn","gridEditor","locales","en","error.codemirror_missing","features","codemirror","ge","editor","warned","onSourceOpen","textarea","height","window","CodeMirror","fromTextArea","own","settings","config","mode","lineNumbers","lineWrapping","tabSize","indentUnit","getWrapperElement","addClass","setSize","focus","warn","t","onSourceClose","save","toTextArea","jQuery"],"mappings":"CAuBUA,IAEVA,EAAEC,OAAOD,EAAEE,GAAGC,WAAWC,QAAQC,GAAI,CACjCC,2BAA4B,6HAChC,CAAC,EAEDN,EAAEE,GAAGC,WAAWI,SAASC,WAAa,SAASC,GAE3C,IAAIC,EAAS,KACTC,EAAS,CAAA,EAcb,MAAO,CAGHC,aAAc,SAASC,GACnB,IAQIC,EARCC,OAAOC,YAQRF,EAASD,EAASC,OAAO,EAE7BJ,EAASK,OAAOC,WAAWC,aAAaJ,EAAS,IAzBjDK,EAAOT,EAAGU,SAASX,YAAcC,EAAGU,SAASX,WAAWY,QAAW,GAEhEpB,EAAEC,OAAO,CACZoB,KAAM,YACNC,YAAa,CAAA,EACbC,aAAc,CAAA,EACdC,QAAS,EACTC,WAAY,CAChB,EAAGP,CAAG,EAiB4D,EAC9DlB,EAAEU,EAAOgB,kBAAkB,CAAC,EAAEC,SAAS,gBAAgB,EACvDjB,EAAOkB,QAAQ,KAAMd,CAAM,EAC3BJ,EAAOmB,MAAM,GAZJlB,IACDA,EAAS,CAAA,EACTF,EAAGqB,KAAKrB,EAAGsB,EAAE,0BAA0B,CAAC,EAWpD,EAIAC,cAAe,WACNtB,IAELA,EAAOuB,KAAK,EACZvB,EAAOwB,WAAW,EAClBxB,EAAS,KACb,CACJ,CACJ,CAEC,GAAEyB,MAAM"}
|
package/docs/events.md
CHANGED
|
@@ -51,6 +51,8 @@ about every insertion can bind `grideditor:before-add` and switch on
|
|
|
51
51
|
| `grideditor:after-add-text` | `grideditor:after-add` | no | |
|
|
52
52
|
| `grideditor:before-convert` | — | yes | before the host's plain content is made a text, on a click, with the type chosen |
|
|
53
53
|
| `grideditor:after-convert` | — | no | once the type is on it, before its editor has finished opening |
|
|
54
|
+
| `grideditor:before-edit-html` | — | yes | with the codemirror-inline plugin, before a block's html is replaced with what was written; canceled, the editor stays open |
|
|
55
|
+
| `grideditor:after-edit-html` | — | no | once it is, and the canvas is editing again; `node` is what was written, which may be several nodes or none |
|
|
54
56
|
| `grideditor:before-delete` | — | yes | before any node is removed, whatever its kind |
|
|
55
57
|
| `grideditor:after-delete` | — | no | after removal completes, animation included |
|
|
56
58
|
| `grideditor:before-move` | — | yes | on drag start (see *Canceling*) |
|
|
@@ -104,6 +106,10 @@ The payload
|
|
|
104
106
|
from: 'plain',
|
|
105
107
|
to: 'tinymce', // the text type it is made
|
|
106
108
|
|
|
109
|
+
// edit-html only
|
|
110
|
+
from: '<div class="row">…</div>', // the block's html as it was
|
|
111
|
+
to: '<div class="row">…</div>', // what was written
|
|
112
|
+
|
|
107
113
|
// popup-orphan only
|
|
108
114
|
missing: 'ge-popup-3-a91', // the id the trigger pointed at
|
|
109
115
|
|
package/docs/locale-keys.md
CHANGED
|
@@ -165,6 +165,18 @@ The clipboard plugin: copy and paste.
|
|
|
165
165
|
| `clipboard.paste_section` | Paste section | Title of the toolbar's paste button, while a section is copied |
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
codemirror.*
|
|
169
|
+
------------
|
|
170
|
+
|
|
171
|
+
The codemirror-inline plugin: a block's html, edited in place.
|
|
172
|
+
|
|
173
|
+
| Key | English | Where |
|
|
174
|
+
| --- | --- | --- |
|
|
175
|
+
| `tool.edit_html` | Edit html | The </> tool, in the drawers of rows, columns, texts, plain content, elements, sections and containers |
|
|
176
|
+
| `codemirror.apply` | Apply | Under the editor: the block's place takes what was written |
|
|
177
|
+
| `codemirror.cancel` | Cancel | Under the editor: the block stays as it was |
|
|
178
|
+
|
|
179
|
+
|
|
168
180
|
confirm.*
|
|
169
181
|
---------
|
|
170
182
|
|
|
@@ -289,6 +301,7 @@ all the same: the developer reading them is the one who chose the locale.
|
|
|
289
301
|
| `error.tinymce_missing` | tinyMCE not available! … | `content_types: ['tinymce']` with no tinyMCE loaded |
|
|
290
302
|
| `error.ckeditor_missing` | CKEditor not available! … | `content_types: ['ckeditor']` with no CKEditor loaded |
|
|
291
303
|
| `error.summernote_missing` | Summernote not available! … | `content_types: ['summernote']` with no Summernote loaded |
|
|
304
|
+
| `error.codemirror_missing` | CodeMirror not available! … | The codemirror plugin's source view with no CodeMirror loaded: the textarea is used |
|
|
292
305
|
|
|
293
306
|
|
|
294
307
|
Namespaces not in use yet
|
package/docs/plugins.md
CHANGED
|
@@ -161,8 +161,11 @@ $.fn.gridEditor.features.elements = function(ge) {
|
|
|
161
161
|
onInit: function() { … }, // every init: put the furniture in
|
|
162
162
|
onDeinit: function() { … }, // every deinit: take it out again
|
|
163
163
|
onBeforeDeinit: function() { … }, // every deinit, before the drawers come off: close what you opened
|
|
164
|
+
onSourceOpen: function(textarea) { … }, // the source view opened: the canvas's html is in the textarea
|
|
165
|
+
onSourceClose: function(textarea) { … }, // and is closing: put what you edited back in the textarea
|
|
164
166
|
onContentReady: function(area) { … }, // a rich text editor just took over, or rewrote a text
|
|
165
167
|
textTypes: function() { … }, // the text types this plugin edits, see "Text"
|
|
168
|
+
plainTools: function(drawer, block) { … }, // tools for the host's plain content, which has no drawerTools
|
|
166
169
|
|
|
167
170
|
cuts: '[data-my-block]', // what cuts a text: a block of the column, never part of a text
|
|
168
171
|
onSortable: function(sortable) { … }, // declare your own sortable lists
|
|
@@ -253,6 +256,17 @@ rather than remembering anything about it.
|
|
|
253
256
|
Leaving `group` out makes a list that sorts only within itself, which is what
|
|
254
257
|
a tab strip wants. Group names are scoped to the editor instance, so two
|
|
255
258
|
editors on one page never drag into each other.
|
|
259
|
+
- **`onSourceOpen(textarea)`** and **`onSourceClose(textarea)`** are the
|
|
260
|
+
toolbar's source view: it opens with the canvas's html in the textarea, and
|
|
261
|
+
closing it makes the canvas of what is in the textarea then. A code editor
|
|
262
|
+
goes over the textarea on open and puts its value back in it on close, which
|
|
263
|
+
is all the codemirror plugin does; `destroy` with the source open closes it
|
|
264
|
+
first.
|
|
265
|
+
- **`plainTools(drawer, block)`** puts tools in the drawer of the host's plain
|
|
266
|
+
content, between move and delete. That drawer has no gear, so
|
|
267
|
+
`drawerTools` never runs for it: plain content gets no utility, no copy and
|
|
268
|
+
no host tool, only what a plugin gives it here - the codemirror-inline
|
|
269
|
+
plugin's </> tool.
|
|
256
270
|
- **`methods`** are added to the instance handle. A method the editor
|
|
257
271
|
documents but a plugin implements — `createElement` — warns and returns null
|
|
258
272
|
when the plugin is not loaded.
|
|
@@ -285,9 +299,10 @@ Text
|
|
|
285
299
|
What the editor finds in a column that is not the grid's - loose markup, the
|
|
286
300
|
page it was started on before it had a row - it wraps in a content area with
|
|
287
301
|
no type: the host's **plain content**, `<div class="ge-content">`. While
|
|
288
|
-
editing it is a block with a drawer of
|
|
289
|
-
gear; it is edited in the source, with
|
|
290
|
-
|
|
302
|
+
editing it is a block with a drawer of move and delete - and what a plugin's
|
|
303
|
+
`plainTools` add between them - and no gear; it is edited in the source, with
|
|
304
|
+
the toolbar's code button or the codemirror-inline plugin's </> tool, and
|
|
305
|
+
nothing in the editor makes a new one. `getHtml` saves it as it is, and it is plain
|
|
291
306
|
content again when the page comes back. Events call it `kind: 'plain'`.
|
|
292
307
|
|
|
293
308
|
A text is a content area with a type on it - `data-ge-content-type` and the
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/lib/codemirror.min.css">
|
|
10
|
+
|
|
11
|
+
<!-- Javascript dependencies -->
|
|
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
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/6.8.6/tinymce.min.js"></script>
|
|
15
|
+
|
|
16
|
+
<!-- CodeMirror 5 and its html mode, which is made of the xml, javascript
|
|
17
|
+
and css modes -->
|
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/lib/codemirror.min.js"></script>
|
|
19
|
+
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/xml/xml.min.js"></script>
|
|
20
|
+
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/javascript/javascript.min.js"></script>
|
|
21
|
+
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/css/css.min.js"></script>
|
|
22
|
+
<script src="https://cdn.jsdelivr.net/npm/codemirror@5.65.21/mode/htmlmixed/htmlmixed.min.js"></script>
|
|
23
|
+
|
|
24
|
+
<!-- Grid editor CSS -->
|
|
25
|
+
<link rel="stylesheet" type="text/css" href="../dist/grideditor.css" />
|
|
26
|
+
<!-- Grid editor javascript -->
|
|
27
|
+
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
|
|
28
|
+
<script src="../dist/jquery.grideditor.min.js"></script>
|
|
29
|
+
<script src="../dist/plugins/grideditor.tinymce.min.js"></script>
|
|
30
|
+
<!-- The source view in CodeMirror, a plugin of its own -->
|
|
31
|
+
<script src="../dist/plugins/grideditor.codemirror.min.js"></script>
|
|
32
|
+
<!-- And each block's html, in place, from the </> tool in its drawer -->
|
|
33
|
+
<script src="../dist/plugins/grideditor.codemirror-inline.min.js"></script>
|
|
34
|
+
|
|
35
|
+
<script>
|
|
36
|
+
$(function() {
|
|
37
|
+
function start() {
|
|
38
|
+
if ($('#myGrid').data('grideditor')) { $('#myGrid').gridEditor('destroy'); }
|
|
39
|
+
|
|
40
|
+
$('#myGrid').gridEditor({
|
|
41
|
+
new_row_layouts: [[12], [6, 6], [4, 4, 4]],
|
|
42
|
+
// false leaves the toolbar's source button out
|
|
43
|
+
edit_source: $('#editSource').prop('checked'),
|
|
44
|
+
// Anything CodeMirror.fromTextArea takes, over the
|
|
45
|
+
// plugin's own defaults
|
|
46
|
+
codemirror: {
|
|
47
|
+
config: { lineNumbers: true },
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
$('#editSource').on('change', start);
|
|
53
|
+
start();
|
|
54
|
+
});
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<title>Grid Editor example - the source in CodeMirror</title>
|
|
58
|
+
</head>
|
|
59
|
+
<body>
|
|
60
|
+
<!-- Back to the demo index -->
|
|
61
|
+
<div class="container pt-3">
|
|
62
|
+
<a class="link-secondary" href="index.html"><i class="bi bi-arrow-left"></i> All demos</a>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="container py-3">
|
|
66
|
+
<h2>The source in CodeMirror</h2>
|
|
67
|
+
<p class="text-body-secondary">
|
|
68
|
+
The toolbar's <i class="bi bi-code-slash"></i> button turns the
|
|
69
|
+
canvas into its html, to edit by hand. With the codemirror plugin
|
|
70
|
+
loaded that html is in <a href="https://codemirror.net/5/">CodeMirror</a>,
|
|
71
|
+
highlighted and with line numbers, instead of a plain textarea; the
|
|
72
|
+
same button brings the canvas back with what you wrote.
|
|
73
|
+
<code>edit_source: false</code> leaves the button out.
|
|
74
|
+
</p>
|
|
75
|
+
<p class="text-body-secondary">
|
|
76
|
+
The codemirror-inline plugin puts a <i class="bi bi-code-slash"></i>
|
|
77
|
+
tool in the drawer of every row, column, text, element and
|
|
78
|
+
container, and of the page's plain content: it opens that block's
|
|
79
|
+
html, the block itself and all that is in it, in CodeMirror where
|
|
80
|
+
the block was. <em>Apply</em> puts what you wrote in its place.
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
<div class="form-check mb-3">
|
|
84
|
+
<input class="form-check-input" type="checkbox" id="editSource" checked>
|
|
85
|
+
<label class="form-check-label" for="editSource"><code>edit_source</code></label>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div id="myGrid">
|
|
89
|
+
<div class="row">
|
|
90
|
+
<div class="col-lg-6">
|
|
91
|
+
<h3>Edit me as html</h3>
|
|
92
|
+
<p>Press the code button in the toolbar and this is CodeMirror.</p>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="col-lg-6">
|
|
95
|
+
<div class="ge-content ge-content-type-tinymce" data-ge-content-type="tinymce">
|
|
96
|
+
<p>A text, saved as one: a click edits it in tinyMCE.</p>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</body>
|
|
103
|
+
</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="codemirror.html">
|
|
65
|
+
<div class="d-flex justify-content-between">
|
|
66
|
+
<strong>The source in CodeMirror</strong>
|
|
67
|
+
<code class="text-body-secondary">codemirror.html</code>
|
|
68
|
+
</div>
|
|
69
|
+
<span class="text-body-secondary">The source button's html in a code editor, and edit_source to leave the button out</span>
|
|
70
|
+
</a>
|
|
71
|
+
|
|
64
72
|
<a class="list-group-item list-group-item-action" href="custom_editor.html">
|
|
65
73
|
<div class="d-flex justify-content-between">
|
|
66
74
|
<strong>A text editor of your own</strong>
|
package/package.json
CHANGED
|
@@ -358,6 +358,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
358
358
|
'default_view' : ALL_VIEW,
|
|
359
359
|
'resize' : NESTED_SETTINGS.resize, // Resizing a column by dragging its edge
|
|
360
360
|
'source_textarea' : '',
|
|
361
|
+
'edit_source' : true, // The toolbar's button to edit the canvas as html
|
|
361
362
|
'locale' : 'en', // Code of a locale in $.fn.gridEditor.locales
|
|
362
363
|
'locale_strings' : {}, // Overrides for individual keys
|
|
363
364
|
'callbacks' : {}, // before_*/after_* functions, the events by another route
|
|
@@ -397,6 +398,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
397
398
|
var curView = settings.default_view; // Breakpoint key, or 'all'
|
|
398
399
|
var confirmDialog = null; // The delete confirmation, built when first needed
|
|
399
400
|
var sizePicker = null; // The open column size picker, if there is one
|
|
401
|
+
var sourceOpen = false; // Whether the canvas is being edited as html
|
|
400
402
|
var dropMarker = null; // The line showing where a dragged toolbar button would land
|
|
401
403
|
var warnedHere = {}; // Deprecations are worth saying once per instance, not once per call
|
|
402
404
|
var sortables = []; // Every list made sortable, so deinit destroys exactly those
|
|
@@ -1003,27 +1005,23 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1003
1005
|
var btnGroup = $('<div class="btn-group pull-right"/>')
|
|
1004
1006
|
.appendTo(wrapper)
|
|
1005
1007
|
;
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
.val(canvas.html())
|
|
1018
|
-
.show()
|
|
1019
|
-
;
|
|
1020
|
-
canvas.hide();
|
|
1021
|
-
}
|
|
1008
|
+
if (settings.edit_source) {
|
|
1009
|
+
// Built again by setLocale, maybe with the source open
|
|
1010
|
+
var htmlButton = $('<button type="button" class="btn btn-sm btn-primary gm-edit-mode"><i class="bi bi-code-slash"></i></button>')
|
|
1011
|
+
.attr('title', t('tool.edit_source'))
|
|
1012
|
+
.toggleClass('active btn-danger', sourceOpen)
|
|
1013
|
+
.on('click', function() {
|
|
1014
|
+
if (sourceOpen) {
|
|
1015
|
+
closeSource();
|
|
1016
|
+
} else {
|
|
1017
|
+
openSource();
|
|
1018
|
+
}
|
|
1022
1019
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1020
|
+
htmlButton.toggleClass('active btn-danger', sourceOpen);
|
|
1021
|
+
})
|
|
1022
|
+
.appendTo(btnGroup)
|
|
1023
|
+
;
|
|
1024
|
+
}
|
|
1027
1025
|
var previewButton = $('<button type="button" class="btn btn-sm btn-primary gm-preview"><i class="bi bi-eye-fill"></i></button>')
|
|
1028
1026
|
.attr('title', t('tool.preview'))
|
|
1029
1027
|
.on('mouseenter', function() {
|
|
@@ -1584,6 +1582,32 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1584
1582
|
init();
|
|
1585
1583
|
}
|
|
1586
1584
|
|
|
1585
|
+
/**
|
|
1586
|
+
* The canvas as html, in the textarea in its place, to edit by hand.
|
|
1587
|
+
* A feature plugin's onSourceOpen may put a code editor over the
|
|
1588
|
+
* textarea; its onSourceClose puts what it holds back in it, which is
|
|
1589
|
+
* what the canvas is made of again.
|
|
1590
|
+
*/
|
|
1591
|
+
function openSource() {
|
|
1592
|
+
deinit();
|
|
1593
|
+
htmlTextArea
|
|
1594
|
+
.height(0.8 * $(window).height())
|
|
1595
|
+
.val(canvas.html())
|
|
1596
|
+
.show()
|
|
1597
|
+
;
|
|
1598
|
+
canvas.hide();
|
|
1599
|
+
sourceOpen = true;
|
|
1600
|
+
plugins('onSourceOpen', htmlTextArea);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
function closeSource() {
|
|
1604
|
+
plugins('onSourceClose', htmlTextArea);
|
|
1605
|
+
sourceOpen = false;
|
|
1606
|
+
canvas.empty().html(htmlTextArea.val()).show();
|
|
1607
|
+
init();
|
|
1608
|
+
htmlTextArea.hide();
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1587
1611
|
function init() {
|
|
1588
1612
|
// The node whose settings were open is gone - deleted, say - and
|
|
1589
1613
|
// its panel with it
|
|
@@ -1662,6 +1686,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1662
1686
|
}
|
|
1663
1687
|
|
|
1664
1688
|
function destroy() {
|
|
1689
|
+
// The html being edited is what the canvas is left with
|
|
1690
|
+
if (sourceOpen) { closeSource(); }
|
|
1665
1691
|
deinit();
|
|
1666
1692
|
removeConfirmModal();
|
|
1667
1693
|
removeSettingsPanels();
|
|
@@ -4581,6 +4607,13 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
4581
4607
|
textBlock.addClass('ge-plain-block');
|
|
4582
4608
|
|
|
4583
4609
|
createMoveTool(drawer);
|
|
4610
|
+
|
|
4611
|
+
// The tools a feature plugin gives plain content, which is not
|
|
4612
|
+
// every plugin's drawerTools: no gear, no utilities, no copy
|
|
4613
|
+
$.each(FEATURES, function(name, feature) {
|
|
4614
|
+
if (feature.plainTools) { feature.plainTools(drawer, block); }
|
|
4615
|
+
});
|
|
4616
|
+
|
|
4584
4617
|
createTool(drawer, t('tool.delete_plain'), 'ge-delete-plain', 'bi bi-trash', function() {
|
|
4585
4618
|
deleteNode('plain', block, t('confirm.delete_plain'), function(removed) {
|
|
4586
4619
|
textBlock.slideUp(function() {
|