@themarioga/grid-editor 4.1.0 → 5.0.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.
- package/CHANGELOG.md +53 -0
- package/README.md +68 -8
- package/UPGRADING.md +55 -0
- package/dist/grideditor.css +461 -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 +634 -109
- package/dist/jquery.grideditor.min.js +1 -1
- package/dist/jquery.grideditor.min.js.map +1 -1
- package/dist/locales/grideditor.es.js +26 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +1 -1
- package/dist/plugins/grideditor.float.js +56 -0
- package/dist/plugins/grideditor.float.min.js +2 -0
- package/dist/plugins/grideditor.float.min.js.map +1 -0
- package/dist/plugins/grideditor.sections.js +199 -0
- package/dist/plugins/grideditor.sections.min.js +2 -0
- package/dist/plugins/grideditor.sections.min.js.map +1 -0
- package/dist/plugins/grideditor.textalign.js +60 -0
- package/dist/plugins/grideditor.textalign.min.js +2 -0
- package/dist/plugins/grideditor.textalign.min.js.map +1 -0
- package/docs/events.md +13 -2
- package/docs/locale-keys.md +36 -1
- package/docs/plugins.md +35 -2
- package/example/autocols.html +137 -0
- package/example/breakpoints.html +7 -5
- package/example/index.html +16 -2
- package/example/utilities.html +22 -1
- package/package.json +1 -1
- package/src/js/jquery.grideditor.js +635 -110
- package/src/js/locales/grideditor.es.js +26 -0
- package/src/js/plugins/grideditor.float.js +56 -0
- package/src/js/plugins/grideditor.sections.js +199 -0
- package/src/js/plugins/grideditor.textalign.js +60 -0
- package/src/less/grideditor.less +132 -0
|
@@ -28,6 +28,7 @@ var METHODS = {
|
|
|
28
28
|
createRow: { value: true },
|
|
29
29
|
createColumn: { value: true },
|
|
30
30
|
createElement: { value: true },
|
|
31
|
+
createSection: { value: true },
|
|
31
32
|
createContainer: { value: true },
|
|
32
33
|
addTab: { value: true },
|
|
33
34
|
addAccordionItem: { value: true },
|
|
@@ -62,8 +63,8 @@ var BREAKPOINTS = [
|
|
|
62
63
|
|
|
63
64
|
/**
|
|
64
65
|
* The view that edits every tier at once. It is the default, and the one most
|
|
65
|
-
* pages want: a layout that needs no per-device tuning is written once
|
|
66
|
-
*
|
|
66
|
+
* pages want: a layout that needs no per-device tuning is written once, as the
|
|
67
|
+
* class with no breakpoint, and applies at every size.
|
|
67
68
|
*/
|
|
68
69
|
var ALL_VIEW = 'all';
|
|
69
70
|
var ALL_VIEW_LABEL_KEY = 'view.all';
|
|
@@ -77,6 +78,31 @@ var LEGACY_VIEW_INDEXES = ['lg', 'sm', 'xs'];
|
|
|
77
78
|
var MAX_COL_SIZE = 12;
|
|
78
79
|
var MAX_COL_OFFSET = 11;
|
|
79
80
|
|
|
81
|
+
/**
|
|
82
|
+
* The two sizes that are not a number of units: `equal` is Bootstrap's col,
|
|
83
|
+
* which shares what the row has left with the other equal columns, and
|
|
84
|
+
* `auto` is col-auto, as wide as its content.
|
|
85
|
+
*/
|
|
86
|
+
var FLEX_SIZES = ['equal', 'auto'];
|
|
87
|
+
|
|
88
|
+
/** How many columns a row-cols class puts on a line. */
|
|
89
|
+
var ROW_COLS_VALUES = ['1', '2', '3', '4', '5', '6', 'auto'];
|
|
90
|
+
|
|
91
|
+
function rowColsClass(tier, value) {
|
|
92
|
+
return 'row-cols' + (tier.infix ? '-' + tier.infix : '') + '-' + value;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isUnits(size) {
|
|
96
|
+
return typeof size === 'number';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The class that gives a column `size` at one tier: col-md-4, col-md, col-md-auto. */
|
|
100
|
+
function sizeClass(tier, size) {
|
|
101
|
+
if (size === 'equal') { return tier.infix ? 'col-' + tier.infix : 'col'; }
|
|
102
|
+
|
|
103
|
+
return tier.colPrefix + size;
|
|
104
|
+
}
|
|
105
|
+
|
|
80
106
|
function breakpoint(key) {
|
|
81
107
|
for (var i = 0; i < BREAKPOINTS.length; i++) {
|
|
82
108
|
if (BREAKPOINTS[i].key === key) { return BREAKPOINTS[i]; }
|
|
@@ -84,9 +110,12 @@ function breakpoint(key) {
|
|
|
84
110
|
return null;
|
|
85
111
|
}
|
|
86
112
|
|
|
87
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* The tier a view writes to. The all view writes the base class, the one
|
|
115
|
+
* with no breakpoint, and takes the others off.
|
|
116
|
+
*/
|
|
88
117
|
function tiersFor(view) {
|
|
89
|
-
if (view === ALL_VIEW) { return BREAKPOINTS
|
|
118
|
+
if (view === ALL_VIEW) { return [BREAKPOINTS[0]]; }
|
|
90
119
|
|
|
91
120
|
var tier = breakpoint(view);
|
|
92
121
|
return tier ? [tier] : [];
|
|
@@ -264,11 +293,12 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
264
293
|
'tab_tools' : [], // Host tools on tab drawers
|
|
265
294
|
'accordion_tools' : [], // Host tools on accordion item drawers
|
|
266
295
|
'plugins' : null, // Plugins to use, of any kind; null means every one loaded
|
|
296
|
+
'row_cols' : true, // A row's "columns per row" field, row-cols-*
|
|
267
297
|
'utilities' : {}, // Options for the utility plugins, by plugin name
|
|
268
298
|
'elements' : NESTED_SETTINGS.elements, // Element level controls, below the column
|
|
269
299
|
'custom_filter' : '',
|
|
270
300
|
'content_types' : ['tinymce'],
|
|
271
|
-
'valid_col_sizes' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
|
301
|
+
'valid_col_sizes' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 'equal', 'auto'],
|
|
272
302
|
'valid_col_offsets' : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
273
303
|
'add_column' : NESTED_SETTINGS.add_column, // The add column tool
|
|
274
304
|
'layout_modes' : VIEW_KEYS.slice(), // Which views the dropdown offers
|
|
@@ -580,54 +610,91 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
580
610
|
}
|
|
581
611
|
|
|
582
612
|
/**
|
|
583
|
-
*
|
|
584
|
-
*
|
|
613
|
+
* What resizing this column to `size` in `view` would write, or null
|
|
614
|
+
* when the budget refuses it or there is nothing to change.
|
|
585
615
|
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* What resizing this column to `size` would write, or null when the
|
|
591
|
-
* budget refuses it or there is nothing to change.
|
|
616
|
+
* A breakpoint view writes its own tier. The all view writes the base
|
|
617
|
+
* class and takes the size off every other tier, so one size is what
|
|
618
|
+
* applies everywhere; the plan says what it took off.
|
|
592
619
|
*
|
|
593
620
|
* Refused rather than quietly clamped: the offset is something the
|
|
594
|
-
* user set, and a tool that rewrites it is a tool that lies.
|
|
595
|
-
*
|
|
621
|
+
* user set, and a tool that rewrites it is a tool that lies. In the
|
|
622
|
+
* all view the base size has to fit every tier's offset, since it is
|
|
623
|
+
* the size at every tier once the others are gone.
|
|
596
624
|
*/
|
|
597
|
-
function planSize(col, size) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
625
|
+
function planSize(col, size, view) {
|
|
626
|
+
view = view || curView;
|
|
627
|
+
|
|
628
|
+
if (view !== ALL_VIEW) {
|
|
629
|
+
var tier = breakpoint(view);
|
|
630
|
+
var wanted = clamp({ size: size, offset: getEffectiveOffset(col, tier) || 0 });
|
|
631
|
+
|
|
632
|
+
if (wanted.refused || getSize(col, tier) === wanted.size) { return null; }
|
|
633
|
+
|
|
634
|
+
return { writes: [{ tier: tier, size: wanted.size }], cleared: null, size: wanted.size };
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
var refused = BREAKPOINTS.some(function(each) {
|
|
638
|
+
return clamp({ size: size, offset: getEffectiveOffset(col, each) || 0 }).refused;
|
|
601
639
|
});
|
|
640
|
+
if (refused) { return null; }
|
|
641
|
+
|
|
642
|
+
var base = BREAKPOINTS[0];
|
|
643
|
+
var writes = [];
|
|
644
|
+
var cleared = [];
|
|
602
645
|
|
|
603
|
-
|
|
646
|
+
BREAKPOINTS.slice(1).forEach(function(each) {
|
|
647
|
+
var own = getSize(col, each);
|
|
648
|
+
if (own === null) { return; }
|
|
604
649
|
|
|
605
|
-
|
|
606
|
-
|
|
650
|
+
writes.push({ tier: each, size: null });
|
|
651
|
+
cleared.push({ breakpoint: each.key, value: own });
|
|
607
652
|
});
|
|
608
|
-
if (unchanged) { return null; }
|
|
609
653
|
|
|
610
|
-
|
|
654
|
+
if (getSize(col, base) !== size) { writes.unshift({ tier: base, size: size }); }
|
|
655
|
+
|
|
656
|
+
return writes.length ? { writes: writes, cleared: cleared, size: size } : null;
|
|
611
657
|
}
|
|
612
658
|
|
|
613
659
|
function writeSize(col, plan) {
|
|
614
|
-
plan.
|
|
660
|
+
plan.writes.forEach(function(write) { setSize(col, write.tier, write.size); });
|
|
615
661
|
stripPixelWidths(col);
|
|
616
662
|
}
|
|
617
663
|
|
|
618
|
-
/**
|
|
619
|
-
function
|
|
664
|
+
/** The all view's payloads say what the write took off the breakpoints. */
|
|
665
|
+
function withCleared(extra, cleared) {
|
|
666
|
+
if (cleared) { extra.cleared = cleared; }
|
|
667
|
+
return extra;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Resize a column, announcing it either side. `size` is units,
|
|
672
|
+
* `equal` or `auto`; `view` is the current one unless the size field
|
|
673
|
+
* of a plugin's panel says otherwise.
|
|
674
|
+
*/
|
|
675
|
+
function resizeColumn(col, size, source, view) {
|
|
676
|
+
view = view || curView;
|
|
677
|
+
|
|
620
678
|
var from = currentSize(col);
|
|
621
|
-
var plan = planSize(col, size);
|
|
679
|
+
var plan = planSize(col, size, view);
|
|
622
680
|
|
|
623
681
|
if (!plan) { return false; }
|
|
624
682
|
|
|
625
683
|
return operate(function() {
|
|
626
|
-
var payload = payloadFor('column', col, {
|
|
684
|
+
var payload = payloadFor('column', col, withCleared({
|
|
685
|
+
source: source,
|
|
686
|
+
breakpoint: view,
|
|
687
|
+
from: from,
|
|
688
|
+
to: plan.size,
|
|
689
|
+
}, plan.cleared));
|
|
627
690
|
|
|
628
|
-
if (!emit('before-resize', payload)) {
|
|
691
|
+
if (!emit('before-resize', payload)) {
|
|
692
|
+
refreshUtilities(col);
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
629
695
|
|
|
630
696
|
writeSize(col, plan);
|
|
697
|
+
refreshUtilities(col);
|
|
631
698
|
emit('after-resize', payload);
|
|
632
699
|
|
|
633
700
|
return true;
|
|
@@ -637,41 +704,49 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
637
704
|
/**
|
|
638
705
|
* Indent a column, shrinking it when the budget needs it: the offset
|
|
639
706
|
* is what the user asked for, so it is the one that gets its way.
|
|
707
|
+
*
|
|
708
|
+
* Like a size, an offset is written to the tier being edited, or in
|
|
709
|
+
* the all view as the base class with every other tier's taken off.
|
|
640
710
|
*/
|
|
641
711
|
function indentColumn(col, offset, source) {
|
|
642
|
-
var
|
|
712
|
+
var everywhere = curView === ALL_VIEW;
|
|
713
|
+
var tier = everywhere ? BREAKPOINTS[0] : breakpoint(curView);
|
|
643
714
|
var from = currentOffset(col);
|
|
644
715
|
|
|
645
716
|
offset = Math.min(Math.max(offset, 0), MAX_COL_OFFSET);
|
|
646
717
|
|
|
647
|
-
var
|
|
648
|
-
return
|
|
649
|
-
});
|
|
650
|
-
|
|
718
|
+
var others = everywhere ? BREAKPOINTS.slice(1).filter(function(each) {
|
|
719
|
+
return getOffset(col, each) !== null;
|
|
720
|
+
}) : [];
|
|
721
|
+
|
|
722
|
+
if ((getOffset(col, tier) || 0) === offset && !others.length) { return false; }
|
|
651
723
|
|
|
652
724
|
return operate(function() {
|
|
653
|
-
var payload = payloadFor('column', col, {
|
|
725
|
+
var payload = payloadFor('column', col, withCleared({
|
|
654
726
|
source: source,
|
|
655
727
|
from: from,
|
|
656
728
|
to: offset,
|
|
657
|
-
})
|
|
729
|
+
}, everywhere ? others.map(function(each) {
|
|
730
|
+
return { breakpoint: each.key, value: getOffset(col, each) };
|
|
731
|
+
}) : null));
|
|
658
732
|
|
|
659
733
|
if (!emit('before-indent', payload)) { return false; }
|
|
660
734
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
var wanted = clamp({ size: was, offset: offset, leading: 'offset' });
|
|
735
|
+
setOffset(col, tier, offset);
|
|
736
|
+
others.forEach(function(each) { setOffset(col, each, 0); });
|
|
664
737
|
|
|
665
|
-
|
|
738
|
+
// Wherever the column's size and the new offset no longer fit
|
|
739
|
+
// - one tier, or every tier in the all view - the size gives
|
|
740
|
+
// way, at that tier only. An equal or auto column fits anywhere.
|
|
741
|
+
(everywhere ? BREAKPOINTS : [tier]).forEach(function(each) {
|
|
742
|
+
var was = getEffectiveSize(col, each);
|
|
743
|
+
if (!isUnits(was)) { return; }
|
|
666
744
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
// tiers nobody asked it to touch
|
|
670
|
-
if (wanted.size !== null && wanted.size !== was) {
|
|
671
|
-
setSize(col, tier, wanted.size);
|
|
672
|
-
}
|
|
745
|
+
var wanted = clamp({ size: was, offset: offset, leading: 'offset' });
|
|
746
|
+
if (wanted.size !== was) { setSize(col, each, wanted.size); }
|
|
673
747
|
});
|
|
674
748
|
|
|
749
|
+
refreshUtilities(col);
|
|
675
750
|
emit('after-indent', payload);
|
|
676
751
|
|
|
677
752
|
return true;
|
|
@@ -770,17 +845,17 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
770
845
|
addRowGroup = $('<div class="ge-addRowGroup btn-group" />').appendTo(wrapper);
|
|
771
846
|
addContainerGroup = $('<div class="ge-addContainerGroup btn-group" />');
|
|
772
847
|
$.each(settings.new_row_layouts, function(j, layout) {
|
|
848
|
+
var grouped = !Array.isArray(layout);
|
|
773
849
|
var btn = $('<a class="btn btn-sm btn-primary" />')
|
|
774
|
-
.attr('title',
|
|
850
|
+
.attr('title', grouped
|
|
851
|
+
? t('row.add_row_cols', { columns: layout.columns, counts: rowColsText(layout.row_cols) })
|
|
852
|
+
: t('row.add', { layout: layout.join('-') }))
|
|
775
853
|
// What this button makes, in the markup rather than in
|
|
776
854
|
// jQuery data: a drag works on a clone of it
|
|
777
855
|
.attr('data-ge-toolbar', 'row')
|
|
778
|
-
.attr('data-ge-layout', layout.join(','))
|
|
856
|
+
.attr('data-ge-layout', grouped ? JSON.stringify(layout) : layout.join(','))
|
|
779
857
|
.on('click', function() {
|
|
780
|
-
var row =
|
|
781
|
-
layout.forEach(function(i) {
|
|
782
|
-
createColumn(i).appendTo(row);
|
|
783
|
-
});
|
|
858
|
+
var row = rowFromLayoutValue(layout);
|
|
784
859
|
|
|
785
860
|
var added = addNode('row', row, function() {
|
|
786
861
|
row.appendTo(canvas);
|
|
@@ -795,10 +870,14 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
795
870
|
|
|
796
871
|
btn.append('<i class="bi bi-plus"></i>');
|
|
797
872
|
|
|
798
|
-
|
|
873
|
+
// A row of columns shares out the icon as they share the row;
|
|
874
|
+
// a row with row-cols draws one line of its widest count
|
|
875
|
+
var sizes = grouped ? rowColsIcon(layout) : layout;
|
|
799
876
|
var icon = '<div class="row ge-row-icon">';
|
|
800
|
-
|
|
801
|
-
|
|
877
|
+
sizes.forEach(function(size) {
|
|
878
|
+
// Closed explicitly: jQuery 4 no longer expands <div/>, and
|
|
879
|
+
// each column would be parsed inside the one before
|
|
880
|
+
icon += '<div class="column ' + sizeClass(BREAKPOINTS[0], size) + '"></div>';
|
|
802
881
|
});
|
|
803
882
|
icon += '</div>';
|
|
804
883
|
btn.append(icon);
|
|
@@ -830,6 +909,29 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
830
909
|
;
|
|
831
910
|
});
|
|
832
911
|
|
|
912
|
+
// A feature plugin's own buttons, beside the containers': what
|
|
913
|
+
// one makes goes onto the canvas, where the plugin says it belongs
|
|
914
|
+
$.each(FEATURES, function(name, feature) {
|
|
915
|
+
(feature.toolbar || []).forEach(function(item, index) {
|
|
916
|
+
$('<a class="btn btn-sm btn-primary ge-add-container ge-add-feature" />')
|
|
917
|
+
.attr('title', t(item.labelKey))
|
|
918
|
+
.attr('data-ge-toolbar', 'feature')
|
|
919
|
+
.attr('data-ge-feature', name)
|
|
920
|
+
.attr('data-ge-item', index)
|
|
921
|
+
.append('<i class="bi bi-plus"></i>')
|
|
922
|
+
.append($('<span />').text(t(item.labelKey)))
|
|
923
|
+
.on('click', function() {
|
|
924
|
+
var made = item.create();
|
|
925
|
+
|
|
926
|
+
addNode(item.kind, made, function() {
|
|
927
|
+
made.appendTo(canvas);
|
|
928
|
+
}, { parent: canvas, source: 'tool' });
|
|
929
|
+
})
|
|
930
|
+
.appendTo(addContainerGroup)
|
|
931
|
+
;
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
|
|
833
935
|
// Buttons on right
|
|
834
936
|
layoutDropdown = $('<div class="dropdown pull-right ge-layout-mode">' +
|
|
835
937
|
'<button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown"></button>' +
|
|
@@ -1005,14 +1107,14 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1005
1107
|
|
|
1006
1108
|
if (!under) { return null; }
|
|
1007
1109
|
|
|
1008
|
-
var region = $(under).closest('.column, .ge-canvas');
|
|
1110
|
+
var region = $(under).closest(['.column', '.ge-canvas'].concat(pluginHooks('regions')).join(', '));
|
|
1009
1111
|
if (!region.length || (region[0] !== canvas[0] && !canvas[0].contains(region[0]))) {
|
|
1010
1112
|
return null;
|
|
1011
1113
|
}
|
|
1012
1114
|
|
|
1013
1115
|
var before = null;
|
|
1014
1116
|
|
|
1015
|
-
region.children(
|
|
1117
|
+
region.children(blockSelector()).each(function() {
|
|
1016
1118
|
if (before) { return; }
|
|
1017
1119
|
|
|
1018
1120
|
var box = this.getBoundingClientRect();
|
|
@@ -1022,6 +1124,30 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1022
1124
|
return { region: region, before: before };
|
|
1023
1125
|
}
|
|
1024
1126
|
|
|
1127
|
+
/**
|
|
1128
|
+
* A feature's toolbar button dropped on the canvas. A region that will
|
|
1129
|
+
* not have what it makes - a section dropped on a column - gives way
|
|
1130
|
+
* to the canvas, just after the top level block the pointer was in.
|
|
1131
|
+
*/
|
|
1132
|
+
function insertFeatureFromToolbar(button, where) {
|
|
1133
|
+
var item = FEATURES[button.attr('data-ge-feature')].toolbar[parseInt(button.attr('data-ge-item'), 10)];
|
|
1134
|
+
var made = item.create();
|
|
1135
|
+
|
|
1136
|
+
if (!acceptsBlock(where.region, made)) {
|
|
1137
|
+
var top = where.region.parentsUntil(canvas).addBack().first();
|
|
1138
|
+
where = { region: canvas, before: top.length ? top.next() : null };
|
|
1139
|
+
if (where.before && !where.before.length) { where.before = null; }
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
return addNode(item.kind, made, function() {
|
|
1143
|
+
if (where.before) {
|
|
1144
|
+
made.insertBefore(where.before);
|
|
1145
|
+
} else {
|
|
1146
|
+
made.appendTo(where.region);
|
|
1147
|
+
}
|
|
1148
|
+
}, { parent: where.region, source: 'dragdrop' });
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1025
1151
|
/** A line where the block would go, following the pointer. */
|
|
1026
1152
|
function showDropMarker(pageX, pageY) {
|
|
1027
1153
|
var where = dropPlaceAt(pageX, pageY);
|
|
@@ -1048,6 +1174,10 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1048
1174
|
* the pointer left it.
|
|
1049
1175
|
*/
|
|
1050
1176
|
function insertFromToolbar(button, where) {
|
|
1177
|
+
if (button.attr('data-ge-toolbar') === 'feature') {
|
|
1178
|
+
return insertFeatureFromToolbar(button, where);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1051
1181
|
var container = button.attr('data-ge-toolbar') === 'container';
|
|
1052
1182
|
var type = button.attr('data-ge-container-type');
|
|
1053
1183
|
var made = container
|
|
@@ -1072,16 +1202,94 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1072
1202
|
}, { parent: where.region, source: 'dragdrop' });
|
|
1073
1203
|
}
|
|
1074
1204
|
|
|
1205
|
+
/**
|
|
1206
|
+
* The column width as a utility family, so the Responsive section of
|
|
1207
|
+
* a column's panel has a field for it: every size, units or not, in
|
|
1208
|
+
* the view being edited. A write is a resize, through the resize
|
|
1209
|
+
* events, not a utility change.
|
|
1210
|
+
*/
|
|
1211
|
+
function widthFamily() {
|
|
1212
|
+
var values = [];
|
|
1213
|
+
for (var units = 1; units <= MAX_COL_SIZE; units++) { values.push(String(units)); }
|
|
1214
|
+
|
|
1215
|
+
return {
|
|
1216
|
+
name: 'col',
|
|
1217
|
+
values: values.concat(FLEX_SIZES),
|
|
1218
|
+
appliesTo: ['column'],
|
|
1219
|
+
labelKey: 'utility.col_width',
|
|
1220
|
+
className: function(key, value) { return sizeClass(breakpoint(key), parseSize(value)); },
|
|
1221
|
+
choices: function() { return settings.valid_col_sizes.map(String); },
|
|
1222
|
+
label: function(value) {
|
|
1223
|
+
if (value === 'equal') { return t('utility.col_equal'); }
|
|
1224
|
+
if (value === 'auto') { return t('utility.col_auto'); }
|
|
1225
|
+
|
|
1226
|
+
return value;
|
|
1227
|
+
},
|
|
1228
|
+
write: function(col, value, view, source) {
|
|
1229
|
+
return resizeColumn(col, value === null ? null : parseSize(value), source, view);
|
|
1230
|
+
},
|
|
1231
|
+
// With no size of its own, a column in a row with row-cols
|
|
1232
|
+
// takes its share from the row, which the field says
|
|
1233
|
+
blank: function(col, view) {
|
|
1234
|
+
var winner = view === ALL_VIEW ? null : rowColsWinner(col, breakpoint(view));
|
|
1235
|
+
return winner ? t('utility.col_from_row', { count: rowColsLabel(winner.value) }) : null;
|
|
1236
|
+
},
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/** A size as markup or a select carries it: '4' is 4, 'equal' and 'auto' are themselves. */
|
|
1241
|
+
function parseSize(size) {
|
|
1242
|
+
return /^\d+$/.test(String(size)) ? parseInt(size, 10) : size;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
/** A row from a toolbar button's data-ge-layout: sizes, or a row-cols layout as JSON. */
|
|
1075
1246
|
function rowFromLayout(layout) {
|
|
1247
|
+
if (/^\s*\{/.test(layout || '')) { return rowFromLayoutValue(JSON.parse(layout)); }
|
|
1248
|
+
|
|
1249
|
+
return rowFromLayoutValue((layout || '').split(',').filter(function(size) {
|
|
1250
|
+
return size !== '';
|
|
1251
|
+
}).map(parseSize));
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* A row from a layout: an array of sizes, or { row_cols, columns } -
|
|
1256
|
+
* row-cols per breakpoint, and that many columns sized by the row.
|
|
1257
|
+
*/
|
|
1258
|
+
function rowFromLayoutValue(layout) {
|
|
1076
1259
|
var row = createRow();
|
|
1077
1260
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1261
|
+
if (Array.isArray(layout)) {
|
|
1262
|
+
layout.forEach(function(size) { createColumn(size).appendTo(row); });
|
|
1263
|
+
return row;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
$.each(layout.row_cols || {}, function(key, value) {
|
|
1267
|
+
var tier = breakpoint(key);
|
|
1268
|
+
if (tier && ROW_COLS_VALUES.indexOf(String(value)) !== -1) { row.addClass(rowColsClass(tier, value)); }
|
|
1080
1269
|
});
|
|
1081
1270
|
|
|
1271
|
+
for (var i = 0; i < (layout.columns || 0); i++) { createColumn(null).appendTo(row); }
|
|
1272
|
+
|
|
1082
1273
|
return row;
|
|
1083
1274
|
}
|
|
1084
1275
|
|
|
1276
|
+
/** "1, md: 3": a row-cols layout's counts, for its button's title. */
|
|
1277
|
+
function rowColsText(counts) {
|
|
1278
|
+
return BREAKPOINTS.filter(function(tier) { return counts && counts[tier.key] !== undefined; })
|
|
1279
|
+
.map(function(tier) { return (tier.infix ? tier.key + ': ' : '') + counts[tier.key]; })
|
|
1280
|
+
.join(', ');
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/** The icon of a row-cols layout: one line of equal columns, as many as its widest count. */
|
|
1284
|
+
function rowColsIcon(layout) {
|
|
1285
|
+
var widest = 1;
|
|
1286
|
+
$.each(layout.row_cols || {}, function(key, value) {
|
|
1287
|
+
if (value !== 'auto') { widest = Math.max(widest, parseInt(value, 10) || 1); }
|
|
1288
|
+
});
|
|
1289
|
+
|
|
1290
|
+
return Array.apply(null, Array(Math.min(widest, layout.columns || widest))).map(function() { return 'equal'; });
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1085
1293
|
function onScroll(e) {
|
|
1086
1294
|
var $window = $(window);
|
|
1087
1295
|
|
|
@@ -1168,6 +1376,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1168
1376
|
// one that rebuilt its area's DOM brought the preview styles back
|
|
1169
1377
|
// with it, and the attribute recording them came back too
|
|
1170
1378
|
clearPreviews(canvas);
|
|
1379
|
+
canvas.find('[data-ge-row-cols]').removeAttr('data-ge-row-cols');
|
|
1171
1380
|
unmarkContainers();
|
|
1172
1381
|
removeSortable();
|
|
1173
1382
|
removeResizable();
|
|
@@ -1236,6 +1445,9 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1236
1445
|
*/
|
|
1237
1446
|
function loadPlugins() {
|
|
1238
1447
|
var api = pluginApi();
|
|
1448
|
+
|
|
1449
|
+
registerFamily('grid', {}, widthFamily());
|
|
1450
|
+
if (settings.row_cols !== false) { registerFamily('grid', {}, rowColsFamily()); }
|
|
1239
1451
|
var wanted = function(name) {
|
|
1240
1452
|
return !settings.plugins || settings.plugins.indexOf(name) !== -1;
|
|
1241
1453
|
};
|
|
@@ -1321,6 +1533,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1321
1533
|
getUtility: getUtility,
|
|
1322
1534
|
setUtility: setUtility,
|
|
1323
1535
|
utilityField: utilityField,
|
|
1536
|
+
bareStyle: bareStyle,
|
|
1537
|
+
rowFromLayout: rowFromLayoutValue,
|
|
1324
1538
|
};
|
|
1325
1539
|
}
|
|
1326
1540
|
|
|
@@ -1392,6 +1606,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1392
1606
|
}
|
|
1393
1607
|
|
|
1394
1608
|
function utilityClass(family, tier, value) {
|
|
1609
|
+
if (family.className) { return family.className(tier.key, value); }
|
|
1610
|
+
|
|
1395
1611
|
return family.prefix + (tier.infix ? '-' + tier.infix : '') + '-' + value;
|
|
1396
1612
|
}
|
|
1397
1613
|
|
|
@@ -1538,6 +1754,10 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1538
1754
|
return false;
|
|
1539
1755
|
}
|
|
1540
1756
|
|
|
1757
|
+
// A family whose writes are some other operation - the column
|
|
1758
|
+
// width, which is a resize - does them its own way
|
|
1759
|
+
if (family.write) { return family.write(node, value, view, options.source || 'api'); }
|
|
1760
|
+
|
|
1541
1761
|
var plan = planUtility(node, family, view, value);
|
|
1542
1762
|
if (!plan) { return false; }
|
|
1543
1763
|
|
|
@@ -1568,6 +1788,29 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1568
1788
|
});
|
|
1569
1789
|
}
|
|
1570
1790
|
|
|
1791
|
+
/**
|
|
1792
|
+
* ge.bareStyle(node, family, property): what a css property comes to
|
|
1793
|
+
* on a node with none of the family's classes, at any breakpoint. The
|
|
1794
|
+
* answer a preview needs for "no class applies here" when that is not
|
|
1795
|
+
* a constant: text-align inherits from the parent, and the host's own
|
|
1796
|
+
* css may float an element. The browser is the only one who knows, so
|
|
1797
|
+
* the classes come off for the moment it takes to ask.
|
|
1798
|
+
*/
|
|
1799
|
+
function bareStyle(node, name, property) {
|
|
1800
|
+
var family = familyNamed(name, 'bareStyle');
|
|
1801
|
+
node = $(node).first();
|
|
1802
|
+
if (!family || !node.length) { return null; }
|
|
1803
|
+
|
|
1804
|
+
var original = node.attr('class');
|
|
1805
|
+
BREAKPOINTS.forEach(function(tier) { writeUtility(node, family, tier, null); });
|
|
1806
|
+
|
|
1807
|
+
var value = getComputedStyle(node[0]).getPropertyValue(property);
|
|
1808
|
+
|
|
1809
|
+
if (original === undefined) { node.removeAttr('class'); } else { node.attr('class', original); }
|
|
1810
|
+
|
|
1811
|
+
return value;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1571
1814
|
/** Bring a node's panel and preview up to date with its classes. */
|
|
1572
1815
|
function refreshUtilities(node) {
|
|
1573
1816
|
var details = node.children('.ge-tools-drawer').children('.ge-details');
|
|
@@ -1598,6 +1841,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1598
1841
|
|
|
1599
1842
|
if (curView !== ALL_VIEW) { previewTier(scope, breakpoint(curView)); }
|
|
1600
1843
|
|
|
1844
|
+
markRowCols(scope);
|
|
1845
|
+
|
|
1601
1846
|
// Whatever a plugin marks the canvas with to show its utilities
|
|
1602
1847
|
// goes stale at the same moments the preview does
|
|
1603
1848
|
plugins('onRefresh', scope);
|
|
@@ -1615,6 +1860,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1615
1860
|
$.extend(styles, family.preview(effectiveUtility(node, family, tier), node, kind));
|
|
1616
1861
|
});
|
|
1617
1862
|
|
|
1863
|
+
if (kind === 'column') { $.extend(styles, rowColsPreview(node, tier)); }
|
|
1864
|
+
|
|
1618
1865
|
// A plugin whose families settle one property between them
|
|
1619
1866
|
// previews the node as a whole
|
|
1620
1867
|
$.each(UTILITIES, function(name, utility) {
|
|
@@ -1778,6 +2025,11 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
1778
2025
|
blank = inherited
|
|
1779
2026
|
? t('utility.inherit', { value: labelOf(family, inherited.value), breakpoint: inherited.tier.key })
|
|
1780
2027
|
: t('utility.default');
|
|
2028
|
+
|
|
2029
|
+
// What the empty choice means is sometimes not the family's
|
|
2030
|
+
// own business: a column's width can come from its row
|
|
2031
|
+
var custom = family.blank ? family.blank(node, curView) : null;
|
|
2032
|
+
if (custom && own === null) { blank = custom; }
|
|
1781
2033
|
}
|
|
1782
2034
|
|
|
1783
2035
|
// A value the markup carries is shown even when the family
|
|
@@ -2129,9 +2381,10 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2129
2381
|
settings.valid_col_sizes.forEach(function(size) {
|
|
2130
2382
|
$('<a class="ge-size" />')
|
|
2131
2383
|
.attr('data-ge-size', size)
|
|
2132
|
-
.attr('title',
|
|
2133
|
-
.toggleClass('ge-size-tight', size > room)
|
|
2134
|
-
.
|
|
2384
|
+
.attr('title', sizeTitle(size))
|
|
2385
|
+
.toggleClass('ge-size-tight', isUnits(size) && size > room)
|
|
2386
|
+
.toggleClass('ge-size-flex', !isUnits(size))
|
|
2387
|
+
.text(isUnits(size) ? size : sizeClass(BREAKPOINTS[0], size))
|
|
2135
2388
|
.on('click', function(e) {
|
|
2136
2389
|
e.preventDefault();
|
|
2137
2390
|
e.stopPropagation();
|
|
@@ -2152,6 +2405,13 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2152
2405
|
}
|
|
2153
2406
|
|
|
2154
2407
|
/** True when there was one to close, which is also a click's answer. */
|
|
2408
|
+
function sizeTitle(size) {
|
|
2409
|
+
if (size === 'equal') { return t('tool.column_equal'); }
|
|
2410
|
+
if (size === 'auto') { return t('tool.column_auto'); }
|
|
2411
|
+
|
|
2412
|
+
return t('tool.column_size', { size: size });
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2155
2415
|
function closeSizePicker() {
|
|
2156
2416
|
if (!sizePicker) { return false; }
|
|
2157
2417
|
|
|
@@ -2183,7 +2443,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2183
2443
|
createTool(drawer, t('tool.add_column'), 'ge-add-column', 'bi bi-plus-circle', function() {
|
|
2184
2444
|
if (closeSizePicker()) { return; } // The picker was open: that was the answer
|
|
2185
2445
|
|
|
2186
|
-
|
|
2446
|
+
// In a row with row-cols the new column takes its share
|
|
2447
|
+
addColumnTo(row, rowColsSource(row, leadingTier()) ? null : settings.add_column.size);
|
|
2187
2448
|
});
|
|
2188
2449
|
|
|
2189
2450
|
attachSizePicker(drawer.find('> .ge-add-column'), row);
|
|
@@ -2203,12 +2464,15 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2203
2464
|
createTool(drawer, t('tool.column_narrower'), 'ge-decrease-col-width', 'bi bi-dash-lg', function(e) {
|
|
2204
2465
|
resizeColumn(col, e.shiftKey
|
|
2205
2466
|
? smallest(settings.valid_col_sizes)
|
|
2206
|
-
: stepThrough(settings.valid_col_sizes,
|
|
2467
|
+
: stepThrough(settings.valid_col_sizes.filter(isUnits), currentUnits(col), -1),
|
|
2207
2468
|
'tool');
|
|
2208
2469
|
});
|
|
2209
2470
|
|
|
2210
2471
|
createTool(drawer, t('tool.column_wider'), 'ge-increase-col-width', 'bi bi-plus-lg', function(e) {
|
|
2211
|
-
resizeColumn(col, e.shiftKey
|
|
2472
|
+
resizeColumn(col, e.shiftKey
|
|
2473
|
+
? widestFor(col)
|
|
2474
|
+
: stepThrough(settings.valid_col_sizes.filter(isUnits), currentUnits(col), 1),
|
|
2475
|
+
'tool');
|
|
2212
2476
|
});
|
|
2213
2477
|
|
|
2214
2478
|
createTool(drawer, t('tool.indent_decrease'), 'ge-decrease-col-offset', 'bi bi-text-indent-right', function(e) {
|
|
@@ -2259,17 +2523,43 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2259
2523
|
* view it is the widest tier, because the canvas is not constrained
|
|
2260
2524
|
* there and the widest tier is what the user is looking at: clicking
|
|
2261
2525
|
* "narrower" on a column authored as col-lg-6 should take it to 5,
|
|
2262
|
-
* not to 11 because no
|
|
2526
|
+
* not to 11 because no base class was ever written. What the all view
|
|
2527
|
+
* writes is the base class all the same.
|
|
2263
2528
|
*/
|
|
2264
2529
|
function leadingTier() {
|
|
2265
2530
|
return curView === ALL_VIEW ? BREAKPOINTS[BREAKPOINTS.length - 1] : breakpoint(curView);
|
|
2266
2531
|
}
|
|
2267
2532
|
|
|
2533
|
+
/** The size that applies in the view: units, `equal` or `auto`. */
|
|
2268
2534
|
function currentSize(col) {
|
|
2269
|
-
var
|
|
2535
|
+
var tier = leadingTier();
|
|
2536
|
+
|
|
2537
|
+
// Sized by its row: it has no size of its own to report
|
|
2538
|
+
if (rowColsWinner(col, tier)) { return null; }
|
|
2539
|
+
|
|
2540
|
+
var size = getEffectiveSize(col, tier);
|
|
2270
2541
|
return size === null ? MAX_COL_SIZE : size;
|
|
2271
2542
|
}
|
|
2272
2543
|
|
|
2544
|
+
/**
|
|
2545
|
+
* The size in units, which is what the tools step through. An equal
|
|
2546
|
+
* or auto column has no number, so it is measured: the width it has
|
|
2547
|
+
* on the canvas, in twelfths of its row.
|
|
2548
|
+
*/
|
|
2549
|
+
function currentUnits(col) {
|
|
2550
|
+
var size = currentSize(col);
|
|
2551
|
+
if (isUnits(size)) { return size; }
|
|
2552
|
+
|
|
2553
|
+
var units = Math.round(col.outerWidth() / rowContentWidth(col.parent()) * MAX_COL_SIZE);
|
|
2554
|
+
return Math.min(Math.max(units, 1), MAX_COL_SIZE);
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
function rowContentWidth(row) {
|
|
2558
|
+
var style = window.getComputedStyle(row[0]);
|
|
2559
|
+
|
|
2560
|
+
return row[0].clientWidth - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2273
2563
|
function currentOffset(col) {
|
|
2274
2564
|
return getEffectiveOffset(col, leadingTier()) || 0;
|
|
2275
2565
|
}
|
|
@@ -2289,11 +2579,11 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2289
2579
|
}
|
|
2290
2580
|
|
|
2291
2581
|
function smallest(values) {
|
|
2292
|
-
return values.reduce(function(a, b) { return Math.min(a, b); }, MAX_COL_SIZE);
|
|
2582
|
+
return values.filter(isUnits).reduce(function(a, b) { return Math.min(a, b); }, MAX_COL_SIZE);
|
|
2293
2583
|
}
|
|
2294
2584
|
|
|
2295
2585
|
function largest(values) {
|
|
2296
|
-
return values.reduce(function(a, b) { return Math.max(a, b); }, 0);
|
|
2586
|
+
return values.filter(isUnits).reduce(function(a, b) { return Math.max(a, b); }, 0);
|
|
2297
2587
|
}
|
|
2298
2588
|
|
|
2299
2589
|
/**
|
|
@@ -2311,7 +2601,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2311
2601
|
* itself left inside the row.
|
|
2312
2602
|
*/
|
|
2313
2603
|
function deepestFor(col) {
|
|
2314
|
-
var room = spare(col.parent(), leadingTier(), col) -
|
|
2604
|
+
var room = spare(col.parent(), leadingTier(), col) - currentUnits(col);
|
|
2315
2605
|
|
|
2316
2606
|
return Math.min(largest(settings.valid_col_offsets), Math.max(room, 0));
|
|
2317
2607
|
}
|
|
@@ -2354,6 +2644,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2354
2644
|
function isEditorClass(name) {
|
|
2355
2645
|
if (name === 'row' || name === 'column') { return true; }
|
|
2356
2646
|
if (/^(ge-|ui-)/.test(name)) { return true; }
|
|
2647
|
+
if (/^col(-(sm|md|lg|xl|xxl))?(-auto)?$/.test(name)) { return true; }
|
|
2357
2648
|
|
|
2358
2649
|
return BREAKPOINTS.some(function(tier) {
|
|
2359
2650
|
return new RegExp('^(' + tier.colPrefix + '|' + tier.offsetPrefix + ')\\d+$').test(name);
|
|
@@ -2452,15 +2743,137 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2452
2743
|
* column that had none.
|
|
2453
2744
|
*/
|
|
2454
2745
|
function addAllColClasses() {
|
|
2455
|
-
canvas.find('.column, div[class*="col-"]').each(function() {
|
|
2746
|
+
canvas.find('.column, div[class*="col-"], div.col').each(function() {
|
|
2456
2747
|
var col = $(this).addClass('column');
|
|
2457
2748
|
|
|
2458
|
-
|
|
2749
|
+
// A column in a row with row-cols is sized by its row
|
|
2750
|
+
if (sizedTiers(col).length || hasRowCols(col.parent())) { return; }
|
|
2459
2751
|
|
|
2460
2752
|
setSize(col, BREAKPOINTS[0], MAX_COL_SIZE);
|
|
2461
2753
|
});
|
|
2462
2754
|
}
|
|
2463
2755
|
|
|
2756
|
+
/* --------------------------------------------------------------
|
|
2757
|
+
* Columns per row: row-cols-*.
|
|
2758
|
+
*
|
|
2759
|
+
* A row's row-cols class gives every child an equal share of a
|
|
2760
|
+
* line, and a column's own size class takes that share's place.
|
|
2761
|
+
* Which of the two wins at a breakpoint is settled the way
|
|
2762
|
+
* Bootstrap's css settles it: the class from the wider breakpoint,
|
|
2763
|
+
* and at one breakpoint col loses to row-cols, which loses to
|
|
2764
|
+
* col-auto and col-N - the order Bootstrap writes their rules in.
|
|
2765
|
+
* -------------------------------------------------------------- */
|
|
2766
|
+
|
|
2767
|
+
function hasRowCols(row) {
|
|
2768
|
+
return row.hasClass('row') && BREAKPOINTS.some(function(tier) {
|
|
2769
|
+
return ROW_COLS_VALUES.some(function(value) { return row.hasClass(rowColsClass(tier, value)); });
|
|
2770
|
+
});
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
/** The row-cols class that applies to a row at a tier, as { tier, value }, or null. */
|
|
2774
|
+
function rowColsSource(row, tier) {
|
|
2775
|
+
if (!row.hasClass('row')) { return null; }
|
|
2776
|
+
|
|
2777
|
+
for (var i = BREAKPOINTS.indexOf(tier); i >= 0; i--) {
|
|
2778
|
+
for (var v = 0; v < ROW_COLS_VALUES.length; v++) {
|
|
2779
|
+
if (row.hasClass(rowColsClass(BREAKPOINTS[i], ROW_COLS_VALUES[v]))) {
|
|
2780
|
+
return { tier: i, value: ROW_COLS_VALUES[v] };
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
return null;
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
/** The column's own size that applies at a tier, as { tier, size }, or null. */
|
|
2789
|
+
function columnSource(col, tier) {
|
|
2790
|
+
for (var i = BREAKPOINTS.indexOf(tier); i >= 0; i--) {
|
|
2791
|
+
var size = getSize(col, BREAKPOINTS[i]);
|
|
2792
|
+
if (size !== null) { return { tier: i, size: size }; }
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2795
|
+
return null;
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
/**
|
|
2799
|
+
* The row-cols class that sizes this column at a tier, or null when
|
|
2800
|
+
* the column's own size does.
|
|
2801
|
+
*/
|
|
2802
|
+
function rowColsWinner(col, tier) {
|
|
2803
|
+
var row = rowColsSource(col.parent(), tier);
|
|
2804
|
+
if (!row) { return null; }
|
|
2805
|
+
|
|
2806
|
+
var own = columnSource(col, tier);
|
|
2807
|
+
if (!own || row.tier > own.tier) { return row; }
|
|
2808
|
+
|
|
2809
|
+
return row.tier === own.tier && own.size === 'equal' ? row : null;
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
/** A column's share of a line when its row sizes it, in units: auto has no number. */
|
|
2813
|
+
function rowColsUnits(winner) {
|
|
2814
|
+
return winner.value === 'auto' ? 0 : MAX_COL_SIZE / parseInt(winner.value, 10);
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
/**
|
|
2818
|
+
* What a breakpoint view shows of the row-cols a column is under. The
|
|
2819
|
+
* view narrows the canvas, not the window, and Bootstrap's
|
|
2820
|
+
* .row-cols-md-3 > * answers to the window - and to nothing the
|
|
2821
|
+
* preview can put on the row, since it styles the row's children.
|
|
2822
|
+
*/
|
|
2823
|
+
function rowColsPreview(col, tier) {
|
|
2824
|
+
var winner = rowColsWinner(col, tier);
|
|
2825
|
+
|
|
2826
|
+
if (winner) {
|
|
2827
|
+
return {
|
|
2828
|
+
flex: '0 0 auto',
|
|
2829
|
+
width: winner.value === 'auto' ? 'auto' : (100 / parseInt(winner.value, 10)) + '%',
|
|
2830
|
+
'max-width': '100%',
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// A wider breakpoint's row-cols is live in a wide window; a
|
|
2835
|
+
// column with no size of its own here is a full width one
|
|
2836
|
+
if (hasRowCols(col.parent()) && !columnSource(col, tier)) {
|
|
2837
|
+
return { flex: '0 0 auto', width: '100%', 'max-width': '100%' };
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
return {};
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
/**
|
|
2844
|
+
* The badge on a row whose columns are sized by row-cols in the view,
|
|
2845
|
+
* and in the all view by its row-cols with no breakpoint.
|
|
2846
|
+
*/
|
|
2847
|
+
function markRowCols(scope) {
|
|
2848
|
+
scope.find('.row').addBack('.row').each(function() {
|
|
2849
|
+
var row = $(this);
|
|
2850
|
+
var source = settings.row_cols === false ? null : (curView === ALL_VIEW
|
|
2851
|
+
? (rowColsSource(row, BREAKPOINTS[0]) || null)
|
|
2852
|
+
: rowColsSource(row, breakpoint(curView)));
|
|
2853
|
+
|
|
2854
|
+
if (!source) {
|
|
2855
|
+
row.removeAttr('data-ge-row-cols');
|
|
2856
|
+
} else {
|
|
2857
|
+
row.attr('data-ge-row-cols', rowColsLabel(source.value));
|
|
2858
|
+
}
|
|
2859
|
+
});
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
function rowColsLabel(value) {
|
|
2863
|
+
return value === 'auto' ? t('badge.row_cols_auto') : t('badge.row_cols', { count: value });
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
/** The core's family for the field in a row's panel. */
|
|
2867
|
+
function rowColsFamily() {
|
|
2868
|
+
return {
|
|
2869
|
+
name: 'row-cols',
|
|
2870
|
+
prefix: 'row-cols',
|
|
2871
|
+
values: ROW_COLS_VALUES,
|
|
2872
|
+
appliesTo: ['row'],
|
|
2873
|
+
labelKey: 'utility.row_cols',
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2464
2877
|
/* --------------------------------------------------------------
|
|
2465
2878
|
* The sizing core.
|
|
2466
2879
|
*
|
|
@@ -2470,9 +2883,18 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2470
2883
|
* names, the 12 unit budget and what an absent class means.
|
|
2471
2884
|
* -------------------------------------------------------------- */
|
|
2472
2885
|
|
|
2473
|
-
/**
|
|
2886
|
+
/**
|
|
2887
|
+
* A column's size at one tier: a number of units, `equal`, `auto`, or
|
|
2888
|
+
* null when that tier says nothing.
|
|
2889
|
+
*/
|
|
2474
2890
|
function getSize(col, tier) {
|
|
2475
|
-
|
|
2891
|
+
var units = readUnits(col, tier.colPrefix);
|
|
2892
|
+
if (units !== null) { return units; }
|
|
2893
|
+
|
|
2894
|
+
if (col.hasClass(sizeClass(tier, 'auto'))) { return 'auto'; }
|
|
2895
|
+
if (col.hasClass(sizeClass(tier, 'equal'))) { return 'equal'; }
|
|
2896
|
+
|
|
2897
|
+
return null;
|
|
2476
2898
|
}
|
|
2477
2899
|
|
|
2478
2900
|
/** The units a column is indented by at one tier, or null. */
|
|
@@ -2522,8 +2944,12 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2522
2944
|
col.attr('class', classes.join(' '));
|
|
2523
2945
|
}
|
|
2524
2946
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2947
|
+
/** One size per tier: writing a size takes whatever size the tier had off. */
|
|
2948
|
+
function setSize(col, tier, size) {
|
|
2949
|
+
writeUnits(col, tier.colPrefix, null);
|
|
2950
|
+
FLEX_SIZES.forEach(function(flex) { col.removeClass(sizeClass(tier, flex)); });
|
|
2951
|
+
|
|
2952
|
+
if (size !== null && size !== undefined) { col.addClass(sizeClass(tier, size)); }
|
|
2527
2953
|
}
|
|
2528
2954
|
|
|
2529
2955
|
/** An offset of 0 is written as no class at all, which is what it means. */
|
|
@@ -2549,7 +2975,11 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2549
2975
|
var sibling = $(this);
|
|
2550
2976
|
if (ignore && sibling[0] === ignore[0]) { return; }
|
|
2551
2977
|
|
|
2552
|
-
|
|
2978
|
+
// An equal or auto column takes what is left, so it uses none;
|
|
2979
|
+
// one its row sizes uses its share of the line
|
|
2980
|
+
var winner = rowColsWinner(sibling, tier);
|
|
2981
|
+
var size = winner ? rowColsUnits(winner) : getEffectiveSize(sibling, tier);
|
|
2982
|
+
used += (isUnits(size) ? size : 0) + (getEffectiveOffset(sibling, tier) || 0);
|
|
2553
2983
|
});
|
|
2554
2984
|
|
|
2555
2985
|
return MAX_COL_SIZE - used;
|
|
@@ -2570,7 +3000,7 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2570
3000
|
|
|
2571
3001
|
offset = Math.min(Math.max(offset, 0), MAX_COL_OFFSET);
|
|
2572
3002
|
|
|
2573
|
-
if (size === null) { return { size:
|
|
3003
|
+
if (size === null || !isUnits(size)) { return { size: size, offset: offset, refused: false }; }
|
|
2574
3004
|
|
|
2575
3005
|
size = Math.min(Math.max(size, 1), MAX_COL_SIZE);
|
|
2576
3006
|
|
|
@@ -2614,6 +3044,35 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2614
3044
|
return 'ge-' + name + '-' + instanceId;
|
|
2615
3045
|
}
|
|
2616
3046
|
|
|
3047
|
+
/**
|
|
3048
|
+
* What the canvas, the columns and the plugins' regions move: rows,
|
|
3049
|
+
* content areas and containers, and whatever blocks a feature adds -
|
|
3050
|
+
* the sections plugin's sections.
|
|
3051
|
+
*/
|
|
3052
|
+
function blockSelector() {
|
|
3053
|
+
return ['.row', '.ge-content', '[data-ge-container]'].concat(pluginHooks('blocks')).join(', ');
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
/** A selector every feature plugin may contribute to, under one name. */
|
|
3057
|
+
function pluginHooks(name) {
|
|
3058
|
+
return $.map(FEATURES, function(feature) { return feature[name] || null; });
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
/**
|
|
3062
|
+
* Whether a region will have a block dropped in it. Every block goes
|
|
3063
|
+
* everywhere unless a feature says otherwise: a section only on the
|
|
3064
|
+
* canvas, and only rows in a section.
|
|
3065
|
+
*/
|
|
3066
|
+
function acceptsBlock(region, node) {
|
|
3067
|
+
var accepted = true;
|
|
3068
|
+
|
|
3069
|
+
$.each(FEATURES, function(name, feature) {
|
|
3070
|
+
if (accepted && feature.accepts && feature.accepts(region, node) === false) { accepted = false; }
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3073
|
+
return accepted;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
2617
3076
|
/** What must never start a drag, whatever the handle is. */
|
|
2618
3077
|
function dragCancelSelector() {
|
|
2619
3078
|
return settings.drag_handle === 'drawer'
|
|
@@ -2651,6 +3110,16 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2651
3110
|
? { name: groupName(options.group) }
|
|
2652
3111
|
: { name: groupName(options.draggable + '-' + (++soloGroup)), pull: false, put: false };
|
|
2653
3112
|
|
|
3113
|
+
// A list may turn some of its group's items away. A put
|
|
3114
|
+
// function replaces SortableJS's own test that the item comes
|
|
3115
|
+
// from the same group, so it makes that test too: without it
|
|
3116
|
+
// a column would drop into the canvas, or into another editor
|
|
3117
|
+
if (options.group && options.accepts) {
|
|
3118
|
+
group.put = function(to, from, dragged) {
|
|
3119
|
+
return from.options.group.name === group.name && options.accepts($(to.el), $(dragged));
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
|
|
2654
3123
|
sortables.push(window.Sortable.create(list, $.extend({
|
|
2655
3124
|
group: group,
|
|
2656
3125
|
draggable: options.draggable,
|
|
@@ -2715,9 +3184,24 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2715
3184
|
});
|
|
2716
3185
|
|
|
2717
3186
|
sortable(canvas.add(canvas.find('.column')), {
|
|
2718
|
-
draggable:
|
|
3187
|
+
draggable: blockSelector(),
|
|
2719
3188
|
group: 'block',
|
|
2720
|
-
|
|
3189
|
+
accepts: acceptsBlock,
|
|
3190
|
+
});
|
|
3191
|
+
|
|
3192
|
+
// A plugin's region can be a block itself - a section is both -
|
|
3193
|
+
// and SortableJS tests a list's own element against the draggable
|
|
3194
|
+
// selector when it counts the list's children, so every child of
|
|
3195
|
+
// a section would count as a block, its drawer first. '>' is
|
|
3196
|
+
// SortableJS for "direct children only", which the list is not.
|
|
3197
|
+
var regions = pluginHooks('regions');
|
|
3198
|
+
if (regions.length) {
|
|
3199
|
+
sortable(canvas.find(regions.join(', ')), {
|
|
3200
|
+
draggable: '>' + blockSelector(),
|
|
3201
|
+
group: 'block',
|
|
3202
|
+
accepts: acceptsBlock,
|
|
3203
|
+
});
|
|
3204
|
+
}
|
|
2721
3205
|
|
|
2722
3206
|
// A plugin makes its own: only it knows which of its parts move
|
|
2723
3207
|
plugins('onSortable', sortable);
|
|
@@ -2889,20 +3373,21 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2889
3373
|
* divider between two columns looks like it should do.
|
|
2890
3374
|
*/
|
|
2891
3375
|
function snapUnits(col, pixels) {
|
|
2892
|
-
var
|
|
2893
|
-
var style = window.getComputedStyle(row[0]);
|
|
2894
|
-
var content = row[0].clientWidth -
|
|
2895
|
-
parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
|
|
2896
|
-
|
|
2897
|
-
var units = Math.round(pixels / content * MAX_COL_SIZE);
|
|
3376
|
+
var units = Math.round(pixels / rowContentWidth(col.parent()) * MAX_COL_SIZE);
|
|
2898
3377
|
var next = balanceSibling(col);
|
|
3378
|
+
var nextSize = next ? currentSize(next) : null;
|
|
3379
|
+
|
|
3380
|
+
// Measured when the drag started: the column is the width of the
|
|
3381
|
+
// pointer now, which is not what it was
|
|
3382
|
+
var own = col.data('ge-resize-units');
|
|
2899
3383
|
|
|
2900
3384
|
// With a sibling to balance against, the drag may take that
|
|
2901
3385
|
// column's units but not its last one. Without one, the row is
|
|
2902
3386
|
// allowed to wrap - that is what balance false means - so the only
|
|
2903
3387
|
// limit is the column's own budget against its indent.
|
|
2904
|
-
|
|
2905
|
-
|
|
3388
|
+
// An equal or auto sibling gives way by itself, so it sets no limit
|
|
3389
|
+
var room = next && isUnits(nextSize)
|
|
3390
|
+
? own + nextSize - smallest(settings.valid_col_sizes)
|
|
2906
3391
|
: MAX_COL_SIZE - currentOffset(col);
|
|
2907
3392
|
|
|
2908
3393
|
return Math.min(
|
|
@@ -2948,7 +3433,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2948
3433
|
if (!allowed) { return false; }
|
|
2949
3434
|
|
|
2950
3435
|
col.data('ge-resize-from', from);
|
|
2951
|
-
|
|
3436
|
+
col.data('ge-resize-units', currentUnits(col));
|
|
3437
|
+
resizeReadout(col, sizeLabel(col.data('ge-resize-units')));
|
|
2952
3438
|
|
|
2953
3439
|
return true;
|
|
2954
3440
|
}
|
|
@@ -2959,30 +3445,33 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2959
3445
|
|
|
2960
3446
|
function resizeStop(col, width) {
|
|
2961
3447
|
var from = col.data('ge-resize-from');
|
|
3448
|
+
var started = col.data('ge-resize-units');
|
|
2962
3449
|
var units = snapUnits(col, width);
|
|
2963
3450
|
|
|
2964
|
-
col.removeData('ge-resize-from');
|
|
3451
|
+
col.removeData('ge-resize-from').removeData('ge-resize-units');
|
|
2965
3452
|
resizeReadout(col, '');
|
|
2966
3453
|
stripPixelWidths(col);
|
|
2967
3454
|
|
|
2968
3455
|
if (from === undefined) { return; }
|
|
2969
3456
|
|
|
2970
3457
|
// A drag of a couple of pixels lands on the size it started from,
|
|
2971
|
-
// and is not a resize
|
|
2972
|
-
|
|
3458
|
+
// and is not a resize - not even of an equal or auto column,
|
|
3459
|
+
// which it would otherwise turn into a number
|
|
3460
|
+
if (units === started) { return; }
|
|
2973
3461
|
|
|
2974
3462
|
var plan = planSize(col, units);
|
|
2975
3463
|
if (!plan) { return; }
|
|
2976
3464
|
|
|
2977
3465
|
operate(function() {
|
|
2978
3466
|
writeSize(col, plan);
|
|
2979
|
-
balanceAfterResize(col,
|
|
3467
|
+
balanceAfterResize(col, units - started);
|
|
3468
|
+
refreshUtilities(col);
|
|
2980
3469
|
|
|
2981
|
-
emit('after-resize', payloadFor('column', col, {
|
|
3470
|
+
emit('after-resize', payloadFor('column', col, withCleared({
|
|
2982
3471
|
source: 'dragdrop',
|
|
2983
3472
|
from: from,
|
|
2984
3473
|
to: plan.size,
|
|
2985
|
-
}));
|
|
3474
|
+
}, plan.cleared)));
|
|
2986
3475
|
});
|
|
2987
3476
|
}
|
|
2988
3477
|
|
|
@@ -2990,12 +3479,22 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
2990
3479
|
* Move the delta into the following column, so a full row stays full.
|
|
2991
3480
|
* It is part of the same gesture, so it is not announced separately.
|
|
2992
3481
|
*/
|
|
3482
|
+
/**
|
|
3483
|
+
* The column after takes what the resized one gave or took, unless it
|
|
3484
|
+
* is equal or auto: those take what is left by themselves.
|
|
3485
|
+
*/
|
|
2993
3486
|
function balanceAfterResize(col, delta) {
|
|
2994
3487
|
var next = balanceSibling(col);
|
|
2995
3488
|
if (!next || !delta) { return; }
|
|
2996
3489
|
|
|
2997
|
-
var
|
|
2998
|
-
if (
|
|
3490
|
+
var size = currentSize(next);
|
|
3491
|
+
if (!isUnits(size)) { return; }
|
|
3492
|
+
|
|
3493
|
+
var plan = planSize(next, size - delta);
|
|
3494
|
+
if (plan) {
|
|
3495
|
+
writeSize(next, plan);
|
|
3496
|
+
refreshUtilities(next);
|
|
3497
|
+
}
|
|
2999
3498
|
}
|
|
3000
3499
|
|
|
3001
3500
|
/**
|
|
@@ -3062,13 +3561,15 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
3062
3561
|
function apiCreateRow(layout, options) {
|
|
3063
3562
|
var row = createRow();
|
|
3064
3563
|
|
|
3065
|
-
if (layout !== undefined && !Array.isArray(layout)) {
|
|
3066
|
-
warn('createRow: the layout is an array of column sizes, as in [8, 4]
|
|
3067
|
-
'Making an empty row instead.');
|
|
3564
|
+
if (layout !== undefined && !Array.isArray(layout) && !(layout && layout.row_cols)) {
|
|
3565
|
+
warn('createRow: the layout is an array of column sizes, as in [8, 4], or ' +
|
|
3566
|
+
'{ row_cols, columns }. Making an empty row instead.');
|
|
3068
3567
|
layout = [];
|
|
3069
3568
|
}
|
|
3070
3569
|
|
|
3071
|
-
(layout
|
|
3570
|
+
if (layout && !Array.isArray(layout)) { row = rowFromLayoutValue(layout); }
|
|
3571
|
+
|
|
3572
|
+
(Array.isArray(layout) ? layout : []).forEach(function(size) {
|
|
3072
3573
|
createColumn(size).appendTo(row);
|
|
3073
3574
|
});
|
|
3074
3575
|
|
|
@@ -3081,7 +3582,12 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
3081
3582
|
function apiCreateColumn(size, options) {
|
|
3082
3583
|
options = options || {};
|
|
3083
3584
|
|
|
3084
|
-
|
|
3585
|
+
// Going into a row with row-cols, no size is a size: the row's share
|
|
3586
|
+
var into = $(options.appendTo || options.prependTo || []).first();
|
|
3587
|
+
|
|
3588
|
+
if (size === undefined && into.length && rowColsSource(into, leadingTier())) {
|
|
3589
|
+
size = null;
|
|
3590
|
+
} else if (!isUnits(size) && FLEX_SIZES.indexOf(size) === -1) {
|
|
3085
3591
|
warn('createColumn: no column size given, using ' + MAX_COL_SIZE);
|
|
3086
3592
|
size = MAX_COL_SIZE;
|
|
3087
3593
|
}
|
|
@@ -3152,8 +3658,8 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
3152
3658
|
}
|
|
3153
3659
|
|
|
3154
3660
|
/**
|
|
3155
|
-
* A column sized for the current view:
|
|
3156
|
-
* all view. `offset` indents it, within the same 12 unit budget.
|
|
3661
|
+
* A column sized for the current view: its tier, or the base class in
|
|
3662
|
+
* the all view. `offset` indents it, within the same 12 unit budget.
|
|
3157
3663
|
*/
|
|
3158
3664
|
function createColumn(size, offset) {
|
|
3159
3665
|
var rte = getRTE(settings.content_types[0]);
|
|
@@ -3161,12 +3667,12 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
3161
3667
|
.append(createDefaultContentWrapper().html(rte ? rte.initialContent : ''))
|
|
3162
3668
|
;
|
|
3163
3669
|
|
|
3164
|
-
|
|
3165
|
-
|
|
3670
|
+
// The tier being edited, or the base class in the all view
|
|
3671
|
+
var tier = tiersFor(curView)[0];
|
|
3672
|
+
var wanted = clamp({ size: size, offset: offset || 0, leading: 'offset' });
|
|
3166
3673
|
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
});
|
|
3674
|
+
setSize(column, tier, wanted.size === null ? size : wanted.size);
|
|
3675
|
+
setOffset(column, tier, wanted.offset);
|
|
3170
3676
|
|
|
3171
3677
|
return column;
|
|
3172
3678
|
}
|
|
@@ -3324,6 +3830,15 @@ $.fn.gridEditor = function( optionsOrMethod ) {
|
|
|
3324
3830
|
|
|
3325
3831
|
return featureMethods.createElement(content, options);
|
|
3326
3832
|
},
|
|
3833
|
+
createSection: function(options) {
|
|
3834
|
+
if (!featureMethods.createSection) {
|
|
3835
|
+
warnOnceHere('plugin:sections', 'createSection needs the sections plugin: ' +
|
|
3836
|
+
'include dist/plugins/grideditor.sections.js after the editor');
|
|
3837
|
+
return null;
|
|
3838
|
+
}
|
|
3839
|
+
|
|
3840
|
+
return featureMethods.createSection(options);
|
|
3841
|
+
},
|
|
3327
3842
|
createContainer: apiCreateContainer,
|
|
3328
3843
|
addTab: function(container, options) { return addPaneTo(container, 'tabs', options); },
|
|
3329
3844
|
addAccordionItem: function(container, options) {
|
|
@@ -3416,6 +3931,8 @@ $.fn.gridEditor.locales = {
|
|
|
3416
3931
|
'tool.add_row': 'Add row',
|
|
3417
3932
|
'tool.add_column': 'Add column\n(hold to choose the width)',
|
|
3418
3933
|
'tool.column_size': '{size} of 12',
|
|
3934
|
+
'tool.column_equal': 'Equal: shares what the row has left',
|
|
3935
|
+
'tool.column_auto': 'Auto: as wide as its content',
|
|
3419
3936
|
'tool.delete_row': 'Remove row',
|
|
3420
3937
|
'tool.delete_column': 'Remove col',
|
|
3421
3938
|
'tool.delete_container': 'Remove container',
|
|
@@ -3433,6 +3950,7 @@ $.fn.gridEditor.locales = {
|
|
|
3433
3950
|
'tool.classes_title': 'Css classes, separated by spaces',
|
|
3434
3951
|
'tool.toggle_class': 'Toggle "{label}" styling',
|
|
3435
3952
|
'row.add': 'Add row {layout}',
|
|
3953
|
+
'row.add_row_cols': 'Add a row of {columns} columns, {counts} per row',
|
|
3436
3954
|
'confirm.title': 'Confirm',
|
|
3437
3955
|
'confirm.ok': 'Delete',
|
|
3438
3956
|
'confirm.cancel': 'Cancel',
|
|
@@ -3447,6 +3965,13 @@ $.fn.gridEditor.locales = {
|
|
|
3447
3965
|
'view.xl': 'Large desktop',
|
|
3448
3966
|
'view.xxl': 'Widescreen',
|
|
3449
3967
|
'utility.section': 'Responsive: {view}',
|
|
3968
|
+
'utility.col_width': 'Width',
|
|
3969
|
+
'utility.col_equal': 'Equal',
|
|
3970
|
+
'utility.col_auto': 'Auto',
|
|
3971
|
+
'utility.col_from_row': 'From the row: {count}',
|
|
3972
|
+
'utility.row_cols': 'Columns per row',
|
|
3973
|
+
'badge.row_cols': '{count} per row',
|
|
3974
|
+
'badge.row_cols_auto': 'As wide as their content',
|
|
3450
3975
|
'utility.default': 'Default',
|
|
3451
3976
|
'utility.inherit': 'Inherit: {value} (from {breakpoint})',
|
|
3452
3977
|
'utility.varies': 'Changes at {breakpoints}; choosing here replaces that',
|