@themarioga/grid-editor 8.7.0 → 8.8.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.
@@ -0,0 +1,775 @@
1
+ // src/js/plugins/grideditor.carousel.js
2
+ import { GridEditor } from "../grideditor.esm.js";
3
+
4
+ // src/js/dom.js
5
+ function all(root, selector) {
6
+ return root ? Array.prototype.slice.call(root.querySelectorAll(selector)) : [];
7
+ }
8
+ function children(node, selector) {
9
+ if (!node) {
10
+ return [];
11
+ }
12
+ return Array.prototype.filter.call(node.children, function(each) {
13
+ return !selector || each.matches(selector);
14
+ });
15
+ }
16
+ function child(node, selector) {
17
+ return children(node, selector)[0] || null;
18
+ }
19
+ function element(tag, attributes, text) {
20
+ var node = document.createElement(tag);
21
+ Object.keys(attributes || {}).forEach(function(name) {
22
+ var value = attributes[name];
23
+ if (value !== null && value !== void 0 && value !== false) {
24
+ node.setAttribute(name, value);
25
+ }
26
+ });
27
+ if (text !== void 0 && text !== null) {
28
+ node.textContent = text;
29
+ }
30
+ return node;
31
+ }
32
+ function addClass(node, names) {
33
+ split(names).forEach(function(name) {
34
+ node.classList.add(name);
35
+ });
36
+ return node;
37
+ }
38
+ function removeClass(node, names) {
39
+ split(names).forEach(function(name) {
40
+ node.classList.remove(name);
41
+ });
42
+ return node;
43
+ }
44
+ function toggleClass(node, names, state) {
45
+ split(names).forEach(function(name) {
46
+ if (state === void 0) {
47
+ node.classList.toggle(name);
48
+ } else {
49
+ node.classList.toggle(name, !!state);
50
+ }
51
+ });
52
+ return node;
53
+ }
54
+ function hasClass(node, name) {
55
+ return !!node && node.nodeType === 1 && node.classList.contains(name);
56
+ }
57
+ function split(names) {
58
+ return String(names || "").split(/\s+/).filter(Boolean);
59
+ }
60
+ function dropEmptyClass(node) {
61
+ if (!node.getAttribute("class")) {
62
+ node.removeAttribute("class");
63
+ }
64
+ return node;
65
+ }
66
+ function hide(node) {
67
+ node.style.display = "none";
68
+ return node;
69
+ }
70
+ function visible(node) {
71
+ return !!(node.offsetWidth || node.offsetHeight || node.getClientRects().length);
72
+ }
73
+ var DEFAULT_DURATION = 400;
74
+ function animateAway(node, frames, duration, done) {
75
+ duration = duration === void 0 ? DEFAULT_DURATION : duration;
76
+ var finish = function() {
77
+ hide(node);
78
+ if (done) {
79
+ done();
80
+ }
81
+ };
82
+ if (!visible(node) || !node.animate || duration <= 0) {
83
+ window.setTimeout(finish, 0);
84
+ return;
85
+ }
86
+ var animation = node.animate(frames(getComputedStyle(node)), {
87
+ duration,
88
+ easing: "ease-in-out"
89
+ });
90
+ var called = false;
91
+ var once = function() {
92
+ if (called) {
93
+ return;
94
+ }
95
+ called = true;
96
+ finish();
97
+ };
98
+ animation.onfinish = once;
99
+ animation.oncancel = once;
100
+ }
101
+ function fadeOut(node, duration, done) {
102
+ animateAway(node, function(style) {
103
+ return [{ opacity: style.opacity }, { opacity: 0 }];
104
+ }, duration, done);
105
+ }
106
+
107
+ // src/js/plugins/grideditor.carousel.js
108
+ Object.assign(GridEditor.locales.en, {
109
+ "container.add_carousel": "Carousel",
110
+ "container.add_carousel_item": "Add slide",
111
+ "confirm.delete_carousel_item": "Delete this slide and everything in it?",
112
+ "panel.kind_carousel_item": "Slide",
113
+ "container.carousel_previous": "Previous",
114
+ "container.carousel_next": "Next",
115
+ "container.carousel_slide_label": "Slide {number}",
116
+ "container.carousel_counter": "{current} / {total}",
117
+ "tool.carousel_show_previous": "Previous slide",
118
+ "tool.carousel_show_next": "Next slide",
119
+ "tool.carousel_move_back": "Move back",
120
+ "tool.carousel_move_forward": "Move forward",
121
+ "container.carousel_section": "Carousel",
122
+ "container.carousel_controls": "Arrows",
123
+ "container.carousel_indicators": "Indicators",
124
+ "container.carousel_fade": "Fade",
125
+ "container.carousel_dark": "Dark theme",
126
+ "container.carousel_ride": "Autoplay",
127
+ "container.carousel_ride_no": "No",
128
+ "container.carousel_ride_load": "On load",
129
+ "container.carousel_ride_interaction": "After first interaction",
130
+ "container.carousel_interval": "Interval (s)",
131
+ "container.carousel_pause": "Pause on hover",
132
+ "container.carousel_wrap": "Wrap around",
133
+ "container.carousel_keyboard": "Keyboard",
134
+ "container.carousel_touch": "Touch swipe",
135
+ "container.carousel_item_section": "Slide"
136
+ });
137
+ var DEFAULTS = {
138
+ controls: true,
139
+ indicators: true,
140
+ fade: false,
141
+ dark: false,
142
+ ride: false,
143
+ interval: null,
144
+ pause: true,
145
+ wrap: true,
146
+ keyboard: true,
147
+ touch: true,
148
+ slides: 2
149
+ };
150
+ var CHECKBOXES = ["controls", "indicators", "fade", "dark"];
151
+ var BEHAVIOURS = ["pause", "wrap", "keyboard", "touch"];
152
+ var LABELS = {
153
+ controls: { labelKey: "container.carousel_controls" },
154
+ indicators: { labelKey: "container.carousel_indicators" },
155
+ fade: { labelKey: "container.carousel_fade" },
156
+ dark: { labelKey: "container.carousel_dark" },
157
+ pause: { labelKey: "container.carousel_pause" },
158
+ wrap: { labelKey: "container.carousel_wrap" },
159
+ keyboard: { labelKey: "container.carousel_keyboard" },
160
+ touch: { labelKey: "container.carousel_touch" }
161
+ };
162
+ var RIDE_LABEL = { labelKey: "container.carousel_ride" };
163
+ var INTERVAL_LABEL = { labelKey: "container.carousel_interval" };
164
+ var RIDES = [false, "carousel", "true"];
165
+ var MIN_INTERVAL = 1e3;
166
+ var TRANSITION = "carousel-item-next carousel-item-prev carousel-item-start carousel-item-end";
167
+ function validInterval(value) {
168
+ return typeof value === "number" && isFinite(value) && Math.floor(value) === value && value >= MIN_INTERVAL;
169
+ }
170
+ var CHECKS = {
171
+ ride: function(value) {
172
+ return RIDES.indexOf(value) !== -1;
173
+ },
174
+ interval: function(value) {
175
+ return value === null || validInterval(value);
176
+ },
177
+ slides: function(value) {
178
+ return typeof value === "number" && Math.floor(value) === value && value >= 1;
179
+ }
180
+ };
181
+ function takes(key) {
182
+ if (key === "ride") {
183
+ return JSON.stringify(RIDES);
184
+ }
185
+ if (key === "interval") {
186
+ return "null or an integer of " + MIN_INTERVAL + " or more";
187
+ }
188
+ if (key === "slides") {
189
+ return "an integer of 1 or more";
190
+ }
191
+ return "[true,false]";
192
+ }
193
+ function isValid(key, value) {
194
+ return CHECKS[key] ? CHECKS[key](value) : typeof value === "boolean";
195
+ }
196
+ var fieldCounter = 0;
197
+ GridEditor.containers.carousel = function(ge) {
198
+ var shown = /* @__PURE__ */ new WeakMap();
199
+ var sections = [];
200
+ function carouselOf(container) {
201
+ return child(container, ".carousel");
202
+ }
203
+ function innerOf(container) {
204
+ return child(carouselOf(container), ".carousel-inner");
205
+ }
206
+ function usable(container) {
207
+ return !!innerOf(container);
208
+ }
209
+ function itemsOf(container) {
210
+ return children(innerOf(container), ".carousel-item");
211
+ }
212
+ function idOf(carousel) {
213
+ if (!carousel.getAttribute("id")) {
214
+ carousel.setAttribute("id", ge.containerId("carousel"));
215
+ }
216
+ return carousel.getAttribute("id");
217
+ }
218
+ function bsAttribute(node, name) {
219
+ var value = node.getAttribute("data-bs-" + name);
220
+ return value === null ? node.getAttribute("data-ge-bs-" + name) : value;
221
+ }
222
+ function intervalOf(node) {
223
+ var value = parseInt(node.getAttribute("data-bs-interval"), 10);
224
+ return isFinite(value) && value > 0 ? value : null;
225
+ }
226
+ function writeInterval(node, value) {
227
+ if (value === null) {
228
+ node.removeAttribute("data-bs-interval");
229
+ } else {
230
+ node.setAttribute("data-bs-interval", String(value));
231
+ }
232
+ }
233
+ function read(container) {
234
+ var carousel = carouselOf(container);
235
+ var ride = bsAttribute(carousel, "ride");
236
+ var off = function(name) {
237
+ return carousel.getAttribute("data-bs-" + name) !== "false";
238
+ };
239
+ return {
240
+ controls: !!child(carousel, ".carousel-control-prev, .carousel-control-next"),
241
+ indicators: !!child(carousel, ".carousel-indicators"),
242
+ fade: hasClass(carousel, "carousel-fade"),
243
+ dark: carousel.getAttribute("data-bs-theme") === "dark",
244
+ ride: ride === "carousel" || ride === "true" ? ride : false,
245
+ interval: intervalOf(carousel),
246
+ pause: off("pause"),
247
+ wrap: off("wrap"),
248
+ keyboard: off("keyboard"),
249
+ touch: off("touch")
250
+ };
251
+ }
252
+ function controlButton(carousel, direction) {
253
+ var button = element("button", {
254
+ "class": "carousel-control-" + direction,
255
+ type: "button",
256
+ "data-bs-target": "#" + idOf(carousel),
257
+ "data-bs-slide": direction
258
+ });
259
+ button.appendChild(element("span", { "class": "carousel-control-" + direction + "-icon", "aria-hidden": "true" }));
260
+ button.appendChild(element(
261
+ "span",
262
+ { "class": "visually-hidden" },
263
+ direction === "prev" ? ge.t("container.carousel_previous") : ge.t("container.carousel_next")
264
+ ));
265
+ return button;
266
+ }
267
+ function setControls(container, on) {
268
+ var carousel = carouselOf(container);
269
+ children(carousel, ".carousel-control-prev, .carousel-control-next").forEach(function(button) {
270
+ button.remove();
271
+ });
272
+ if (on) {
273
+ carousel.appendChild(controlButton(carousel, "prev"));
274
+ carousel.appendChild(controlButton(carousel, "next"));
275
+ }
276
+ }
277
+ function setIndicators(container, on) {
278
+ var carousel = carouselOf(container);
279
+ var bar = child(carousel, ".carousel-indicators");
280
+ if (!on) {
281
+ if (bar) {
282
+ bar.remove();
283
+ }
284
+ return;
285
+ }
286
+ if (!bar) {
287
+ bar = carousel.insertBefore(element("div", { "class": "carousel-indicators" }), carousel.firstChild);
288
+ }
289
+ rebuildIndicators(container);
290
+ }
291
+ function rebuildIndicators(container, list) {
292
+ var carousel = carouselOf(container);
293
+ var bar = child(carousel, ".carousel-indicators");
294
+ if (!bar) {
295
+ return;
296
+ }
297
+ list = list || itemsOf(container);
298
+ var id = idOf(carousel);
299
+ var active = 0;
300
+ list.forEach(function(item, index) {
301
+ if (hasClass(item, "active")) {
302
+ active = index;
303
+ }
304
+ });
305
+ bar.textContent = "";
306
+ list.forEach(function(item, index) {
307
+ bar.appendChild(element("button", {
308
+ type: "button",
309
+ "data-bs-target": "#" + id,
310
+ "data-bs-slide-to": String(index),
311
+ "aria-label": ge.t("container.carousel_slide_label", { number: index + 1 })
312
+ }));
313
+ });
314
+ syncIndicators(container, list.length ? active : -1);
315
+ }
316
+ function syncIndicators(container, index) {
317
+ var bar = child(carouselOf(container), ".carousel-indicators");
318
+ children(bar).forEach(function(indicator, position) {
319
+ toggleClass(indicator, "active", position === index);
320
+ if (position === index) {
321
+ indicator.setAttribute("aria-current", "true");
322
+ } else {
323
+ indicator.removeAttribute("aria-current");
324
+ }
325
+ });
326
+ }
327
+ function write(container, key, value) {
328
+ var carousel = carouselOf(container);
329
+ if (key === "controls") {
330
+ setControls(container, value);
331
+ }
332
+ if (key === "indicators") {
333
+ setIndicators(container, value);
334
+ }
335
+ if (key === "fade") {
336
+ toggleClass(carousel, "carousel-fade", value);
337
+ }
338
+ if (key === "dark") {
339
+ if (value) {
340
+ carousel.setAttribute("data-bs-theme", "dark");
341
+ } else if (carousel.getAttribute("data-bs-theme") === "dark") {
342
+ carousel.removeAttribute("data-bs-theme");
343
+ }
344
+ }
345
+ if (key === "ride") {
346
+ carousel.removeAttribute("data-bs-ride");
347
+ carousel.removeAttribute("data-ge-bs-ride");
348
+ if (value) {
349
+ carousel.setAttribute("data-bs-ride", value);
350
+ }
351
+ }
352
+ if (key === "interval") {
353
+ writeInterval(carousel, value);
354
+ }
355
+ if (BEHAVIOURS.indexOf(key) !== -1) {
356
+ if (value) {
357
+ carousel.removeAttribute("data-bs-" + key);
358
+ } else {
359
+ carousel.setAttribute("data-bs-" + key, "false");
360
+ }
361
+ }
362
+ dropEmptyClass(carousel);
363
+ }
364
+ function chosen(options, key) {
365
+ var setting = ge.settings.carousel || {};
366
+ var value = options[key] !== void 0 ? options[key] : setting[key];
367
+ if (value === void 0) {
368
+ return DEFAULTS[key];
369
+ }
370
+ if (isValid(key, value)) {
371
+ return value;
372
+ }
373
+ ge.warn("carousel: " + JSON.stringify(value) + " is not a " + key + ", which takes " + takes(key) + ": " + JSON.stringify(DEFAULTS[key]) + " is used");
374
+ return DEFAULTS[key];
375
+ }
376
+ function suspend(container) {
377
+ var carousel = carouselOf(container);
378
+ children(carousel, ".carousel-control-prev, .carousel-control-next").forEach(ge.suspendToggles);
379
+ children(child(carousel, ".carousel-indicators")).forEach(ge.suspendToggles);
380
+ var ride = carousel.getAttribute("data-bs-ride");
381
+ if (ride !== null) {
382
+ carousel.setAttribute("data-ge-bs-ride", ride);
383
+ carousel.removeAttribute("data-bs-ride");
384
+ }
385
+ }
386
+ function stopBootstrap(carousel) {
387
+ var library = GridEditor.bootstrap || window.bootstrap;
388
+ var instance = library && library.Carousel ? library.Carousel.getInstance(carousel) : null;
389
+ if (instance) {
390
+ instance.pause();
391
+ instance.dispose();
392
+ }
393
+ }
394
+ function buildItem(container, active, interval) {
395
+ var item = innerOf(container).appendChild(element("div", { "class": active ? "carousel-item active" : "carousel-item" }));
396
+ item.appendChild(ge.defaultRegion());
397
+ if (interval !== null && interval !== void 0) {
398
+ writeInterval(item, interval);
399
+ }
400
+ return item;
401
+ }
402
+ function currentOf(container) {
403
+ var list = itemsOf(container);
404
+ var kept = shown.get(container);
405
+ if (kept && list.indexOf(kept) !== -1) {
406
+ return kept;
407
+ }
408
+ return list.filter(function(item) {
409
+ return hasClass(item, "active");
410
+ })[0] || list[0] || null;
411
+ }
412
+ function show(container, item, list) {
413
+ list = list || itemsOf(container);
414
+ list.forEach(function(each) {
415
+ toggleClass(each, "active", each === item);
416
+ });
417
+ if (item) {
418
+ shown.set(container, item);
419
+ } else {
420
+ shown.delete(container);
421
+ }
422
+ syncIndicators(container, list.indexOf(item));
423
+ refreshNavigation(container);
424
+ }
425
+ function step(container, offset) {
426
+ var list = itemsOf(container);
427
+ if (list.length < 2) {
428
+ return;
429
+ }
430
+ var index = list.indexOf(currentOf(container));
431
+ show(container, list[(index + offset + list.length) % list.length]);
432
+ }
433
+ function disable(tool, state) {
434
+ if (!tool) {
435
+ return;
436
+ }
437
+ toggleClass(tool, "disabled", state);
438
+ if (state) {
439
+ tool.setAttribute("aria-disabled", "true");
440
+ } else {
441
+ tool.removeAttribute("aria-disabled");
442
+ }
443
+ }
444
+ function disabled(tool) {
445
+ return tool.getAttribute("aria-disabled") === "true";
446
+ }
447
+ function refreshNavigation(container) {
448
+ var list = itemsOf(container);
449
+ var drawer = child(container, ".ge-container-drawer");
450
+ var index = list.indexOf(currentOf(container));
451
+ if (drawer) {
452
+ var counter = child(drawer, ".ge-carousel-counter");
453
+ if (counter) {
454
+ counter.textContent = ge.t("container.carousel_counter", {
455
+ current: list.length ? index + 1 : 0,
456
+ total: list.length
457
+ });
458
+ }
459
+ disable(child(drawer, ".ge-carousel-previous"), list.length < 2);
460
+ disable(child(drawer, ".ge-carousel-next"), list.length < 2);
461
+ }
462
+ list.forEach(function(item, position) {
463
+ var tools = child(item, ".ge-pane-drawer");
464
+ disable(child(tools, ".ge-carousel-move-back"), position === 0);
465
+ disable(child(tools, ".ge-carousel-move-forward"), position === list.length - 1);
466
+ });
467
+ }
468
+ function moveItem(container, item, offset) {
469
+ var inner = innerOf(container);
470
+ var list = itemsOf(container);
471
+ var index = list.indexOf(item);
472
+ var target = index + offset;
473
+ if (target < 0 || target >= list.length) {
474
+ return;
475
+ }
476
+ var from = { parent: inner, index };
477
+ ge.operate(function() {
478
+ if (!ge.emit("before-move", ge.payloadFor("carousel-item", item, {
479
+ parent: inner,
480
+ source: "tool",
481
+ from
482
+ }))) {
483
+ return;
484
+ }
485
+ inner.insertBefore(item, offset < 0 ? list[target] : list[target].nextSibling);
486
+ show(container, currentOf(container));
487
+ rebuildIndicators(container);
488
+ suspend(container);
489
+ ge.emit("after-move", ge.payloadFor("carousel-item", item, {
490
+ parent: inner,
491
+ source: "tool",
492
+ from,
493
+ to: { parent: inner, index: target },
494
+ container
495
+ }));
496
+ });
497
+ }
498
+ function afterRemoving(container, item, removed) {
499
+ fadeOut(item, 200, function() {
500
+ var list = itemsOf(container);
501
+ var rest = list.filter(function(each) {
502
+ return each !== item;
503
+ });
504
+ if (currentOf(container) === item) {
505
+ show(container, rest[Math.min(list.indexOf(item), rest.length - 1)] || null, rest);
506
+ }
507
+ rebuildIndicators(container, rest);
508
+ removed();
509
+ });
510
+ }
511
+ function createItemControls(container, item) {
512
+ var drawer = ge.createPaneControls(
513
+ item,
514
+ "carousel-item",
515
+ ge.settings.carousel_tools,
516
+ ge.t("confirm.delete_carousel_item"),
517
+ function(removed) {
518
+ afterRemoving(container, item, removed);
519
+ }
520
+ );
521
+ var handle = child(drawer, ".ge-move");
522
+ if (handle) {
523
+ handle.remove();
524
+ }
525
+ var back = ge.createTool(drawer, ge.t("tool.carousel_move_back"), "ge-carousel-move-back", "bi bi-arrow-left", function() {
526
+ if (!disabled(this)) {
527
+ moveItem(container, item, -1);
528
+ }
529
+ });
530
+ var forward = ge.createTool(drawer, ge.t("tool.carousel_move_forward"), "ge-carousel-move-forward", "bi bi-arrow-right", function() {
531
+ if (!disabled(this)) {
532
+ moveItem(container, item, 1);
533
+ }
534
+ });
535
+ drawer.insertBefore(forward, drawer.firstChild);
536
+ drawer.insertBefore(back, forward);
537
+ }
538
+ function addSlideTo(container, options) {
539
+ options = options || {};
540
+ if (!usable(container)) {
541
+ ge.warn("carousel: there is no .carousel-inner to add a slide to");
542
+ return null;
543
+ }
544
+ var interval = null;
545
+ if (options.interval !== void 0 && options.interval !== null) {
546
+ if (validInterval(options.interval)) {
547
+ interval = options.interval;
548
+ } else {
549
+ ge.warn("carousel: " + JSON.stringify(options.interval) + " is not a interval, which takes " + takes("interval") + ": null is used");
550
+ }
551
+ }
552
+ var item = buildItem(container, false, interval);
553
+ show(container, item);
554
+ rebuildIndicators(container);
555
+ return item;
556
+ }
557
+ function field(labelKey, control, id) {
558
+ var box = element("div", { "class": "ge-carousel-option mb-2" });
559
+ box.appendChild(element("label", { "class": "form-label", "for": id }, ge.t(labelKey)));
560
+ box.appendChild(control);
561
+ return box;
562
+ }
563
+ function nextId() {
564
+ return "ge-carousel-option-" + ++fieldCounter;
565
+ }
566
+ function intervalField(node, onWrite) {
567
+ var id = nextId();
568
+ var input = element("input", {
569
+ "class": "form-control form-control-sm",
570
+ id,
571
+ type: "number",
572
+ step: "0.1",
573
+ min: String(MIN_INTERVAL / 1e3)
574
+ });
575
+ input.addEventListener("change", function() {
576
+ var text = input.value.trim();
577
+ var seconds = parseFloat(text);
578
+ if (text === "") {
579
+ removeClass(input, "is-invalid");
580
+ writeInterval(node, null);
581
+ } else if (!isFinite(seconds) || Math.round(seconds * 1e3) < MIN_INTERVAL) {
582
+ addClass(input, "is-invalid");
583
+ return;
584
+ } else {
585
+ removeClass(input, "is-invalid");
586
+ writeInterval(node, Math.round(seconds * 1e3));
587
+ }
588
+ if (onWrite) {
589
+ onWrite();
590
+ }
591
+ });
592
+ return {
593
+ id,
594
+ input,
595
+ render: function() {
596
+ var interval = intervalOf(node);
597
+ removeClass(input, "is-invalid");
598
+ input.value = interval === null ? "" : String(interval / 1e3);
599
+ }
600
+ };
601
+ }
602
+ function checkbox(labelKey, onChange) {
603
+ var id = nextId();
604
+ var box = element("div", { "class": "form-check" });
605
+ var input = box.appendChild(element("input", { "class": "form-check-input", type: "checkbox", id }));
606
+ box.appendChild(element("label", { "class": "form-check-label", "for": id }, ge.t(labelKey)));
607
+ input.addEventListener("change", function() {
608
+ onChange(input.checked);
609
+ });
610
+ return { box, input };
611
+ }
612
+ function createSection(container) {
613
+ var body = element("div", { "class": "ge-carousel-options" });
614
+ var inputs = {};
615
+ function change(key, value) {
616
+ write(container, key, value);
617
+ suspend(container);
618
+ render();
619
+ }
620
+ var rideId = nextId();
621
+ var ride = element("select", { "class": "form-select form-select-sm", id: rideId });
622
+ [
623
+ { value: "false", labelKey: "container.carousel_ride_no" },
624
+ { value: "carousel", labelKey: "container.carousel_ride_load" },
625
+ { value: "true", labelKey: "container.carousel_ride_interaction" }
626
+ ].forEach(function(choice) {
627
+ ride.appendChild(element("option", { value: choice.value }, ge.t(choice.labelKey)));
628
+ });
629
+ ride.addEventListener("change", function() {
630
+ change("ride", ride.value === "false" ? false : ride.value);
631
+ });
632
+ body.appendChild(field(RIDE_LABEL.labelKey, ride, rideId));
633
+ var interval = intervalField(carouselOf(container), function() {
634
+ render();
635
+ });
636
+ body.appendChild(field(INTERVAL_LABEL.labelKey, interval.input, interval.id));
637
+ CHECKBOXES.concat(BEHAVIOURS).forEach(function(key) {
638
+ var each = checkbox(LABELS[key].labelKey, function(on) {
639
+ change(key, on);
640
+ });
641
+ inputs[key] = each.input;
642
+ each.box.setAttribute("data-ge-carousel-option", key);
643
+ body.appendChild(each.box);
644
+ });
645
+ function render() {
646
+ var values = read(container);
647
+ ride.value = String(values.ride);
648
+ interval.render();
649
+ Object.keys(inputs).forEach(function(key) {
650
+ inputs[key].checked = values[key];
651
+ });
652
+ interval.input.disabled = values.ride === false;
653
+ inputs.pause.disabled = values.ride === false;
654
+ }
655
+ render();
656
+ sections.push({ node: container, element: body, render });
657
+ return body;
658
+ }
659
+ function createItemSection(item) {
660
+ var body = element("div", { "class": "ge-carousel-options" });
661
+ var interval = intervalField(item);
662
+ body.appendChild(field(INTERVAL_LABEL.labelKey, interval.input, interval.id));
663
+ interval.render();
664
+ sections.push({ node: item, element: body, render: interval.render });
665
+ return body;
666
+ }
667
+ return {
668
+ labelKey: "container.add_carousel",
669
+ addPaneKey: "container.add_carousel_item",
670
+ paneKind: "carousel-item",
671
+ paneClass: "ge-carousel-item",
672
+ paneLabelKey: "panel.kind_carousel_item",
673
+ /**
674
+ * `slides` slides, each a region, and the options of DEFAULTS as the
675
+ * call, the carousel setting or the defaults give them.
676
+ */
677
+ create: function(options) {
678
+ options = options || {};
679
+ var container = element("div", { "data-ge-container": "carousel" });
680
+ var carousel = container.appendChild(element("div", { "class": "carousel slide", id: ge.containerId("carousel") }));
681
+ var slides = chosen(options, "slides");
682
+ carousel.appendChild(element("div", { "class": "carousel-inner" }));
683
+ for (var i = 0; i < slides; i++) {
684
+ buildItem(container, i === 0);
685
+ }
686
+ Object.keys(DEFAULTS).filter(function(key) {
687
+ return key !== "slides";
688
+ }).forEach(function(key) {
689
+ write(container, key, chosen(options, key));
690
+ });
691
+ return container;
692
+ },
693
+ addPane: addSlideTo,
694
+ mark: function(container) {
695
+ var carousel = carouselOf(container);
696
+ if (!carousel || !usable(container)) {
697
+ return;
698
+ }
699
+ stopBootstrap(carousel);
700
+ suspend(container);
701
+ var current = currentOf(container);
702
+ itemsOf(container).forEach(function(item) {
703
+ addClass(item, "ge-carousel-item");
704
+ removeClass(item, TRANSITION);
705
+ if (!child(item, ".ge-tools-drawer")) {
706
+ createItemControls(container, item);
707
+ }
708
+ });
709
+ show(container, current);
710
+ },
711
+ unmark: function(container) {
712
+ ge.resumeToggles(container);
713
+ if (!usable(container)) {
714
+ return;
715
+ }
716
+ itemsOf(container).forEach(function(item, index) {
717
+ removeClass(item, "ge-carousel-item " + TRANSITION);
718
+ toggleClass(item, "active", index === 0);
719
+ dropEmptyClass(item);
720
+ });
721
+ syncIndicators(container, itemsOf(container).length ? 0 : -1);
722
+ },
723
+ // The same, on a copy of the canvas: unmark only touches markup
724
+ cleanMarkup: function(root) {
725
+ var definition = this;
726
+ all(root, '[data-ge-container="carousel"]').forEach(function(container) {
727
+ definition.unmark(container);
728
+ });
729
+ },
730
+ // The arrows, the counter and the arrow's other side: what moves the
731
+ // carousel from slide to slide while it is edited
732
+ tools: function(drawer, container) {
733
+ if (!usable(container)) {
734
+ return;
735
+ }
736
+ ge.createTool(drawer, ge.t("tool.carousel_show_previous"), "ge-carousel-previous", "bi bi-chevron-left", function() {
737
+ if (!disabled(this)) {
738
+ step(container, -1);
739
+ }
740
+ });
741
+ var counter = ge.createTool(drawer, "", "ge-carousel-counter", "", null);
742
+ counter.textContent = "";
743
+ counter.removeAttribute("title");
744
+ ge.createTool(drawer, ge.t("tool.carousel_show_next"), "ge-carousel-next", "bi bi-chevron-right", function() {
745
+ if (!disabled(this)) {
746
+ step(container, 1);
747
+ }
748
+ });
749
+ refreshNavigation(container);
750
+ },
751
+ panelSection: function(node, kind) {
752
+ if (kind === "carousel" && usable(node)) {
753
+ return { labelKey: "container.carousel_section", body: createSection(node) };
754
+ }
755
+ if (kind === "carousel-item") {
756
+ return { labelKey: "container.carousel_item_section", body: createItemSection(node) };
757
+ }
758
+ return null;
759
+ },
760
+ // After a view change or a change of classes: the sections follow
761
+ onRefresh: function(scope) {
762
+ sections = sections.filter(function(entry) {
763
+ return entry.element.isConnected;
764
+ });
765
+ sections.forEach(function(entry) {
766
+ if (entry.node === scope || scope.contains(entry.node)) {
767
+ entry.render();
768
+ }
769
+ });
770
+ },
771
+ onDeinit: function() {
772
+ sections = [];
773
+ }
774
+ };
775
+ };