@themarioga/grid-editor 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/AUTO_SAVE.md +30 -0
  2. package/BUILDING.md +68 -0
  3. package/CHANGELOG.md +362 -0
  4. package/LICENSE +23 -0
  5. package/README.md +521 -0
  6. package/UPGRADING.md +88 -0
  7. package/dist/grideditor.css +3875 -0
  8. package/dist/grideditor.min.css +2 -0
  9. package/dist/grideditor.min.css.map +1 -0
  10. package/dist/jquery.grideditor.js +2996 -0
  11. package/dist/jquery.grideditor.min.js +2 -0
  12. package/dist/jquery.grideditor.min.js.map +1 -0
  13. package/dist/locales/grideditor.es.js +74 -0
  14. package/dist/locales/grideditor.es.min.js +2 -0
  15. package/dist/locales/grideditor.es.min.js.map +1 -0
  16. package/dist/plugins/grideditor.accordion.js +185 -0
  17. package/dist/plugins/grideditor.accordion.min.js +2 -0
  18. package/dist/plugins/grideditor.accordion.min.js.map +1 -0
  19. package/dist/plugins/grideditor.elements.js +141 -0
  20. package/dist/plugins/grideditor.elements.min.js +2 -0
  21. package/dist/plugins/grideditor.elements.min.js.map +1 -0
  22. package/dist/plugins/grideditor.popup.js +143 -0
  23. package/dist/plugins/grideditor.popup.min.js +2 -0
  24. package/dist/plugins/grideditor.popup.min.js.map +1 -0
  25. package/dist/plugins/grideditor.tabs.js +140 -0
  26. package/dist/plugins/grideditor.tabs.min.js +2 -0
  27. package/dist/plugins/grideditor.tabs.min.js.map +1 -0
  28. package/docs/events.md +158 -0
  29. package/docs/locale-keys.md +140 -0
  30. package/docs/plugins.md +163 -0
  31. package/example/autosave.html +89 -0
  32. package/example/basic.html +93 -0
  33. package/example/breakpoints.html +94 -0
  34. package/example/ckeditor.html +104 -0
  35. package/example/containers.html +214 -0
  36. package/example/elements.html +147 -0
  37. package/example/index.html +119 -0
  38. package/example/locale.html +84 -0
  39. package/example/plugins.html +217 -0
  40. package/example/summernote.html +106 -0
  41. package/example/wrap_content.html +44 -0
  42. package/package.json +66 -0
  43. package/src/js/jquery.grideditor.ckeditor.js +77 -0
  44. package/src/js/jquery.grideditor.js +2711 -0
  45. package/src/js/jquery.grideditor.summernote.js +72 -0
  46. package/src/js/jquery.grideditor.tinymce.js +135 -0
  47. package/src/js/locales/grideditor.es.js +74 -0
  48. package/src/js/plugins/grideditor.accordion.js +185 -0
  49. package/src/js/plugins/grideditor.elements.js +141 -0
  50. package/src/js/plugins/grideditor.popup.js +143 -0
  51. package/src/js/plugins/grideditor.tabs.js +140 -0
  52. package/src/less/grideditor.less +594 -0
