@themarioga/grid-editor 4.0.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 +95 -0
- package/README.md +121 -9
- package/UPGRADING.md +55 -0
- package/dist/grideditor.css +609 -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 +1189 -118
- package/dist/jquery.grideditor.min.js +1 -1
- package/dist/jquery.grideditor.min.js.map +1 -1
- package/dist/locales/grideditor.es.js +58 -0
- package/dist/locales/grideditor.es.min.js +1 -1
- package/dist/locales/grideditor.es.min.js.map +1 -1
- package/dist/plugins/grideditor.alignment.js +81 -0
- package/dist/plugins/grideditor.alignment.min.js +2 -0
- package/dist/plugins/grideditor.alignment.min.js.map +1 -0
- 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.gutters.js +145 -0
- package/dist/plugins/grideditor.gutters.min.js +2 -0
- package/dist/plugins/grideditor.gutters.min.js.map +1 -0
- package/dist/plugins/grideditor.order.js +206 -0
- package/dist/plugins/grideditor.order.min.js +2 -0
- package/dist/plugins/grideditor.order.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.spacing.js +299 -0
- package/dist/plugins/grideditor.spacing.min.js +2 -0
- package/dist/plugins/grideditor.spacing.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/dist/plugins/grideditor.visibility.js +172 -0
- package/dist/plugins/grideditor.visibility.min.js +2 -0
- package/dist/plugins/grideditor.visibility.min.js.map +1 -0
- package/docs/events.md +32 -2
- package/docs/locale-keys.md +88 -1
- package/docs/plugins.md +141 -3
- package/example/autocols.html +137 -0
- package/example/autosave.html +5 -0
- package/example/basic.html +5 -0
- package/example/breakpoints.html +12 -5
- package/example/ckeditor.html +5 -0
- package/example/containers.html +4 -0
- package/example/elements.html +5 -0
- package/example/index.html +38 -1
- package/example/locale.html +5 -0
- package/example/plugins.html +5 -0
- package/example/summernote.html +5 -0
- package/example/utilities.html +166 -0
- package/example/wrap_content.html +5 -0
- package/package.json +1 -1
- package/src/js/jquery.grideditor.js +1190 -119
- package/src/js/locales/grideditor.es.js +58 -0
- package/src/js/plugins/grideditor.alignment.js +81 -0
- package/src/js/plugins/grideditor.float.js +56 -0
- package/src/js/plugins/grideditor.gutters.js +145 -0
- package/src/js/plugins/grideditor.order.js +206 -0
- package/src/js/plugins/grideditor.sections.js +199 -0
- package/src/js/plugins/grideditor.spacing.js +299 -0
- package/src/js/plugins/grideditor.textalign.js +60 -0
- package/src/js/plugins/grideditor.visibility.js +172 -0
- package/src/less/grideditor.less +299 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sections for grid-editor.
|
|
3
|
+
*
|
|
4
|
+
* A feature plugin: load this file after the editor and the canvas can hold
|
|
5
|
+
* sections - Bootstrap's .container, .container-fluid and .container-{bp} -
|
|
6
|
+
* each grouping rows at a width of its own. What it can ask the editor for is
|
|
7
|
+
* the handle its factory is called with, described in docs/plugins.md.
|
|
8
|
+
*
|
|
9
|
+
* <script src="dist/jquery.grideditor.min.js"></script>
|
|
10
|
+
* <script src="dist/plugins/grideditor.sections.min.js"></script>
|
|
11
|
+
*
|
|
12
|
+
* Called sections, not containers, because a container is what the tabs,
|
|
13
|
+
* accordion, popup and card plugins make. A section is recognised by its
|
|
14
|
+
* Bootstrap class alone, and only as a child of the canvas: a .container
|
|
15
|
+
* somewhere inside an element's markup is that element's business.
|
|
16
|
+
*
|
|
17
|
+
* sections.widths narrows the widths the field offers.
|
|
18
|
+
*/
|
|
19
|
+
(function($) {
|
|
20
|
+
|
|
21
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
22
|
+
'section.add': 'Section',
|
|
23
|
+
'section.width': 'Width',
|
|
24
|
+
'section.fixed': 'Fixed',
|
|
25
|
+
'section.fluid': 'Full width',
|
|
26
|
+
'section.from': 'Fixed from {breakpoint}',
|
|
27
|
+
'tool.add_row_to_section': 'Add row',
|
|
28
|
+
'tool.delete_section': 'Remove section',
|
|
29
|
+
'confirm.delete_section': 'Delete this section and everything in it?',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/** Each width, and the class that gives it. */
|
|
33
|
+
var WIDTHS = {
|
|
34
|
+
fixed: 'container',
|
|
35
|
+
fluid: 'container-fluid',
|
|
36
|
+
sm: 'container-sm',
|
|
37
|
+
md: 'container-md',
|
|
38
|
+
lg: 'container-lg',
|
|
39
|
+
xl: 'container-xl',
|
|
40
|
+
xxl: 'container-xxl',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
var ORDER = ['fixed', 'sm', 'md', 'lg', 'xl', 'xxl', 'fluid'];
|
|
44
|
+
|
|
45
|
+
$.fn.gridEditor.features.sections = function(ge) {
|
|
46
|
+
|
|
47
|
+
var options = $.extend({ widths: ORDER }, ge.settings.sections);
|
|
48
|
+
|
|
49
|
+
function widthOf(section) {
|
|
50
|
+
var found = null;
|
|
51
|
+
|
|
52
|
+
$.each(WIDTHS, function(width, className) {
|
|
53
|
+
if (!found && section.hasClass(className)) { found = width; }
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isSection(node) {
|
|
60
|
+
return node.parent()[0] === ge.canvas[0] && widthOf(node) !== null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function sections() {
|
|
64
|
+
return ge.canvas.children().filter(function() { return isSection($(this)); });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function label(width) {
|
|
68
|
+
if (width === 'fixed') { return ge.t('section.fixed'); }
|
|
69
|
+
if (width === 'fluid') { return ge.t('section.fluid'); }
|
|
70
|
+
|
|
71
|
+
return ge.t('section.from', { breakpoint: width });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Change a section's width, announced like a utility: the width is its
|
|
76
|
+
* one container class, the same at every breakpoint.
|
|
77
|
+
*/
|
|
78
|
+
function setWidth(section, width, source) {
|
|
79
|
+
var from = widthOf(section);
|
|
80
|
+
if (from === width || !WIDTHS[width]) { return false; }
|
|
81
|
+
|
|
82
|
+
return ge.operate(function() {
|
|
83
|
+
var payload = ge.payloadFor('section', section, {
|
|
84
|
+
family: 'section',
|
|
85
|
+
breakpoint: 'all',
|
|
86
|
+
tiers: [],
|
|
87
|
+
from: from,
|
|
88
|
+
to: width,
|
|
89
|
+
source: source || 'api',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!ge.emit('before-utility', payload)) {
|
|
93
|
+
section.find('> .ge-tools-drawer .ge-section-width select').val(from);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
section.removeClass(WIDTHS[from]).addClass(WIDTHS[width]);
|
|
98
|
+
ge.emit('after-utility', payload);
|
|
99
|
+
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function widthField(section) {
|
|
105
|
+
var select = $('<select />');
|
|
106
|
+
var current = widthOf(section);
|
|
107
|
+
var offered = options.widths.indexOf(current) === -1 ? options.widths.concat([current]) : options.widths;
|
|
108
|
+
|
|
109
|
+
ORDER.forEach(function(width) {
|
|
110
|
+
if (offered.indexOf(width) === -1) { return; }
|
|
111
|
+
$('<option />').attr('value', width).text(label(width)).appendTo(select);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
select.val(current).on('change', function() { setWidth(section, this.value, 'panel'); });
|
|
115
|
+
|
|
116
|
+
return $('<label class="ge-utility ge-section-width" />')
|
|
117
|
+
.append($('<span class="ge-utility-label" />').text(ge.t('section.width')))
|
|
118
|
+
.append(select);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function createControls(section) {
|
|
122
|
+
var drawer = $('<div class="ge-tools-drawer ge-section-drawer" />').prependTo(section);
|
|
123
|
+
|
|
124
|
+
ge.createMoveTool(drawer);
|
|
125
|
+
ge.addSettingsTool(drawer, section, ge.settings.section_classes || []).append(widthField(section));
|
|
126
|
+
|
|
127
|
+
ge.createTool(drawer, ge.t('tool.add_row_to_section'), 'ge-add-row', 'bi bi-plus-circle', function() {
|
|
128
|
+
ge.place(ge.rowFromLayout([12]), 'row', { appendTo: section });
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
ge.createTool(drawer, ge.t('tool.delete_section'), 'ge-delete-section', 'bi bi-trash', function() {
|
|
132
|
+
ge.deleteNode('section', section, ge.t('confirm.delete_section'), function(removed) {
|
|
133
|
+
section.slideUp(removed);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function mark() {
|
|
139
|
+
sections().each(function() {
|
|
140
|
+
var section = $(this).addClass('ge-section');
|
|
141
|
+
if (!section.children('.ge-tools-drawer').length) { createControls(section); }
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function unmark() {
|
|
146
|
+
ge.canvas.children('.ge-section').removeClass('ge-section');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** createSection(options): a section, detached unless a placement is given. */
|
|
150
|
+
function createSection(settings) {
|
|
151
|
+
settings = settings || {};
|
|
152
|
+
|
|
153
|
+
var section = $('<div />').addClass(WIDTHS[settings.width] || WIDTHS.fixed);
|
|
154
|
+
|
|
155
|
+
(settings.rows || [[12]]).forEach(function(layout) {
|
|
156
|
+
ge.rowFromLayout(layout).appendTo(section);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return ge.place(section, 'section', settings);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
methods: {
|
|
164
|
+
createSection: createSection,
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
kindOf: function(node) {
|
|
168
|
+
return node.hasClass('ge-section') ? 'section' : null;
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// A section is a block the canvas moves, and a region rows move in
|
|
172
|
+
blocks: '.ge-section',
|
|
173
|
+
regions: '.ge-section',
|
|
174
|
+
|
|
175
|
+
/** A section goes on the canvas and nowhere else, and holds rows and nothing else. */
|
|
176
|
+
accepts: function(region, node) {
|
|
177
|
+
if (node.hasClass('ge-section') || isSectionMade(node)) { return region[0] === ge.canvas[0]; }
|
|
178
|
+
if (region.hasClass('ge-section')) { return node.hasClass('row'); }
|
|
179
|
+
|
|
180
|
+
return true;
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
toolbar: [{
|
|
184
|
+
labelKey: 'section.add',
|
|
185
|
+
kind: 'section',
|
|
186
|
+
create: function() { return createSection(); },
|
|
187
|
+
}],
|
|
188
|
+
|
|
189
|
+
onInit: mark,
|
|
190
|
+
onDeinit: unmark,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/** A section the toolbar just made, before init has marked it. */
|
|
194
|
+
function isSectionMade(node) {
|
|
195
|
+
return !node.parent().length && widthOf(node) !== null;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
})(jQuery);
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacing for grid-editor.
|
|
3
|
+
*
|
|
4
|
+
* A utility plugin: load this file after the editor and every row, column,
|
|
5
|
+
* element and container can have its padding and margin set per breakpoint,
|
|
6
|
+
* with Bootstrap's p-{breakpoint}-*, pt-, px- … and m-{breakpoint}-*, mt-, mx-
|
|
7
|
+
* … classes. What it can ask the editor for is the handle its factory is
|
|
8
|
+
* called with, described in docs/plugins.md.
|
|
9
|
+
*
|
|
10
|
+
* <script src="dist/jquery.grideditor.min.js"></script>
|
|
11
|
+
* <script src="dist/plugins/grideditor.spacing.min.js"></script>
|
|
12
|
+
*
|
|
13
|
+
* Fourteen families would be fourteen fields, so the panel has two, padding
|
|
14
|
+
* and margin, each a choice of side and a value for that side.
|
|
15
|
+
*
|
|
16
|
+
* utilities.spacing.values narrows the values offered, and
|
|
17
|
+
* utilities.spacing.scale is what 0 to 5 come to, for a page that changed
|
|
18
|
+
* Bootstrap's $spacers.
|
|
19
|
+
*/
|
|
20
|
+
(function($) {
|
|
21
|
+
|
|
22
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
23
|
+
'utility.padding': 'Padding',
|
|
24
|
+
'utility.margin': 'Margin',
|
|
25
|
+
'utility.side_all': 'All sides',
|
|
26
|
+
'utility.side_x': 'Left and right',
|
|
27
|
+
'utility.side_y': 'Top and bottom',
|
|
28
|
+
'utility.side_t': 'Top',
|
|
29
|
+
'utility.side_b': 'Bottom',
|
|
30
|
+
'utility.side_s': 'Start',
|
|
31
|
+
'utility.side_e': 'End',
|
|
32
|
+
'utility.spacing_gutter': 'A column\'s side padding is its gutter: changing it changes the gutter',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
var VALUES = ['0', '1', '2', '3', '4', '5'];
|
|
36
|
+
|
|
37
|
+
/** Bootstrap's $spacers. */
|
|
38
|
+
var SCALE = ['0', '.25rem', '.5rem', '1rem', '1.5rem', '3rem'];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The sides, in the order Bootstrap's css writes their rules: within one
|
|
42
|
+
* breakpoint a later rule wins, so p-3 pt-1 has a top of .25rem.
|
|
43
|
+
*/
|
|
44
|
+
var SIDES = ['', 'x', 'y', 't', 'e', 'b', 's'];
|
|
45
|
+
|
|
46
|
+
/** What each side sets. Start and end are left and right: Bootstrap's css is left to right. */
|
|
47
|
+
var SET = {
|
|
48
|
+
'': ['top', 'right', 'bottom', 'left'],
|
|
49
|
+
x: ['left', 'right'],
|
|
50
|
+
y: ['top', 'bottom'],
|
|
51
|
+
t: ['top'],
|
|
52
|
+
e: ['right'],
|
|
53
|
+
b: ['bottom'],
|
|
54
|
+
s: ['left'],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
var INFIXES = ['', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
|
58
|
+
|
|
59
|
+
var PROPERTIES = { p: 'padding', m: 'margin' };
|
|
60
|
+
|
|
61
|
+
/** Every class of the plugin's, padding or margin. */
|
|
62
|
+
function pattern(key) {
|
|
63
|
+
return new RegExp('^' + key + '[xytbse]?-(?:(?:sm|md|lg|xl|xxl)-)?(?:[0-5]|auto)$');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
$.fn.gridEditor.utilities.spacing = function(ge) {
|
|
67
|
+
|
|
68
|
+
var options = $.extend({ values: VALUES, scale: SCALE }, ge.settings.utilities.spacing);
|
|
69
|
+
var patterns = { p: pattern('p'), m: pattern('m') };
|
|
70
|
+
|
|
71
|
+
function applies(node, kind) {
|
|
72
|
+
return kind === 'row' || kind === 'column' || kind === 'element' ||
|
|
73
|
+
node.is('[data-ge-container]');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function classes(node) {
|
|
77
|
+
return (node.attr('class') || '').split(/\s+/);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function carries(node, key) {
|
|
81
|
+
return classes(node).some(function(name) { return patterns[key].test(name); });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The class of one family that decides a side at a breakpoint: the
|
|
86
|
+
* widest breakpoint up to it that has one, as { tier, value }.
|
|
87
|
+
*/
|
|
88
|
+
function source(node, family, tier) {
|
|
89
|
+
var names = classes(node);
|
|
90
|
+
var values = family.charAt(0) === 'm' ? VALUES.concat(['auto']) : VALUES;
|
|
91
|
+
|
|
92
|
+
for (var i = tier; i >= 0; i--) {
|
|
93
|
+
for (var v = 0; v < values.length; v++) {
|
|
94
|
+
var name = family + (INFIXES[i] ? '-' + INFIXES[i] : '') + '-' + values[v];
|
|
95
|
+
if (names.indexOf(name) !== -1) { return { tier: i, value: values[v] }; }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What padding or margin is on each side with none of the plugin's
|
|
104
|
+
* classes: the editor's frame for a row or a column, the host's css
|
|
105
|
+
* for anything else. Read by taking the classes off for a moment,
|
|
106
|
+
* since that is the only way to ask the browser.
|
|
107
|
+
*/
|
|
108
|
+
function without(node, key) {
|
|
109
|
+
var original = node.attr('class');
|
|
110
|
+
var style;
|
|
111
|
+
var bare = {};
|
|
112
|
+
|
|
113
|
+
node.attr('class', classes(node).filter(function(name) { return !patterns[key].test(name); }).join(' '));
|
|
114
|
+
style = getComputedStyle(node[0]);
|
|
115
|
+
['top', 'right', 'bottom', 'left'].forEach(function(side) {
|
|
116
|
+
bare[side] = style.getPropertyValue(PROPERTIES[key] + '-' + side);
|
|
117
|
+
});
|
|
118
|
+
node.attr('class', original);
|
|
119
|
+
|
|
120
|
+
return bare;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Each side the way Bootstrap's css settles it: the class from the
|
|
125
|
+
* widest breakpoint wins, and within one breakpoint the side written
|
|
126
|
+
* later in the css. A side no class reaches shows what it is without
|
|
127
|
+
* any, over a wider breakpoint's class that is live in a wide window.
|
|
128
|
+
*/
|
|
129
|
+
function sides(node, key, breakpoint) {
|
|
130
|
+
var tier = ge.breakpoints.indexOf(breakpoint);
|
|
131
|
+
var winners = {};
|
|
132
|
+
var styles = {};
|
|
133
|
+
var neutral = null;
|
|
134
|
+
|
|
135
|
+
SIDES.forEach(function(side, order) {
|
|
136
|
+
var found = source(node, key + side, tier);
|
|
137
|
+
if (!found) { return; }
|
|
138
|
+
|
|
139
|
+
SET[side].forEach(function(set) {
|
|
140
|
+
var current = winners[set];
|
|
141
|
+
if (!current || found.tier > current.tier || (found.tier === current.tier && order > current.order)) {
|
|
142
|
+
winners[set] = { tier: found.tier, order: order, value: found.value };
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
['top', 'right', 'bottom', 'left'].forEach(function(set) {
|
|
148
|
+
var winner = winners[set];
|
|
149
|
+
|
|
150
|
+
if (!winner) {
|
|
151
|
+
neutral = neutral || without(node, key);
|
|
152
|
+
styles[PROPERTIES[key] + '-' + set] = neutral[set];
|
|
153
|
+
} else {
|
|
154
|
+
styles[PROPERTIES[key] + '-' + set] = winner.value === 'auto' ? 'auto' : options.scale[winner.value];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return styles;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The side a group's select starts on: the first that has a class, or all. */
|
|
162
|
+
function startingSide(node, key) {
|
|
163
|
+
var names = classes(node).filter(function(name) { return patterns[key].test(name); });
|
|
164
|
+
var found = SIDES.filter(function(side) {
|
|
165
|
+
return names.some(function(name) { return name.indexOf(key + side + '-') === 0; });
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return found.length ? found[0] : '';
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function sideLabel(side) {
|
|
172
|
+
switch (side) {
|
|
173
|
+
case 'x': return ge.t('utility.side_x');
|
|
174
|
+
case 'y': return ge.t('utility.side_y');
|
|
175
|
+
case 't': return ge.t('utility.side_t');
|
|
176
|
+
case 'b': return ge.t('utility.side_b');
|
|
177
|
+
case 's': return ge.t('utility.side_s');
|
|
178
|
+
case 'e': return ge.t('utility.side_e');
|
|
179
|
+
default: return ge.t('utility.side_all');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** A padding or margin group: its name, the side, and the field of that side's family. */
|
|
184
|
+
function group(node, key, labelText) {
|
|
185
|
+
var box = $('<div class="ge-spacing-group" />').attr('data-ge-spacing', key);
|
|
186
|
+
var side = $('<select class="ge-spacing-side" />');
|
|
187
|
+
|
|
188
|
+
$('<span class="ge-utility-label" />').text(labelText).appendTo(box);
|
|
189
|
+
|
|
190
|
+
SIDES.forEach(function(value) {
|
|
191
|
+
$('<option />').attr('value', value).text(sideLabel(value)).appendTo(side);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
var field = ge.utilityField(node, key + startingSide(node, key));
|
|
195
|
+
|
|
196
|
+
side.val(field.attr('data-ge-family').slice(1))
|
|
197
|
+
.on('change', function() {
|
|
198
|
+
var next = ge.utilityField(node, key + this.value);
|
|
199
|
+
field.replaceWith(next);
|
|
200
|
+
field = next;
|
|
201
|
+
})
|
|
202
|
+
.appendTo(box)
|
|
203
|
+
;
|
|
204
|
+
field.appendTo(box);
|
|
205
|
+
|
|
206
|
+
return box;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
var NODES = '.row, .column, .ge-element, [data-ge-container]';
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Keep each drawer on its node's edges. A drawer is pulled out over the
|
|
213
|
+
* editor's frame by as much as the frame pads the node, and a padding
|
|
214
|
+
* class replaces the frame, so a padded node's drawer is pulled out by
|
|
215
|
+
* its real padding instead. And a column padded at the sides gets a word
|
|
216
|
+
* about what that does to its gutter.
|
|
217
|
+
*/
|
|
218
|
+
function mark(scope) {
|
|
219
|
+
scope.find(NODES).addBack(NODES).each(function() {
|
|
220
|
+
var node = $(this);
|
|
221
|
+
var drawer = node.children('.ge-tools-drawer');
|
|
222
|
+
|
|
223
|
+
if (!drawer.length || !applies(node, ge.kindOf(node))) { return; }
|
|
224
|
+
|
|
225
|
+
if (carries(node, 'p')) {
|
|
226
|
+
var style = getComputedStyle(node[0]);
|
|
227
|
+
|
|
228
|
+
drawer.css({
|
|
229
|
+
marginTop: '-' + style.paddingTop,
|
|
230
|
+
marginLeft: '-' + style.paddingLeft,
|
|
231
|
+
marginRight: '-' + style.paddingRight,
|
|
232
|
+
width: 'calc(100% + ' + style.paddingLeft + ' + ' + style.paddingRight + ')',
|
|
233
|
+
});
|
|
234
|
+
} else {
|
|
235
|
+
drawer.css({ marginTop: '', marginLeft: '', marginRight: '', width: '' });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (node.hasClass('column')) {
|
|
239
|
+
drawer.find('.ge-spacing-gutter').toggle(classes(node).some(function(name) {
|
|
240
|
+
return /^p[xse]?-/.test(name) && patterns.p.test(name);
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function families(key, labelKey) {
|
|
247
|
+
var values = key === 'm' ? VALUES.concat(['auto']) : VALUES;
|
|
248
|
+
var offered = options.values.concat(key === 'm' ? ['auto'] : []);
|
|
249
|
+
|
|
250
|
+
return SIDES.map(function(side) {
|
|
251
|
+
return {
|
|
252
|
+
name: key + side,
|
|
253
|
+
prefix: key + side,
|
|
254
|
+
values: values,
|
|
255
|
+
appliesTo: ['row', 'column', 'element', 'container'],
|
|
256
|
+
labelKey: labelKey,
|
|
257
|
+
panel: false,
|
|
258
|
+
choices: function() {
|
|
259
|
+
return values.filter(function(value) { return offered.indexOf(value) !== -1; });
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
families: families('p', 'utility.padding').concat(families('m', 'utility.margin')),
|
|
267
|
+
|
|
268
|
+
panel: function(node, kind) {
|
|
269
|
+
if (!applies(node, kind)) { return null; }
|
|
270
|
+
|
|
271
|
+
var box = $('<div class="ge-spacing" />')
|
|
272
|
+
.append(group(node, 'p', ge.t('utility.padding')))
|
|
273
|
+
.append(group(node, 'm', ge.t('utility.margin')))
|
|
274
|
+
;
|
|
275
|
+
|
|
276
|
+
if (kind === 'column') {
|
|
277
|
+
$('<small class="ge-spacing-gutter" />').text(ge.t('utility.spacing_gutter')).appendTo(box);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return box;
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
preview: function(node, kind, breakpoint) {
|
|
284
|
+
if (!applies(node, kind)) { return {}; }
|
|
285
|
+
|
|
286
|
+
var styles = {};
|
|
287
|
+
|
|
288
|
+
['p', 'm'].forEach(function(key) {
|
|
289
|
+
if (carries(node, key)) { $.extend(styles, sides(node, key, breakpoint)); }
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
return styles;
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
onRefresh: mark,
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
})(jQuery);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text alignment for grid-editor.
|
|
3
|
+
*
|
|
4
|
+
* A utility plugin: load this file after the editor and a row, column,
|
|
5
|
+
* element or container can align its text per breakpoint, with Bootstrap's
|
|
6
|
+
* text-{breakpoint}-start, -center and -end classes. What it can ask the
|
|
7
|
+
* editor for is the handle its factory is called with, described in
|
|
8
|
+
* docs/plugins.md.
|
|
9
|
+
*
|
|
10
|
+
* <script src="dist/jquery.grideditor.min.js"></script>
|
|
11
|
+
* <script src="dist/plugins/grideditor.textalign.min.js"></script>
|
|
12
|
+
*
|
|
13
|
+
* The class aligns everything inside the node that does not align itself: a
|
|
14
|
+
* paragraph the rich text editor gave its own text-align keeps it.
|
|
15
|
+
*/
|
|
16
|
+
(function($) {
|
|
17
|
+
|
|
18
|
+
$.extend($.fn.gridEditor.locales.en, {
|
|
19
|
+
'utility.text_align': 'Text alignment',
|
|
20
|
+
'utility.text_start': 'Start',
|
|
21
|
+
'utility.text_center': 'Center',
|
|
22
|
+
'utility.text_end': 'End',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/** Start and end are left and right: Bootstrap's css is left to right. */
|
|
26
|
+
var CSS = { start: 'left', center: 'center', end: 'right' };
|
|
27
|
+
|
|
28
|
+
$.fn.gridEditor.utilities.textalign = function(ge) {
|
|
29
|
+
|
|
30
|
+
function label(value) {
|
|
31
|
+
if (value === 'start') { return ge.t('utility.text_start'); }
|
|
32
|
+
if (value === 'center') { return ge.t('utility.text_center'); }
|
|
33
|
+
|
|
34
|
+
return ge.t('utility.text_end');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
families: [{
|
|
39
|
+
name: 'text-align',
|
|
40
|
+
prefix: 'text',
|
|
41
|
+
values: ['start', 'center', 'end'],
|
|
42
|
+
appliesTo: ['row', 'column', 'element', 'container'],
|
|
43
|
+
labelKey: 'utility.text_align',
|
|
44
|
+
label: label,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* With no class applying here, the node aligns as its parent
|
|
48
|
+
* does - or as the host's css says - which only the browser can
|
|
49
|
+
* tell, so it is asked with the classes out of the way. Parents
|
|
50
|
+
* are previewed before their children, so the parent's answer is
|
|
51
|
+
* already the view's.
|
|
52
|
+
*/
|
|
53
|
+
preview: function(value, node) {
|
|
54
|
+
return { 'text-align': value === null ? ge.bareStyle(node, 'text-align', 'text-align') : CSS[value] };
|
|
55
|
+
},
|
|
56
|
+
}],
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
})(jQuery);
|