@themarioga/grid-editor 3.1.0 → 3.2.1

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 CHANGED
@@ -5,6 +5,19 @@ 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
+ ## [3.2.1] - 2026-09-22
9
+ ### Changed
10
+ - `example/containers.html` shows a card too: its own row, with two columns
11
+ inside the card body, beside the tabs, the accordion and the popup.
12
+
13
+
14
+ ## [3.2.0] - 2026-09-22
15
+ ### Added
16
+ - A card container plugin, `dist/plugins/grideditor.card.js`: a bootstrap card
17
+ whose body is an editable region, with an editable header and an optional
18
+ footer. `header: false` leaves the title out, `footer` adds one.
19
+
20
+
8
21
  ## [3.1.0] - 2026-09-22
9
22
  ### Added
10
23
  - A public API, dispatched from a table instead of a chain of string
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Grid Editor
2
2
  ===========
3
3
 
4
- Grid Editor is a visual javascript editor for the [bootstrap 5 grid system](https://getbootstrap.com/docs/5.3/layout/grid/), written as a [jQuery](http://jquery.com/) plugin. You can create, drag, resize and delete rows and columns, indent them, and give each of bootstrap's six breakpoints its own layout — or edit them all at once. It also edits tabs, accordions and popups, and any markup you mark as an element, and it tells your application about every change it makes.
4
+ Grid Editor is a visual javascript editor for the [bootstrap 5 grid system](https://getbootstrap.com/docs/5.3/layout/grid/), written as a [jQuery](http://jquery.com/) plugin. You can create, drag, resize and delete rows and columns, indent them, and give each of bootstrap's six breakpoints its own layout — or edit them all at once. It also edits tabs, accordions, popups and cards, and any markup you mark as an element, and it tells your application about every change it makes.
5
5
 
6
6
  This is a fork of [Friendly-Pixel/grid-editor](https://github.com/Friendly-Pixel/grid-editor)
7
7
  by Simon Epskamp, carrying it on from 2.x. It is published as
@@ -16,22 +16,25 @@ It provides integration plugins for the following rich text editors to edit colu
16
16
  Demos
17
17
  -----
18
18
 
19
+ __[Try it live](https://themarioga.github.io/grid-editor/example/)__ — every
20
+ demo below, running on GitHub Pages.
21
+
19
22
  Every page under `example/` is a working editor, and they are static: served
20
23
  from any web server, or from GitHub Pages, with no build step.
21
24
  [example/index.html](example/index.html) lists them all.
22
25
 
23
- | Demo | What it shows |
24
- | --- | --- |
25
- | [example/basic.html](example/basic.html) | The editor with tinyMCE in the content areas |
26
- | [example/breakpoints.html](example/breakpoints.html) | The six breakpoints and the "all sizes" view |
27
- | [example/plugins.html](example/plugins.html) | The plugin model, with one written in the page itself |
28
- | [example/containers.html](example/containers.html) | Tabs, accordions and popups, two levels deep |
29
- | [example/elements.html](example/elements.html) | Element level controls, including an element with no visual output |
30
- | [example/locale.html](example/locale.html) | The interface in Spanish, with a language switcher |
31
- | [example/ckeditor.html](example/ckeditor.html) | CKEditor instead of tinyMCE |
32
- | [example/summernote.html](example/summernote.html) | Summernote instead of tinyMCE |
33
- | [example/wrap_content.html](example/wrap_content.html) | Non-bootstrap markup wrapped into the grid |
34
- | [example/autosave.html](example/autosave.html) | Saving the html as the user edits |
26
+ | Demo | What it shows | |
27
+ | --- | --- | --- |
28
+ | [example/basic.html](example/basic.html) | The editor with tinyMCE in the content areas | [live](https://themarioga.github.io/grid-editor/example/basic.html) |
29
+ | [example/breakpoints.html](example/breakpoints.html) | The six breakpoints and the "all sizes" view | [live](https://themarioga.github.io/grid-editor/example/breakpoints.html) |
30
+ | [example/plugins.html](example/plugins.html) | The plugin model, with one written in the page itself | [live](https://themarioga.github.io/grid-editor/example/plugins.html) |
31
+ | [example/containers.html](example/containers.html) | Tabs, accordions, popups and cards, two levels deep | [live](https://themarioga.github.io/grid-editor/example/containers.html) |
32
+ | [example/elements.html](example/elements.html) | Element level controls, including an element with no visual output | [live](https://themarioga.github.io/grid-editor/example/elements.html) |
33
+ | [example/locale.html](example/locale.html) | The interface in Spanish, with a language switcher | [live](https://themarioga.github.io/grid-editor/example/locale.html) |
34
+ | [example/ckeditor.html](example/ckeditor.html) | CKEditor instead of tinyMCE | [live](https://themarioga.github.io/grid-editor/example/ckeditor.html) |
35
+ | [example/summernote.html](example/summernote.html) | Summernote instead of tinyMCE | [live](https://themarioga.github.io/grid-editor/example/summernote.html) |
36
+ | [example/wrap_content.html](example/wrap_content.html) | Non-bootstrap markup wrapped into the grid | [live](https://themarioga.github.io/grid-editor/example/wrap_content.html) |
37
+ | [example/autosave.html](example/autosave.html) | Saving the html as the user edits | [live](https://themarioga.github.io/grid-editor/example/autosave.html) |
35
38
 
36
39
  Installation
37
40
  ------------
@@ -357,9 +360,10 @@ pattern for an element with no visual output of its own.
357
360
 
358
361
  ### Containers
359
362
 
360
- Tabs, accordions and popups. Each holds panes, and a pane is an ordinary
361
- region: rows, columns, content areas and elements nest inside one exactly as
362
- they do at the top level.
363
+ Tabs, accordions, popups and cards. A tabs, accordion or popup container holds
364
+ panes; a card holds one region. Either way a region is an ordinary one: rows,
365
+ columns, content areas and elements nest inside it exactly as they do at the
366
+ top level.
363
367
 
364
368
  Each type is a plugin, in a file of its own, and loading the file is what makes
365
369
  it available:
@@ -369,6 +373,7 @@ it available:
369
373
  <script src="grid-editor/dist/plugins/grideditor.tabs.min.js"></script>
370
374
  <script src="grid-editor/dist/plugins/grideditor.accordion.min.js"></script>
371
375
  <script src="grid-editor/dist/plugins/grideditor.popup.min.js"></script>
376
+ <script src="grid-editor/dist/plugins/grideditor.card.min.js"></script>
372
377
  ```
373
378
 
374
379
  The toolbar offers a button per loaded plugin. See [docs/plugins.md](docs/plugins.md)
@@ -50,6 +50,9 @@
50
50
  'container.add_popup': 'Ventana emergente',
51
51
  'container.popup_title': 'Título',
52
52
  'container.popup_trigger': 'Abrir',
53
+ 'container.add_card': 'Tarjeta',
54
+ 'container.card_title': 'Título de la tarjeta',
55
+ 'container.card_footer': 'Pie de la tarjeta',
53
56
  'confirm.title': 'Confirmar',
54
57
  'confirm.ok': 'Borrar',
55
58
  'confirm.cancel': 'Cancelar',
@@ -1,2 +1,2 @@
1
- jQuery.fn.gridEditor.locales.es={"tool.move":"Mover","tool.settings":"Configuración","tool.add_row":"Añadir fila","tool.add_column":"Añadir columna\n(mantén pulsado para elegir el ancho)","tool.column_size":"{size} de 12","tool.delete_row":"Borrar fila","tool.delete_column":"Borrar columna","tool.delete_element":"Borrar elemento","tool.delete_container":"Borrar contenedor","tool.delete_pane":"Borrar panel","tool.rename":"Haz doble clic para renombrar","tool.toggle_popup":"Plegar esta ventana mientras editas","tool.element_info":"Elemento: {name}","tool.column_narrower":"Estrechar columna\n(Mayús para el mínimo)","tool.column_wider":"Ensanchar columna\n(Mayús para el máximo)","tool.indent_decrease":"Reducir sangría\n(Mayús para quitarla)","tool.indent_increase":"Aumentar sangría\n(Mayús para el máximo)","tool.edit_source":"Editar el código fuente","tool.preview":"Vista previa","tool.id_placeholder":"id","tool.id_title":"Asignar un identificador único","tool.classes_placeholder":"clases","tool.classes_title":"Clases css, separadas por espacios","tool.toggle_class":'Aplicar o quitar el estilo "{label}"',"row.add":"Añadir fila {layout}","container.add_tabs":"Pestañas","container.add_tab":"Añadir pestaña","container.tab_label":"Pestaña {number}","container.add_accordion":"Acordeón","container.add_accordion_item":"Añadir apartado","container.accordion_label":"Apartado {number}","container.add_popup":"Ventana emergente","container.popup_title":"Título","container.popup_trigger":"Abrir","confirm.title":"Confirmar","confirm.ok":"Borrar","confirm.cancel":"Cancelar","confirm.delete_row":"¿Seguro que quieres borrar esta fila?","confirm.delete_column":"¿Seguro que quieres borrar esta columna?","confirm.delete_element":"¿Seguro que quieres borrar este elemento?","confirm.delete_container":"¿Seguro que quieres borrar este contenedor y todo su contenido?","confirm.delete_tab":"¿Seguro que quieres borrar esta pestaña y todo su contenido?","confirm.delete_accordion_item":"¿Seguro que quieres borrar este apartado y todo su contenido?","view.all":"Todos los tamaños","view.xs":"Móvil","view.sm":"Tablet","view.md":"Escritorio pequeño","view.lg":"Escritorio","view.xl":"Escritorio grande","view.xxl":"Pantalla panorámica","error.tinymce_missing":"¡tinyMCE no está disponible! Asegúrate de haber cargado el archivo js de tinyMCE.","error.ckeditor_missing":"¡CKEditor no está disponible! Asegúrate de haber cargado los archivos js de ckeditor y del adaptador de jQuery.","error.summernote_missing":"¡Summernote no está disponible! Asegúrate de haber cargado el archivo js de Summernote."};
1
+ jQuery.fn.gridEditor.locales.es={"tool.move":"Mover","tool.settings":"Configuración","tool.add_row":"Añadir fila","tool.add_column":"Añadir columna\n(mantén pulsado para elegir el ancho)","tool.column_size":"{size} de 12","tool.delete_row":"Borrar fila","tool.delete_column":"Borrar columna","tool.delete_element":"Borrar elemento","tool.delete_container":"Borrar contenedor","tool.delete_pane":"Borrar panel","tool.rename":"Haz doble clic para renombrar","tool.toggle_popup":"Plegar esta ventana mientras editas","tool.element_info":"Elemento: {name}","tool.column_narrower":"Estrechar columna\n(Mayús para el mínimo)","tool.column_wider":"Ensanchar columna\n(Mayús para el máximo)","tool.indent_decrease":"Reducir sangría\n(Mayús para quitarla)","tool.indent_increase":"Aumentar sangría\n(Mayús para el máximo)","tool.edit_source":"Editar el código fuente","tool.preview":"Vista previa","tool.id_placeholder":"id","tool.id_title":"Asignar un identificador único","tool.classes_placeholder":"clases","tool.classes_title":"Clases css, separadas por espacios","tool.toggle_class":'Aplicar o quitar el estilo "{label}"',"row.add":"Añadir fila {layout}","container.add_tabs":"Pestañas","container.add_tab":"Añadir pestaña","container.tab_label":"Pestaña {number}","container.add_accordion":"Acordeón","container.add_accordion_item":"Añadir apartado","container.accordion_label":"Apartado {number}","container.add_popup":"Ventana emergente","container.popup_title":"Título","container.popup_trigger":"Abrir","container.add_card":"Tarjeta","container.card_title":"Título de la tarjeta","container.card_footer":"Pie de la tarjeta","confirm.title":"Confirmar","confirm.ok":"Borrar","confirm.cancel":"Cancelar","confirm.delete_row":"¿Seguro que quieres borrar esta fila?","confirm.delete_column":"¿Seguro que quieres borrar esta columna?","confirm.delete_element":"¿Seguro que quieres borrar este elemento?","confirm.delete_container":"¿Seguro que quieres borrar este contenedor y todo su contenido?","confirm.delete_tab":"¿Seguro que quieres borrar esta pestaña y todo su contenido?","confirm.delete_accordion_item":"¿Seguro que quieres borrar este apartado y todo su contenido?","view.all":"Todos los tamaños","view.xs":"Móvil","view.sm":"Tablet","view.md":"Escritorio pequeño","view.lg":"Escritorio","view.xl":"Escritorio grande","view.xxl":"Pantalla panorámica","error.tinymce_missing":"¡tinyMCE no está disponible! Asegúrate de haber cargado el archivo js de tinyMCE.","error.ckeditor_missing":"¡CKEditor no está disponible! Asegúrate de haber cargado los archivos js de ckeditor y del adaptador de jQuery.","error.summernote_missing":"¡Summernote no está disponible! Asegúrate de haber cargado el archivo js de Summernote."};
2
2
  //# sourceMappingURL=grideditor.es.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grideditor.es.min.js","sources":["../../src/js/locales/grideditor.es.js"],"names":["jQuery","fn","gridEditor","locales","es","tool.move","tool.settings","tool.add_row","tool.add_column","tool.column_size","tool.delete_row","tool.delete_column","tool.delete_element","tool.delete_container","tool.delete_pane","tool.rename","tool.toggle_popup","tool.element_info","tool.column_narrower","tool.column_wider","tool.indent_decrease","tool.indent_increase","tool.edit_source","tool.preview","tool.id_placeholder","tool.id_title","tool.classes_placeholder","tool.classes_title","tool.toggle_class","row.add","container.add_tabs","container.add_tab","container.tab_label","container.add_accordion","container.add_accordion_item","container.accordion_label","container.add_popup","container.popup_title","container.popup_trigger","confirm.title","confirm.ok","confirm.cancel","confirm.delete_row","confirm.delete_column","confirm.delete_element","confirm.delete_container","confirm.delete_tab","confirm.delete_accordion_item","view.all","view.xs","view.sm","view.md","view.lg","view.xl","view.xxl","error.tinymce_missing","error.ckeditor_missing","error.summernote_missing"],"mappings":"AAyEGA,OAxDGC,GAAGC,WAAWC,QAAQC,GAAK,CACzBC,YAAa,QACbC,gBAAiB,gBACjBC,eAAgB,cAChBC,kBAAmB,wDACnBC,mBAAoB,eACpBC,kBAAmB,cACnBC,qBAAsB,iBACtBC,sBAAuB,kBACvBC,wBAAyB,oBACzBC,mBAAoB,eACpBC,cAAe,gCACfC,oBAAqB,sCACrBC,oBAAqB,mBACrBC,uBAAwB,4CACxBC,oBAAqB,4CACrBC,uBAAwB,yCACxBC,uBAAwB,2CACxBC,mBAAoB,0BACpBC,eAAgB,eAChBC,sBAAuB,KACvBC,gBAAiB,iCACjBC,2BAA4B,SAC5BC,qBAAsB,qCACtBC,oBAAqB,uCACrBC,UAAW,uBACXC,qBAAsB,WACtBC,oBAAqB,iBACrBC,sBAAuB,mBACvBC,0BAA2B,WAC3BC,+BAAgC,kBAChCC,4BAA6B,oBAC7BC,sBAAuB,oBACvBC,wBAAyB,SACzBC,0BAA2B,QAC3BC,gBAAiB,YACjBC,aAAc,SACdC,iBAAkB,WAClBC,qBAAsB,wCACtBC,wBAAyB,2CACzBC,yBAA0B,4CAC1BC,2BAA4B,kEAC5BC,qBAAsB,+DACtBC,gCAAiC,gEACjCC,WAAY,oBACZC,UAAW,QACXC,UAAW,SACXC,UAAW,qBACXC,UAAW,aACXC,UAAW,oBACXC,WAAY,sBACZC,wBAAyB,oFACzBC,yBAA0B,kHAC1BC,2BAA4B,yFAChC"}
1
+ {"version":3,"file":"grideditor.es.min.js","sources":["../../src/js/locales/grideditor.es.js"],"names":["jQuery","fn","gridEditor","locales","es","tool.move","tool.settings","tool.add_row","tool.add_column","tool.column_size","tool.delete_row","tool.delete_column","tool.delete_element","tool.delete_container","tool.delete_pane","tool.rename","tool.toggle_popup","tool.element_info","tool.column_narrower","tool.column_wider","tool.indent_decrease","tool.indent_increase","tool.edit_source","tool.preview","tool.id_placeholder","tool.id_title","tool.classes_placeholder","tool.classes_title","tool.toggle_class","row.add","container.add_tabs","container.add_tab","container.tab_label","container.add_accordion","container.add_accordion_item","container.accordion_label","container.add_popup","container.popup_title","container.popup_trigger","container.add_card","container.card_title","container.card_footer","confirm.title","confirm.ok","confirm.cancel","confirm.delete_row","confirm.delete_column","confirm.delete_element","confirm.delete_container","confirm.delete_tab","confirm.delete_accordion_item","view.all","view.xs","view.sm","view.md","view.lg","view.xl","view.xxl","error.tinymce_missing","error.ckeditor_missing","error.summernote_missing"],"mappings":"AA4EGA,OA3DGC,GAAGC,WAAWC,QAAQC,GAAK,CACzBC,YAAa,QACbC,gBAAiB,gBACjBC,eAAgB,cAChBC,kBAAmB,wDACnBC,mBAAoB,eACpBC,kBAAmB,cACnBC,qBAAsB,iBACtBC,sBAAuB,kBACvBC,wBAAyB,oBACzBC,mBAAoB,eACpBC,cAAe,gCACfC,oBAAqB,sCACrBC,oBAAqB,mBACrBC,uBAAwB,4CACxBC,oBAAqB,4CACrBC,uBAAwB,yCACxBC,uBAAwB,2CACxBC,mBAAoB,0BACpBC,eAAgB,eAChBC,sBAAuB,KACvBC,gBAAiB,iCACjBC,2BAA4B,SAC5BC,qBAAsB,qCACtBC,oBAAqB,uCACrBC,UAAW,uBACXC,qBAAsB,WACtBC,oBAAqB,iBACrBC,sBAAuB,mBACvBC,0BAA2B,WAC3BC,+BAAgC,kBAChCC,4BAA6B,oBAC7BC,sBAAuB,oBACvBC,wBAAyB,SACzBC,0BAA2B,QAC3BC,qBAAsB,UACtBC,uBAAwB,uBACxBC,wBAAyB,oBACzBC,gBAAiB,YACjBC,aAAc,SACdC,iBAAkB,WAClBC,qBAAsB,wCACtBC,wBAAyB,2CACzBC,yBAA0B,4CAC1BC,2BAA4B,kEAC5BC,qBAAsB,+DACtBC,gCAAiC,gEACjCC,WAAY,oBACZC,UAAW,QACXC,UAAW,SACXC,UAAW,qBACXC,UAAW,aACXC,UAAW,oBACXC,WAAY,sBACZC,wBAAyB,oFACzBC,yBAA0B,kHAC1BC,2BAA4B,yFAChC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Cards for grid-editor.
3
+ *
4
+ * A container plugin: load this file after the editor and the toolbar offers
5
+ * a card, a bootstrap card whose body is an editable region. What it can ask
6
+ * the editor for is the handle its factory is called with, described in
7
+ * docs/plugins.md.
8
+ *
9
+ * <script src="dist/jquery.grideditor.min.js"></script>
10
+ * <script src="dist/plugins/grideditor.card.min.js"></script>
11
+ */
12
+ (function($) {
13
+
14
+ $.extend($.fn.gridEditor.locales.en, {
15
+ 'container.add_card': 'Card',
16
+ 'container.card_title': 'Card title',
17
+ 'container.card_footer': 'Card footer',
18
+ });
19
+
20
+ $.fn.gridEditor.containers.card = function(ge) {
21
+
22
+ return {
23
+ labelKey: 'container.add_card',
24
+
25
+ /**
26
+ * A card is a header, a body and an optional footer. `header: false`
27
+ * leaves the title out, `footer: true` or a string adds one; both are
28
+ * plain text the editor makes editable, not regions, so a card holds
29
+ * exactly one region and nests like any other container.
30
+ */
31
+ create: function(options) {
32
+ var card = $('<div class="card" />');
33
+
34
+ if (options.header !== false) {
35
+ $('<div class="card-header" />')
36
+ .append($('<span class="ge-pane-label" />')
37
+ .text(options.title || ge.t('container.card_title')))
38
+ .appendTo(card)
39
+ ;
40
+ }
41
+
42
+ $('<div class="card-body" />').append(ge.defaultRegion()).appendTo(card);
43
+
44
+ if (options.footer) {
45
+ $('<div class="card-footer text-body-secondary" />')
46
+ .append($('<span class="ge-pane-label" />')
47
+ .text(typeof options.footer === 'string'
48
+ ? options.footer
49
+ : ge.t('container.card_footer')))
50
+ .appendTo(card)
51
+ ;
52
+ }
53
+
54
+ return $('<div />').attr('data-ge-container', 'card').append(card);
55
+ },
56
+
57
+ mark: function(container) {
58
+ ge.makeLabelEditable(ge.labelIn(container.find('> .card > .card-header')));
59
+ ge.makeLabelEditable(ge.labelIn(container.find('> .card > .card-footer')));
60
+ },
61
+
62
+ unmark: function(container) {
63
+ ge.unwrapLabels(container);
64
+ },
65
+ };
66
+ };
67
+
68
+ })(jQuery);
@@ -0,0 +1,2 @@
1
+ (d=>{d.extend(d.fn.gridEditor.locales.en,{"container.add_card":"Card","container.card_title":"Card title","container.card_footer":"Card footer"}),d.fn.gridEditor.containers.card=function(r){return{labelKey:"container.add_card",create:function(a){var e=d('<div class="card" />');return!1!==a.header&&d('<div class="card-header" />').append(d('<span class="ge-pane-label" />').text(a.title||r.t("container.card_title"))).appendTo(e),d('<div class="card-body" />').append(r.defaultRegion()).appendTo(e),a.footer&&d('<div class="card-footer text-body-secondary" />').append(d('<span class="ge-pane-label" />').text("string"==typeof a.footer?a.footer:r.t("container.card_footer"))).appendTo(e),d("<div />").attr("data-ge-container","card").append(e)},mark:function(a){r.makeLabelEditable(r.labelIn(a.find("> .card > .card-header"))),r.makeLabelEditable(r.labelIn(a.find("> .card > .card-footer")))},unmark:function(a){r.unwrapLabels(a)}}}})(jQuery);
2
+ //# sourceMappingURL=grideditor.card.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grideditor.card.min.js","sources":["../../src/js/plugins/grideditor.card.js"],"names":["$","extend","fn","gridEditor","locales","en","container.add_card","container.card_title","container.card_footer","containers","card","ge","labelKey","create","options","header","append","text","title","t","appendTo","defaultRegion","footer","attr","mark","container","makeLabelEditable","labelIn","find","unmark","unwrapLabels","jQuery"],"mappings":"CAWUA,IAEVA,EAAEC,OAAOD,EAAEE,GAAGC,WAAWC,QAAQC,GAAI,CACjCC,qBAAsB,OACtBC,uBAAwB,aACxBC,wBAAyB,aAC7B,CAAC,EAEDR,EAAEE,GAAGC,WAAWM,WAAWC,KAAO,SAASC,GAEvC,MAAO,CACHC,SAAU,qBAQVC,OAAQ,SAASC,GACb,IAAIJ,EAAOV,EAAE,sBAAsB,EAsBnC,MApBuB,CAAA,IAAnBc,EAAQC,QACRf,EAAE,6BAA6B,EAC1BgB,OAAOhB,EAAE,gCAAgC,EACrCiB,KAAKH,EAAQI,OAASP,EAAGQ,EAAE,sBAAsB,CAAC,CAAC,EACvDC,SAASV,CAAI,EAItBV,EAAE,2BAA2B,EAAEgB,OAAOL,EAAGU,cAAc,CAAC,EAAED,SAASV,CAAI,EAEnEI,EAAQQ,QACRtB,EAAE,iDAAiD,EAC9CgB,OAAOhB,EAAE,gCAAgC,EACrCiB,KAA+B,UAA1B,OAAOH,EAAQQ,OACfR,EAAQQ,OACRX,EAAGQ,EAAE,uBAAuB,CAAC,CAAC,EACvCC,SAASV,CAAI,EAIfV,EAAE,SAAS,EAAEuB,KAAK,oBAAqB,MAAM,EAAEP,OAAON,CAAI,CACrE,EAEAc,KAAM,SAASC,GACXd,EAAGe,kBAAkBf,EAAGgB,QAAQF,EAAUG,KAAK,wBAAwB,CAAC,CAAC,EACzEjB,EAAGe,kBAAkBf,EAAGgB,QAAQF,EAAUG,KAAK,wBAAwB,CAAC,CAAC,CAC7E,EAEAC,OAAQ,SAASJ,GACbd,EAAGmB,aAAaL,CAAS,CAC7B,CACJ,CACJ,CAEC,GAAEM,MAAM"}
@@ -75,6 +75,9 @@ The containers: tabs, accordions and popups, and the panes inside them.
75
75
  | `container.add_popup` | Popup | Toolbar button that adds a popup |
76
76
  | `container.popup_title` | Title | Title of a new popup, in its modal header |
77
77
  | `container.popup_trigger` | Open | Label of the button a popup makes to open itself |
78
+ | `container.add_card` | Card | Toolbar button that adds a card |
79
+ | `container.card_title` | Card title | Title of a new card, in its header |
80
+ | `container.card_footer` | Card footer | Text of a new card's footer, when it has one |
78
81
 
79
82
 
80
83
  confirm.*
package/docs/plugins.md CHANGED
@@ -1,14 +1,16 @@
1
1
  Writing a plugin
2
2
  ================
3
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.
4
+ Tabs, accordions, popups, cards and the element level controls are not built
5
+ into grid-editor: each is a file you load beside it, and loading the file is
6
+ what turns the feature on. `grideditor.card.js` is the shortest of them, and
7
+ the one to read first if you are about to write your own.
7
8
 
8
9
  ```html
9
10
  <script src="dist/jquery.grideditor.min.js"></script>
10
11
  <script src="dist/plugins/grideditor.tabs.min.js"></script>
11
12
  <script src="dist/plugins/grideditor.popup.min.js"></script>
13
+ <script src="dist/plugins/grideditor.card.min.js"></script>
12
14
  <script src="dist/plugins/grideditor.elements.min.js"></script>
13
15
  ```
14
16
 
@@ -21,6 +21,7 @@
21
21
  <script src="../dist/plugins/grideditor.tabs.min.js"></script>
22
22
  <script src="../dist/plugins/grideditor.accordion.min.js"></script>
23
23
  <script src="../dist/plugins/grideditor.popup.min.js"></script>
24
+ <script src="../dist/plugins/grideditor.card.min.js"></script>
24
25
 
25
26
  <script>
26
27
  $(function() {
@@ -76,11 +77,12 @@
76
77
  <div class="col-lg-8">
77
78
  <h1 class="h4">Containers</h1>
78
79
  <p class="form-text">
79
- A container holds panes, and every pane is an ordinary
80
- region: rows, columns, content areas and elements nest
81
- inside one exactly as they do at the top level. The three
82
- buttons in the toolbar add a tabs container, an accordion
83
- and a popup.
80
+ A container holds regions, and every region is an ordinary
81
+ one: rows, columns, content areas and elements nest inside
82
+ it exactly as they do at the top level. The four buttons in
83
+ the toolbar add a tabs container, an accordion, a popup and
84
+ a card &mdash; the first three hold a pane each, a card
85
+ holds one region and an editable header.
84
86
  </p>
85
87
  <p class="form-text">
86
88
  While editing, a popup is unfolded in place and an
@@ -89,7 +91,8 @@
89
91
  authored page opens with. Bootstrap's own JS is never
90
92
  asked to do any of it, so there is no backdrop and no focus
91
93
  trap to fight with. Double click a tab or item label to
92
- rename it. The last row shows two levels: tabs inside an
94
+ rename it, and a card&rsquo;s header and footer the same
95
+ way. The last row shows two levels: tabs inside an
93
96
  accordion item.
94
97
  </p>
95
98
  <button class="btn btn-sm btn-secondary" id="output" type="button">Show the html this produces</button>
@@ -155,6 +158,27 @@
155
158
  </div>
156
159
  </div>
157
160
 
161
+ <div class="row">
162
+ <div class="col-lg-12">
163
+ <div data-ge-container="card">
164
+ <div class="card">
165
+ <div class="card-header">A card, whose body is one region</div>
166
+ <div class="card-body">
167
+ <div class="row">
168
+ <div class="col-lg-6">
169
+ <div class="ge-content" data-ge-content-type="tinymce"><p>A card holds no panes, so it is the plainest container there is: a header, this region, and a footer if you want one.</p></div>
170
+ </div>
171
+ <div class="col-lg-6">
172
+ <div class="ge-content" data-ge-content-type="tinymce"><p>The region is ordinary, so it takes rows and columns of its own &mdash; these two, for instance.</p></div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ <div class="card-footer text-body-secondary">Double click the header or this footer to rewrite it</div>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+
158
182
  <div class="row">
159
183
  <div class="col-lg-12">
160
184
  <div data-ge-container="accordion">
@@ -45,7 +45,7 @@
45
45
  <strong>Containers</strong>
46
46
  <code class="text-body-secondary">containers.html</code>
47
47
  </div>
48
- <span class="text-body-secondary">Tabs, accordions and popups, two levels deep, and the export opened as a real page</span>
48
+ <span class="text-body-secondary">Tabs, accordions, popups and cards, two levels deep, and the export opened as a real page</span>
49
49
  </a>
50
50
 
51
51
  <a class="list-group-item list-group-item-action" href="elements.html">
@@ -21,47 +21,46 @@
21
21
  <script src="../dist/plugins/grideditor.tabs.min.js"></script>
22
22
  <script src="../dist/plugins/grideditor.accordion.min.js"></script>
23
23
  <script src="../dist/plugins/grideditor.popup.min.js"></script>
24
+ <script src="../dist/plugins/grideditor.card.min.js"></script>
24
25
  <script src="../dist/plugins/grideditor.elements.min.js"></script>
25
26
 
26
27
  <!-- And one written here, to show what a plugin of your own takes. It is
27
- a container type: a bootstrap card whose body is an editable region. -->
28
- <script id="card-plugin">
28
+ a container type: a bootstrap alert whose body is an editable region. -->
29
+ <script id="callout-plugin">
29
30
  (function($) {
30
31
 
31
32
  // A plugin brings its own strings
32
33
  $.extend($.fn.gridEditor.locales.en, {
33
- 'container.add_card': 'Card',
34
- 'container.card_title': 'Card title',
34
+ 'container.add_callout': 'Callout',
35
+ 'container.callout_title': 'Heads up',
35
36
  });
36
37
 
37
38
  // Registered under the type it builds, and called once per editor
38
39
  // with the handle it works through
39
- $.fn.gridEditor.containers.card = function(ge) {
40
+ $.fn.gridEditor.containers.callout = function(ge) {
40
41
 
41
42
  return {
42
43
  // The toolbar button's label
43
- labelKey: 'container.add_card',
44
+ labelKey: 'container.add_callout',
44
45
 
45
46
  // A detached container. data-ge-container is what the
46
47
  // editor recognises: never a class, so restyling is free.
47
48
  create: function(options) {
48
- var container = $('<div />').attr('data-ge-container', 'card');
49
-
50
- $('<div class="card" />')
51
- .append($('<div class="card-header" />')
52
- .text(options.title || ge.t('container.card_title')))
53
- .append($('<div class="card-body" />').append(ge.defaultRegion()))
54
- .appendTo(container)
49
+ var callout = $('<div class="alert alert-primary" role="alert" />')
50
+ .append($('<h4 class="alert-heading" />')
51
+ .append($('<span class="ge-pane-label" />')
52
+ .text(options.title || ge.t('container.callout_title'))))
53
+ .append(ge.defaultRegion())
55
54
  ;
56
55
 
57
- return container;
56
+ return $('<div />').attr('data-ge-container', 'callout').append(callout);
58
57
  },
59
58
 
60
59
  // Editing furniture on, and off again. Anything mark()
61
60
  // adds, unmark() has to take away: what is left is what
62
61
  // getHtml hands back.
63
62
  mark: function(container) {
64
- ge.makeLabelEditable(ge.labelIn(container.find('.card-header')));
63
+ ge.makeLabelEditable(ge.labelIn(container.find('.alert-heading')));
65
64
  },
66
65
 
67
66
  unmark: function(container) {
@@ -76,7 +75,7 @@
76
75
  <script>
77
76
  $(function() {
78
77
  // Show the plugin written above as the page's own source
79
- $('#card-source').text($('#card-plugin').text().trim().replace(/^ {8}/gm, ''));
78
+ $('#callout-source').text($('#callout-plugin').text().trim().replace(/^ {8}/gm, ''));
80
79
 
81
80
  function activePlugins() {
82
81
  return $('.plugin-choice:checked').map(function() { return this.value; }).get();
@@ -119,11 +118,11 @@
119
118
  <div class="col-lg-8">
120
119
  <h1 class="h4">Plugins</h1>
121
120
  <p class="form-text">
122
- Tabs, accordions, popups and the element level controls are
123
- not in the main bundle: each is a file loaded beside the
124
- editor, and loading it is what turns the feature on. This
125
- page loads all four, plus a fifth written in its own
126
- <code>&lt;script&gt;</code> below.
121
+ Tabs, accordions, popups, cards and the element level
122
+ controls are not in the main bundle: each is a file loaded
123
+ beside the editor, and loading it is what turns the feature
124
+ on. This page loads all five, plus a sixth written in its
125
+ own <code>&lt;script&gt;</code> below.
127
126
  </p>
128
127
  <p class="form-text">
129
128
  Tick and untick to change the <code>plugins</code> setting
@@ -152,7 +151,11 @@
152
151
  </div>
153
152
  <div class="form-check form-check-inline">
154
153
  <input class="form-check-input plugin-choice" type="checkbox" value="card" id="p-card" checked>
155
- <label class="form-check-label" for="p-card">card (written on this page)</label>
154
+ <label class="form-check-label" for="p-card">card</label>
155
+ </div>
156
+ <div class="form-check form-check-inline">
157
+ <input class="form-check-input plugin-choice" type="checkbox" value="callout" id="p-callout" checked>
158
+ <label class="form-check-label" for="p-callout">callout (written on this page)</label>
156
159
  </div>
157
160
  </div>
158
161
 
@@ -185,7 +188,7 @@
185
188
  <div class="col-lg-12">
186
189
  <div data-ge-container="card">
187
190
  <div class="card">
188
- <div class="card-header">A card, from the plugin written on this page</div>
191
+ <div class="card-header">A card, from the card plugin</div>
189
192
  <div class="card-body">
190
193
  <div class="row"><div class="col-lg-12">
191
194
  <div class="ge-content"><p>Its body is an ordinary region: rows, columns and elements nest in it.</p></div>
@@ -200,14 +203,15 @@
200
203
 
201
204
  <div class="row my-4">
202
205
  <div class="col-lg-10">
203
- <h2 class="h5">The card plugin, in full</h2>
206
+ <h2 class="h5">The callout plugin, in full</h2>
204
207
  <p class="form-text">
205
208
  Thirty lines, and it moves, deletes, nests, takes an id and
206
209
  classes, and round-trips through <code>getHtml</code> like
207
- anything else. See <a href="../docs/plugins.md">docs/plugins.md</a>
210
+ anything else &mdash; the shipped <code>card</code> plugin is
211
+ barely longer. See <a href="../docs/plugins.md">docs/plugins.md</a>
208
212
  for the whole contract.
209
213
  </p>
210
- <pre class="border rounded p-3 bg-light"><code id="card-source"></code></pre>
214
+ <pre class="border rounded p-3 bg-light"><code id="callout-source"></code></pre>
211
215
  </div>
212
216
  </div>
213
217
 
package/package.json CHANGED
@@ -33,7 +33,7 @@
33
33
  "comment": "A scoped package publishes restricted unless it is told otherwise.",
34
34
  "access": "public"
35
35
  },
36
- "version": "3.1.0",
36
+ "version": "3.2.1",
37
37
  "main": "dist/jquery.grideditor.js",
38
38
  "files": [
39
39
  "dist",
@@ -50,6 +50,9 @@
50
50
  'container.add_popup': 'Ventana emergente',
51
51
  'container.popup_title': 'Título',
52
52
  'container.popup_trigger': 'Abrir',
53
+ 'container.add_card': 'Tarjeta',
54
+ 'container.card_title': 'Título de la tarjeta',
55
+ 'container.card_footer': 'Pie de la tarjeta',
53
56
  'confirm.title': 'Confirmar',
54
57
  'confirm.ok': 'Borrar',
55
58
  'confirm.cancel': 'Cancelar',
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Cards for grid-editor.
3
+ *
4
+ * A container plugin: load this file after the editor and the toolbar offers
5
+ * a card, a bootstrap card whose body is an editable region. What it can ask
6
+ * the editor for is the handle its factory is called with, described in
7
+ * docs/plugins.md.
8
+ *
9
+ * <script src="dist/jquery.grideditor.min.js"></script>
10
+ * <script src="dist/plugins/grideditor.card.min.js"></script>
11
+ */
12
+ (function($) {
13
+
14
+ $.extend($.fn.gridEditor.locales.en, {
15
+ 'container.add_card': 'Card',
16
+ 'container.card_title': 'Card title',
17
+ 'container.card_footer': 'Card footer',
18
+ });
19
+
20
+ $.fn.gridEditor.containers.card = function(ge) {
21
+
22
+ return {
23
+ labelKey: 'container.add_card',
24
+
25
+ /**
26
+ * A card is a header, a body and an optional footer. `header: false`
27
+ * leaves the title out, `footer: true` or a string adds one; both are
28
+ * plain text the editor makes editable, not regions, so a card holds
29
+ * exactly one region and nests like any other container.
30
+ */
31
+ create: function(options) {
32
+ var card = $('<div class="card" />');
33
+
34
+ if (options.header !== false) {
35
+ $('<div class="card-header" />')
36
+ .append($('<span class="ge-pane-label" />')
37
+ .text(options.title || ge.t('container.card_title')))
38
+ .appendTo(card)
39
+ ;
40
+ }
41
+
42
+ $('<div class="card-body" />').append(ge.defaultRegion()).appendTo(card);
43
+
44
+ if (options.footer) {
45
+ $('<div class="card-footer text-body-secondary" />')
46
+ .append($('<span class="ge-pane-label" />')
47
+ .text(typeof options.footer === 'string'
48
+ ? options.footer
49
+ : ge.t('container.card_footer')))
50
+ .appendTo(card)
51
+ ;
52
+ }
53
+
54
+ return $('<div />').attr('data-ge-container', 'card').append(card);
55
+ },
56
+
57
+ mark: function(container) {
58
+ ge.makeLabelEditable(ge.labelIn(container.find('> .card > .card-header')));
59
+ ge.makeLabelEditable(ge.labelIn(container.find('> .card > .card-footer')));
60
+ },
61
+
62
+ unmark: function(container) {
63
+ ge.unwrapLabels(container);
64
+ },
65
+ };
66
+ };
67
+
68
+ })(jQuery);