@@ -0,0 +1,594 @@
1
+ @editGutter: 5px;
2
+ @drawerHeight: 32px;
3
+ @rowTextColor: #666;
4
+ @colColor: #2FA4E7;
5
+ @colTextColor: darken(@colColor, 10%);
6
+ @elementColor: #7B5EA7;
7
+ @elementTextColor: darken(@elementColor, 5%);
8
+ @containerColor: #1D8A5E;
9
+ @containerTextColor: darken(@containerColor, 5%);
10
+
11
+ .ge-mainControls {
12
+ position: relative;
13
+ min-height: 22px;
14
+ margin-bottom: 10px;
15
+
16
+ .ge-wrapper {
17
+ padding-top: 5px;
18
+ }
19
+ .ge-wrapper.ge-top {
20
+ .container {
21
+ margin: 0;
22
+ padding: 0;
23
+ width: auto;
24
+ }
25
+ }
26
+ .ge-wrapper.ge-fixed {
27
+ position: fixed;
28
+ z-index: 20;
29
+ top: 0;
30
+ }
31
+
32
+ .ge-addRowGroup {
33
+ .btn.btn-primary {
34
+ background: #f4f4f4;
35
+ color: @rowTextColor;
36
+ border-color: #999;
37
+ display: flex;
38
+ align-items: center;
39
+
40
+ &:hover {
41
+ background: #E3E3E3;
42
+ }
43
+ }
44
+
45
+ .ge-row-icon {
46
+ width: 48px;
47
+ margin: 0;
48
+
49
+ .column {
50
+ height: 10px;
51
+ background: #666;
52
+ padding: 0;
53
+ border-left: 2px solid #f4f4f4;
54
+ }
55
+ }
56
+ }
57
+
58
+ .ge-layout-mode {
59
+ margin-left: 5px;
60
+ }
61
+
62
+ .btn:focus {
63
+ box-shadow: none;
64
+ outline: none;
65
+ }
66
+
67
+ .pull-right {
68
+ float: right;
69
+ }
70
+
71
+ .dropdown-menu a {
72
+ cursor: default;
73
+ }
74
+ }
75
+
76
+ .ge-html-output {
77
+ width: 100%;
78
+ display: none;
79
+ }
80
+
81
+ /* Not editing */
82
+ .ge-canvas {
83
+ .ge-tools-drawer {
84
+ display: none;
85
+ }
86
+ }
87
+
88
+ /* While a toolbar button is in the air, the canvas opens up: the gap between
89
+ two rows is where a drop lands at canvas level instead of inside a column,
90
+ and it is otherwise too thin to aim at */
91
+ .ge-canvas.ge-editing.ge-dropping {
92
+ > .row {
93
+ margin-bottom: 24px;
94
+ }
95
+ .column > .row {
96
+ margin-bottom: 20px;
97
+ }
98
+
99
+ /* Where the block would land */
100
+ .ge-drop-marker {
101
+ height: 6px;
102
+ margin: 4px 0;
103
+ border-radius: 3px;
104
+ background: @colColor;
105
+ }
106
+ }
107
+
108
+ /* The button following the pointer must not be what the pointer is over */
109
+ .ge-toolbar-helper {
110
+ pointer-events: none;
111
+ opacity: 0.85;
112
+ }
113
+
114
+ /* Dragging by the whole drawer rather than by the move tool */
115
+ .ge-canvas.ge-editing.ge-drag-drawer {
116
+ .ge-tools-drawer {
117
+ cursor: move;
118
+ }
119
+ /* The tools in it are still tools, and do not start a drag */
120
+ .ge-tools-drawer > a,
121
+ .ge-tools-drawer .ge-details {
122
+ cursor: pointer;
123
+ }
124
+ .ge-tools-drawer .ge-details {
125
+ cursor: auto;
126
+ }
127
+ }
128
+
129
+ /* While editing */
130
+ .ge-canvas.ge-editing {
131
+
132
+ .ge-tools-drawer {
133
+ /* Positioned, so a tool can hang a picker off itself. Deliberately
134
+ not stacked above anything the rest of the time: jQuery UI's resize
135
+ handle carries an inline z-index of 90 and runs down the column's
136
+ edge, and a drawer sitting over it would take the clicks meant for
137
+ the handle. */
138
+ position: relative;
139
+ -webkit-touch-callout: none;
140
+
141
+ /* While one of its tools is offering a choice, this drawer is the one
142
+ that matters - above the handles, and above the drawers below it */
143
+ &.ge-picker-open {
144
+ z-index: 200;
145
+ }
146
+ -webkit-user-select: none;
147
+ -moz-user-select: none;
148
+ -ms-user-select: none;
149
+ user-select: none;
150
+ background: blue;
151
+ margin: 0 -@editGutter @editGutter;
152
+ display: block;
153
+ width: calc(~"100% +" 2 * @editGutter);
154
+
155
+ > a {
156
+ display: inline-block;
157
+ padding: 5px;
158
+
159
+ }
160
+ > a:hover {
161
+ background: rgba(255, 255, 255, 0.5);
162
+ cursor: pointer;
163
+ }
164
+ .ge-details {
165
+ padding: 5px;
166
+ border-top: 1px solid rgba(0,0,0,0.05);
167
+ display: none;
168
+
169
+ .btn-group {
170
+ a {
171
+ color: #333;
172
+
173
+ &.active {
174
+ color: white;
175
+ }
176
+ }
177
+ a:hover {
178
+ text-decoration: none;
179
+ cursor: pointer;
180
+ }
181
+ }
182
+ input.ge-id,
183
+ input.ge-classes {
184
+ border: 1px solid #7F7F7F;
185
+ border-radius: 4px;
186
+ font-size: 11px;
187
+ padding: 2px 5px;
188
+ margin-right: 5px;
189
+ width: 80px;
190
+ }
191
+ input.ge-classes {
192
+ width: 200px;
193
+ }
194
+ }
195
+ }
196
+ .row {
197
+ background-color: #efefef;
198
+ border: 1px solid rgb(153,153,153);
199
+ padding: 0 @editGutter @editGutter;
200
+ margin-bottom: @editGutter;
201
+ margin-left: 0;
202
+ margin-right: 0;
203
+
204
+ > .ge-tools-drawer {
205
+ > a {
206
+ color: #666;
207
+ }
208
+ > a.ge-add-column {
209
+ color: @colTextColor;
210
+ }
211
+ // background: rgba(153,153,153,0.2);
212
+ background: #e5e5e5;
213
+ }
214
+ }
215
+ .column {
216
+ background-color: fadeout(@colColor, 85%);
217
+ border: 1px solid @colColor;
218
+ padding: 0 @editGutter @editGutter;
219
+ /* The resize handle is positioned against the column, so the column
220
+ has to be something to position against */
221
+ position: relative;
222
+
223
+ > .ge-tools-drawer {
224
+ a {
225
+ color: @colTextColor;
226
+ }
227
+ > a.ge-add-row {
228
+ color: @rowTextColor;
229
+ }
230
+ background: #afd5ea;
231
+ }
232
+ }
233
+
234
+ /* Content area */
235
+ .ge-content-type-tinymce.active {
236
+ outline: 1px dotted #333;
237
+ }
238
+
239
+ /* The column size picker, offered by holding the add column tool. It
240
+ hangs off the tool itself, so it comes away with the drawers */
241
+ .ge-tools-drawer > a {
242
+ position: relative;
243
+ }
244
+
245
+ .ge-size-picker {
246
+ position: absolute;
247
+ top: 100%;
248
+ left: 0;
249
+ z-index: 30;
250
+ display: flex;
251
+ flex-wrap: wrap;
252
+ width: 160px;
253
+ padding: 3px;
254
+ background: #fff;
255
+ border: 1px solid #999;
256
+ border-radius: 4px;
257
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
258
+
259
+ > .ge-size {
260
+ flex: 0 0 auto;
261
+ width: 26px;
262
+ margin: 1px;
263
+ padding: 4px 0;
264
+ text-align: center;
265
+ font-size: 11px;
266
+ line-height: 1;
267
+ text-decoration: none;
268
+ cursor: pointer;
269
+ color: @colTextColor;
270
+ background: fadeout(@colColor, 92%);
271
+ border: 1px solid fadeout(@colColor, 60%);
272
+ border-radius: 3px;
273
+
274
+ &:hover {
275
+ background: @colColor;
276
+ border-color: @colColor;
277
+ color: #fff;
278
+ }
279
+
280
+ /* Wider than what is left of the row: allowed, but said so */
281
+ &.ge-size-tight {
282
+ color: #999;
283
+ background: transparent;
284
+ border-style: dashed;
285
+ border-color: #ccc;
286
+ }
287
+ }
288
+ }
289
+
290
+ /* Containers: tabs, accordions and popups. A container sits in a column
291
+ beside the content areas, and each of its panes is an ordinary region */
292
+ .ge-container {
293
+ position: relative;
294
+ border: 1px solid @containerColor;
295
+ padding: 0 @editGutter @editGutter;
296
+ margin-bottom: @editGutter;
297
+
298
+ > .ge-container-drawer {
299
+ background: fadeout(@containerColor, 80%);
300
+
301
+ > a {
302
+ color: @containerTextColor;
303
+ }
304
+ }
305
+ }
306
+
307
+ /* A pane's own drawer is small and sits with its label rather than
308
+ above it: a tab strip is a row of tabs, not a stack of them */
309
+ .ge-pane-drawer {
310
+ display: inline-flex;
311
+ align-items: center;
312
+ width: auto;
313
+ margin: 0;
314
+ background: transparent;
315
+
316
+ > a {
317
+ padding: 2px 4px;
318
+ color: @containerTextColor;
319
+ }
320
+ }
321
+
322
+ .ge-tab {
323
+ display: flex;
324
+ align-items: center;
325
+
326
+ > .ge-pane-drawer {
327
+ padding-left: 4px;
328
+ }
329
+ .nav-link {
330
+ padding-left: 4px;
331
+ }
332
+ }
333
+
334
+ /* The label is edited in place, so it needs to look like it can be */
335
+ .ge-pane-label {
336
+ &:hover {
337
+ outline: 1px dotted @containerTextColor;
338
+ }
339
+ &[contenteditable="true"] {
340
+ outline: 1px solid @containerTextColor;
341
+ cursor: text;
342
+ }
343
+ }
344
+
345
+ .tab-content > .tab-pane {
346
+ padding: @editGutter 0;
347
+ }
348
+
349
+ /* Open and closed while editing is what the page will ship, which is what
350
+ data-ge-open says. Bootstrap's own collapse is not involved: its
351
+ javascript is never asked to run over the canvas, so the state is
352
+ driven from the attribute rather than from the .show class it animates */
353
+ .accordion-collapse[data-ge-open="true"] {
354
+ display: block;
355
+ }
356
+ .accordion-collapse[data-ge-open="false"] {
357
+ display: none;
358
+ }
359
+ .ge-accordion-item > .ge-pane-drawer {
360
+ padding: 2px 0;
361
+ }
362
+
363
+ /* A popup is rendered unfolded and in place: a plain block with its
364
+ body as an ordinary region. Bootstrap's modal JS is never asked to
365
+ open it, so there is no backdrop, no focus trap and no scroll lock */
366
+ .ge-container-popup {
367
+ .modal {
368
+ display: block;
369
+ position: static;
370
+ z-index: auto;
371
+ overflow: visible;
372
+ /* Bootstrap keeps a modal at opacity 0 and its dialog shifted up
373
+ until it adds .show, which only its own JS does. The editor
374
+ never asks it to, so the fade is undone here instead */
375
+ opacity: 1;
376
+ transition: none;
377
+ }
378
+ .modal-dialog {
379
+ margin: @editGutter 0;
380
+ max-width: none;
381
+ pointer-events: auto;
382
+ transform: none;
383
+ transition: none;
384
+ }
385
+ .modal-content {
386
+ box-shadow: none;
387
+ }
388
+ .ge-popup-trigger {
389
+ margin-bottom: @editGutter;
390
+ }
391
+
392
+ /* Folded away, for a page with several popups on it */
393
+ &.ge-popup-collapsed .modal {
394
+ display: none;
395
+ }
396
+ }
397
+
398
+ /* A trigger pointing at a popup that is not there any more */
399
+ .ge-popup-orphan {
400
+ outline: 2px dashed #d9534f;
401
+ }
402
+
403
+ /* Elements: the level below a column, inside a content area. Dashed
404
+ rather than solid, so a page full of them still reads as content */
405
+ .ge-element {
406
+ position: relative;
407
+ outline: 1px dashed @elementColor;
408
+ margin-bottom: @editGutter;
409
+ padding: 0 @editGutter;
410
+
411
+ > .ge-element-drawer {
412
+ background: fadeout(@elementColor, 85%);
413
+ margin: 0 -@editGutter @editGutter;
414
+ width: calc(~"100% +" 2 * @editGutter);
415
+
416
+ > a {
417
+ color: @elementTextColor;
418
+ padding: 2px 5px;
419
+ }
420
+ > a.ge-element-info {
421
+ cursor: default;
422
+ }
423
+ }
424
+ }
425
+
426
+ /* Sorting */
427
+ .ui-sortable-placeholder {
428
+ background: fadeout(yellow, 80%);
429
+ visibility: visible !important;
430
+ min-height: 50px;
431
+ max-height: 100px;
432
+ }
433
+
434
+ /* A size change should read as a movement rather than a jump, but not
435
+ while the pointer is dragging the edge: there the column follows the
436
+ pointer and a transition only lags behind it */
437
+ .column {
438
+ transition: width 120ms ease, margin-left 120ms ease;
439
+ }
440
+ .column.ui-resizable-resizing {
441
+ transition: none;
442
+ /* Follow the pointer in pixels: the layout mode's max-width is what
443
+ the column will snap back into once the drag lands */
444
+ max-width: none;
445
+ }
446
+
447
+ /* Resizing. jQuery UI's own stylesheet is not a dependency, so the handle
448
+ is styled here: a grip on the column's edge, clear of the drawer, which
449
+ is what keeps the resize gesture and the sort gesture apart */
450
+ .column > .ui-resizable-handle {
451
+ position: absolute;
452
+ display: block;
453
+ z-index: 10;
454
+ }
455
+ .column > .ui-resizable-e,
456
+ .column > .ui-resizable-w {
457
+ top: 0;
458
+ bottom: 0;
459
+ width: 8px;
460
+ cursor: ew-resize;
461
+ background: fadeout(@colColor, 70%);
462
+
463
+ &:hover {
464
+ background: @colColor;
465
+ }
466
+ }
467
+ .column > .ui-resizable-e {
468
+ right: -1px;
469
+ }
470
+ .column > .ui-resizable-w {
471
+ left: -1px;
472
+ }
473
+
474
+ /* The units the column would land on, shown in its drawer while dragging */
475
+ .ge-tools-drawer > .ge-resize-size {
476
+ display: none;
477
+ float: right;
478
+ padding: 5px;
479
+ font-size: 11px;
480
+ color: @colTextColor;
481
+ }
482
+ .column.ui-resizable-resizing > .ge-tools-drawer > .ge-resize-size {
483
+ display: block;
484
+ }
485
+ }
486
+
487
+ /* The handle belongs to editing, and never to the output */
488
+ .ge-canvas:not(.ge-editing) .ui-resizable-handle {
489
+ display: none;
490
+ }
491
+
492
+ /* Layout modes */
493
+
494
+ /*
495
+ * One row per Bootstrap 5 breakpoint, in the same order as the BREAKPOINTS
496
+ * table in the plugin. A layout mode previews one tier: the canvas is
497
+ * constrained to that tier's width, that tier's column and offset classes are
498
+ * made effective whatever the window is doing, and every other tier's classes
499
+ * are switched off - otherwise a wide window would keep showing the widest
500
+ * tier's classes no matter which mode is selected.
501
+ *
502
+ * The all view constrains nothing and switches nothing off: it renders the
503
+ * page as the browser would, which is the point of it.
504
+ */
505
+
506
+ @ge-tiers: xs, sm, md, lg, xl, xxl;
507
+ @ge-col-prefixes: col, col-sm, col-md, col-lg, col-xl, col-xxl;
508
+ @ge-offset-prefixes: offset, offset-sm, offset-md, offset-lg, offset-xl, offset-xxl;
509
+ @ge-previews: 400px, 576px, 768px, 992px, 1200px, none;
510
+ @ge-columns: 12;
511
+
512
+ .ge-canvas.ge-layout-all {
513
+ max-width: none;
514
+ }
515
+
516
+ .ge-layout-modes(@i: 1) when (@i =< length(@ge-tiers)) {
517
+ @tier: extract(@ge-tiers, @i);
518
+
519
+ .ge-canvas.ge-layout-@{tier} {
520
+ max-width: extract(@ge-previews, @i);
521
+ margin-left: auto;
522
+ margin-right: auto;
523
+
524
+ /* Wider tiers are switched off, then every tier up to and including
525
+ this one is switched on in ascending order. That reproduces
526
+ Bootstrap's own cascade inside the preview: a column carrying only
527
+ col-4 is four units wide at sm too, and col-sm-6 overrides it
528
+ because it is written afterwards. All these rules have the same
529
+ specificity, so the order they are written in is the rule. */
530
+ .ge-tiers-above-off(@i);
531
+ .ge-tiers-upto-on(@i);
532
+ }
533
+
534
+ .ge-layout-modes(@i + 1);
535
+ }
536
+
537
+ .ge-tiers-above-off(@active, @j: 1) when (@j =< length(@ge-tiers)) {
538
+ .ge-tier-above-off(@j, @active);
539
+ .ge-tiers-above-off(@active, @j + 1);
540
+ }
541
+ .ge-tier-above-off(@j, @active) when (@j =< @active) {
542
+ /* this tier applies at the active one, so it is written by the pass below */
543
+ }
544
+ .ge-tier-above-off(@j, @active) when (@j > @active) {
545
+ .ge-columns-off(extract(@ge-col-prefixes, @j));
546
+ .ge-offsets-off(extract(@ge-offset-prefixes, @j));
547
+ }
548
+
549
+ .ge-tiers-upto-on(@active, @j: 1) when (@j =< @active) {
550
+ .ge-columns-on(extract(@ge-col-prefixes, @j));
551
+ .ge-offsets-on(extract(@ge-offset-prefixes, @j));
552
+ .ge-tiers-upto-on(@active, @j + 1);
553
+ }
554
+
555
+ .ge-columns-on(@prefix, @i: 1) when (@i =< @ge-columns) {
556
+ .@{prefix}-@{i} {
557
+ flex: 0 0 auto;
558
+ width: percentage((@i / @ge-columns));
559
+ max-width: percentage((@i / @ge-columns));
560
+ }
561
+ .ge-columns-on(@prefix, (@i + 1));
562
+ }
563
+
564
+ /*
565
+ * Switching a tier off means giving the column back to bootstrap's default
566
+ * for a row child - full width, stacked - which is what a browser really
567
+ * shows for a column that says nothing about the tier being previewed.
568
+ * Leaving it at width auto sizes it to its content instead, and a column of
569
+ * text then runs straight out of a narrow canvas.
570
+ */
571
+ .ge-columns-off(@prefix, @i: 1) when (@i =< @ge-columns) {
572
+ .@{prefix}-@{i} {
573
+ flex: 0 0 auto;
574
+ width: 100%;
575
+ max-width: 100%;
576
+ }
577
+ .ge-columns-off(@prefix, (@i + 1));
578
+ }
579
+
580
+ .ge-offsets-on(@prefix, @i: 1) when (@i < @ge-columns) {
581
+ .@{prefix}-@{i} {
582
+ margin-left: percentage((@i / @ge-columns));
583
+ }
584
+ .ge-offsets-on(@prefix, (@i + 1));
585
+ }
586
+
587
+ .ge-offsets-off(@prefix, @i: 1) when (@i < @ge-columns) {
588
+ .@{prefix}-@{i} {
589
+ margin-left: 0;
590
+ }
591
+ .ge-offsets-off(@prefix, (@i + 1));
592
+ }
593
+
594
+ .ge-layout-modes();