cable_ready-element 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.
@@ -0,0 +1,1759 @@
1
+ var DOCUMENT_FRAGMENT_NODE = 11;
2
+
3
+ function morphAttrs(fromNode, toNode) {
4
+ var toNodeAttrs = toNode.attributes;
5
+ var attr;
6
+ var attrName;
7
+ var attrNamespaceURI;
8
+ var attrValue;
9
+ var fromValue;
10
+ if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
11
+ return;
12
+ }
13
+ for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
14
+ attr = toNodeAttrs[i];
15
+ attrName = attr.name;
16
+ attrNamespaceURI = attr.namespaceURI;
17
+ attrValue = attr.value;
18
+ if (attrNamespaceURI) {
19
+ attrName = attr.localName || attrName;
20
+ fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
21
+ if (fromValue !== attrValue) {
22
+ if (attr.prefix === "xmlns") {
23
+ attrName = attr.name;
24
+ }
25
+ fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
26
+ }
27
+ } else {
28
+ fromValue = fromNode.getAttribute(attrName);
29
+ if (fromValue !== attrValue) {
30
+ fromNode.setAttribute(attrName, attrValue);
31
+ }
32
+ }
33
+ }
34
+ var fromNodeAttrs = fromNode.attributes;
35
+ for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
36
+ attr = fromNodeAttrs[d];
37
+ attrName = attr.name;
38
+ attrNamespaceURI = attr.namespaceURI;
39
+ if (attrNamespaceURI) {
40
+ attrName = attr.localName || attrName;
41
+ if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
42
+ fromNode.removeAttributeNS(attrNamespaceURI, attrName);
43
+ }
44
+ } else {
45
+ if (!toNode.hasAttribute(attrName)) {
46
+ fromNode.removeAttribute(attrName);
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ var range;
53
+
54
+ var NS_XHTML = "http://www.w3.org/1999/xhtml";
55
+
56
+ var doc = typeof document === "undefined" ? undefined : document;
57
+
58
+ var HAS_TEMPLATE_SUPPORT = !!doc && "content" in doc.createElement("template");
59
+
60
+ var HAS_RANGE_SUPPORT = !!doc && doc.createRange && "createContextualFragment" in doc.createRange();
61
+
62
+ function createFragmentFromTemplate(str) {
63
+ var template = doc.createElement("template");
64
+ template.innerHTML = str;
65
+ return template.content.childNodes[0];
66
+ }
67
+
68
+ function createFragmentFromRange(str) {
69
+ if (!range) {
70
+ range = doc.createRange();
71
+ range.selectNode(doc.body);
72
+ }
73
+ var fragment = range.createContextualFragment(str);
74
+ return fragment.childNodes[0];
75
+ }
76
+
77
+ function createFragmentFromWrap(str) {
78
+ var fragment = doc.createElement("body");
79
+ fragment.innerHTML = str;
80
+ return fragment.childNodes[0];
81
+ }
82
+
83
+ function toElement(str) {
84
+ str = str.trim();
85
+ if (HAS_TEMPLATE_SUPPORT) {
86
+ return createFragmentFromTemplate(str);
87
+ } else if (HAS_RANGE_SUPPORT) {
88
+ return createFragmentFromRange(str);
89
+ }
90
+ return createFragmentFromWrap(str);
91
+ }
92
+
93
+ function compareNodeNames(fromEl, toEl) {
94
+ var fromNodeName = fromEl.nodeName;
95
+ var toNodeName = toEl.nodeName;
96
+ var fromCodeStart, toCodeStart;
97
+ if (fromNodeName === toNodeName) {
98
+ return true;
99
+ }
100
+ fromCodeStart = fromNodeName.charCodeAt(0);
101
+ toCodeStart = toNodeName.charCodeAt(0);
102
+ if (fromCodeStart <= 90 && toCodeStart >= 97) {
103
+ return fromNodeName === toNodeName.toUpperCase();
104
+ } else if (toCodeStart <= 90 && fromCodeStart >= 97) {
105
+ return toNodeName === fromNodeName.toUpperCase();
106
+ } else {
107
+ return false;
108
+ }
109
+ }
110
+
111
+ function createElementNS(name, namespaceURI) {
112
+ return !namespaceURI || namespaceURI === NS_XHTML ? doc.createElement(name) : doc.createElementNS(namespaceURI, name);
113
+ }
114
+
115
+ function moveChildren(fromEl, toEl) {
116
+ var curChild = fromEl.firstChild;
117
+ while (curChild) {
118
+ var nextChild = curChild.nextSibling;
119
+ toEl.appendChild(curChild);
120
+ curChild = nextChild;
121
+ }
122
+ return toEl;
123
+ }
124
+
125
+ function syncBooleanAttrProp(fromEl, toEl, name) {
126
+ if (fromEl[name] !== toEl[name]) {
127
+ fromEl[name] = toEl[name];
128
+ if (fromEl[name]) {
129
+ fromEl.setAttribute(name, "");
130
+ } else {
131
+ fromEl.removeAttribute(name);
132
+ }
133
+ }
134
+ }
135
+
136
+ var specialElHandlers = {
137
+ OPTION: function(fromEl, toEl) {
138
+ var parentNode = fromEl.parentNode;
139
+ if (parentNode) {
140
+ var parentName = parentNode.nodeName.toUpperCase();
141
+ if (parentName === "OPTGROUP") {
142
+ parentNode = parentNode.parentNode;
143
+ parentName = parentNode && parentNode.nodeName.toUpperCase();
144
+ }
145
+ if (parentName === "SELECT" && !parentNode.hasAttribute("multiple")) {
146
+ if (fromEl.hasAttribute("selected") && !toEl.selected) {
147
+ fromEl.setAttribute("selected", "selected");
148
+ fromEl.removeAttribute("selected");
149
+ }
150
+ parentNode.selectedIndex = -1;
151
+ }
152
+ }
153
+ syncBooleanAttrProp(fromEl, toEl, "selected");
154
+ },
155
+ INPUT: function(fromEl, toEl) {
156
+ syncBooleanAttrProp(fromEl, toEl, "checked");
157
+ syncBooleanAttrProp(fromEl, toEl, "disabled");
158
+ if (fromEl.value !== toEl.value) {
159
+ fromEl.value = toEl.value;
160
+ }
161
+ if (!toEl.hasAttribute("value")) {
162
+ fromEl.removeAttribute("value");
163
+ }
164
+ },
165
+ TEXTAREA: function(fromEl, toEl) {
166
+ var newValue = toEl.value;
167
+ if (fromEl.value !== newValue) {
168
+ fromEl.value = newValue;
169
+ }
170
+ var firstChild = fromEl.firstChild;
171
+ if (firstChild) {
172
+ var oldValue = firstChild.nodeValue;
173
+ if (oldValue == newValue || !newValue && oldValue == fromEl.placeholder) {
174
+ return;
175
+ }
176
+ firstChild.nodeValue = newValue;
177
+ }
178
+ },
179
+ SELECT: function(fromEl, toEl) {
180
+ if (!toEl.hasAttribute("multiple")) {
181
+ var selectedIndex = -1;
182
+ var i = 0;
183
+ var curChild = fromEl.firstChild;
184
+ var optgroup;
185
+ var nodeName;
186
+ while (curChild) {
187
+ nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
188
+ if (nodeName === "OPTGROUP") {
189
+ optgroup = curChild;
190
+ curChild = optgroup.firstChild;
191
+ } else {
192
+ if (nodeName === "OPTION") {
193
+ if (curChild.hasAttribute("selected")) {
194
+ selectedIndex = i;
195
+ break;
196
+ }
197
+ i++;
198
+ }
199
+ curChild = curChild.nextSibling;
200
+ if (!curChild && optgroup) {
201
+ curChild = optgroup.nextSibling;
202
+ optgroup = null;
203
+ }
204
+ }
205
+ }
206
+ fromEl.selectedIndex = selectedIndex;
207
+ }
208
+ }
209
+ };
210
+
211
+ var ELEMENT_NODE = 1;
212
+
213
+ var DOCUMENT_FRAGMENT_NODE$1 = 11;
214
+
215
+ var TEXT_NODE = 3;
216
+
217
+ var COMMENT_NODE = 8;
218
+
219
+ function noop() {}
220
+
221
+ function defaultGetNodeKey(node) {
222
+ if (node) {
223
+ return node.getAttribute && node.getAttribute("id") || node.id;
224
+ }
225
+ }
226
+
227
+ function morphdomFactory(morphAttrs) {
228
+ return function morphdom(fromNode, toNode, options) {
229
+ if (!options) {
230
+ options = {};
231
+ }
232
+ if (typeof toNode === "string") {
233
+ if (fromNode.nodeName === "#document" || fromNode.nodeName === "HTML" || fromNode.nodeName === "BODY") {
234
+ var toNodeHtml = toNode;
235
+ toNode = doc.createElement("html");
236
+ toNode.innerHTML = toNodeHtml;
237
+ } else {
238
+ toNode = toElement(toNode);
239
+ }
240
+ }
241
+ var getNodeKey = options.getNodeKey || defaultGetNodeKey;
242
+ var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
243
+ var onNodeAdded = options.onNodeAdded || noop;
244
+ var onBeforeElUpdated = options.onBeforeElUpdated || noop;
245
+ var onElUpdated = options.onElUpdated || noop;
246
+ var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
247
+ var onNodeDiscarded = options.onNodeDiscarded || noop;
248
+ var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
249
+ var childrenOnly = options.childrenOnly === true;
250
+ var fromNodesLookup = Object.create(null);
251
+ var keyedRemovalList = [];
252
+ function addKeyedRemoval(key) {
253
+ keyedRemovalList.push(key);
254
+ }
255
+ function walkDiscardedChildNodes(node, skipKeyedNodes) {
256
+ if (node.nodeType === ELEMENT_NODE) {
257
+ var curChild = node.firstChild;
258
+ while (curChild) {
259
+ var key = undefined;
260
+ if (skipKeyedNodes && (key = getNodeKey(curChild))) {
261
+ addKeyedRemoval(key);
262
+ } else {
263
+ onNodeDiscarded(curChild);
264
+ if (curChild.firstChild) {
265
+ walkDiscardedChildNodes(curChild, skipKeyedNodes);
266
+ }
267
+ }
268
+ curChild = curChild.nextSibling;
269
+ }
270
+ }
271
+ }
272
+ function removeNode(node, parentNode, skipKeyedNodes) {
273
+ if (onBeforeNodeDiscarded(node) === false) {
274
+ return;
275
+ }
276
+ if (parentNode) {
277
+ parentNode.removeChild(node);
278
+ }
279
+ onNodeDiscarded(node);
280
+ walkDiscardedChildNodes(node, skipKeyedNodes);
281
+ }
282
+ function indexTree(node) {
283
+ if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
284
+ var curChild = node.firstChild;
285
+ while (curChild) {
286
+ var key = getNodeKey(curChild);
287
+ if (key) {
288
+ fromNodesLookup[key] = curChild;
289
+ }
290
+ indexTree(curChild);
291
+ curChild = curChild.nextSibling;
292
+ }
293
+ }
294
+ }
295
+ indexTree(fromNode);
296
+ function handleNodeAdded(el) {
297
+ onNodeAdded(el);
298
+ var curChild = el.firstChild;
299
+ while (curChild) {
300
+ var nextSibling = curChild.nextSibling;
301
+ var key = getNodeKey(curChild);
302
+ if (key) {
303
+ var unmatchedFromEl = fromNodesLookup[key];
304
+ if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
305
+ curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
306
+ morphEl(unmatchedFromEl, curChild);
307
+ } else {
308
+ handleNodeAdded(curChild);
309
+ }
310
+ } else {
311
+ handleNodeAdded(curChild);
312
+ }
313
+ curChild = nextSibling;
314
+ }
315
+ }
316
+ function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
317
+ while (curFromNodeChild) {
318
+ var fromNextSibling = curFromNodeChild.nextSibling;
319
+ if (curFromNodeKey = getNodeKey(curFromNodeChild)) {
320
+ addKeyedRemoval(curFromNodeKey);
321
+ } else {
322
+ removeNode(curFromNodeChild, fromEl, true);
323
+ }
324
+ curFromNodeChild = fromNextSibling;
325
+ }
326
+ }
327
+ function morphEl(fromEl, toEl, childrenOnly) {
328
+ var toElKey = getNodeKey(toEl);
329
+ if (toElKey) {
330
+ delete fromNodesLookup[toElKey];
331
+ }
332
+ if (!childrenOnly) {
333
+ if (onBeforeElUpdated(fromEl, toEl) === false) {
334
+ return;
335
+ }
336
+ morphAttrs(fromEl, toEl);
337
+ onElUpdated(fromEl);
338
+ if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
339
+ return;
340
+ }
341
+ }
342
+ if (fromEl.nodeName !== "TEXTAREA") {
343
+ morphChildren(fromEl, toEl);
344
+ } else {
345
+ specialElHandlers.TEXTAREA(fromEl, toEl);
346
+ }
347
+ }
348
+ function morphChildren(fromEl, toEl) {
349
+ var curToNodeChild = toEl.firstChild;
350
+ var curFromNodeChild = fromEl.firstChild;
351
+ var curToNodeKey;
352
+ var curFromNodeKey;
353
+ var fromNextSibling;
354
+ var toNextSibling;
355
+ var matchingFromEl;
356
+ outer: while (curToNodeChild) {
357
+ toNextSibling = curToNodeChild.nextSibling;
358
+ curToNodeKey = getNodeKey(curToNodeChild);
359
+ while (curFromNodeChild) {
360
+ fromNextSibling = curFromNodeChild.nextSibling;
361
+ if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
362
+ curToNodeChild = toNextSibling;
363
+ curFromNodeChild = fromNextSibling;
364
+ continue outer;
365
+ }
366
+ curFromNodeKey = getNodeKey(curFromNodeChild);
367
+ var curFromNodeType = curFromNodeChild.nodeType;
368
+ var isCompatible = undefined;
369
+ if (curFromNodeType === curToNodeChild.nodeType) {
370
+ if (curFromNodeType === ELEMENT_NODE) {
371
+ if (curToNodeKey) {
372
+ if (curToNodeKey !== curFromNodeKey) {
373
+ if (matchingFromEl = fromNodesLookup[curToNodeKey]) {
374
+ if (fromNextSibling === matchingFromEl) {
375
+ isCompatible = false;
376
+ } else {
377
+ fromEl.insertBefore(matchingFromEl, curFromNodeChild);
378
+ if (curFromNodeKey) {
379
+ addKeyedRemoval(curFromNodeKey);
380
+ } else {
381
+ removeNode(curFromNodeChild, fromEl, true);
382
+ }
383
+ curFromNodeChild = matchingFromEl;
384
+ }
385
+ } else {
386
+ isCompatible = false;
387
+ }
388
+ }
389
+ } else if (curFromNodeKey) {
390
+ isCompatible = false;
391
+ }
392
+ isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
393
+ if (isCompatible) {
394
+ morphEl(curFromNodeChild, curToNodeChild);
395
+ }
396
+ } else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
397
+ isCompatible = true;
398
+ if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
399
+ curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
400
+ }
401
+ }
402
+ }
403
+ if (isCompatible) {
404
+ curToNodeChild = toNextSibling;
405
+ curFromNodeChild = fromNextSibling;
406
+ continue outer;
407
+ }
408
+ if (curFromNodeKey) {
409
+ addKeyedRemoval(curFromNodeKey);
410
+ } else {
411
+ removeNode(curFromNodeChild, fromEl, true);
412
+ }
413
+ curFromNodeChild = fromNextSibling;
414
+ }
415
+ if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
416
+ fromEl.appendChild(matchingFromEl);
417
+ morphEl(matchingFromEl, curToNodeChild);
418
+ } else {
419
+ var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
420
+ if (onBeforeNodeAddedResult !== false) {
421
+ if (onBeforeNodeAddedResult) {
422
+ curToNodeChild = onBeforeNodeAddedResult;
423
+ }
424
+ if (curToNodeChild.actualize) {
425
+ curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
426
+ }
427
+ fromEl.appendChild(curToNodeChild);
428
+ handleNodeAdded(curToNodeChild);
429
+ }
430
+ }
431
+ curToNodeChild = toNextSibling;
432
+ curFromNodeChild = fromNextSibling;
433
+ }
434
+ cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
435
+ var specialElHandler = specialElHandlers[fromEl.nodeName];
436
+ if (specialElHandler) {
437
+ specialElHandler(fromEl, toEl);
438
+ }
439
+ }
440
+ var morphedNode = fromNode;
441
+ var morphedNodeType = morphedNode.nodeType;
442
+ var toNodeType = toNode.nodeType;
443
+ if (!childrenOnly) {
444
+ if (morphedNodeType === ELEMENT_NODE) {
445
+ if (toNodeType === ELEMENT_NODE) {
446
+ if (!compareNodeNames(fromNode, toNode)) {
447
+ onNodeDiscarded(fromNode);
448
+ morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
449
+ }
450
+ } else {
451
+ morphedNode = toNode;
452
+ }
453
+ } else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) {
454
+ if (toNodeType === morphedNodeType) {
455
+ if (morphedNode.nodeValue !== toNode.nodeValue) {
456
+ morphedNode.nodeValue = toNode.nodeValue;
457
+ }
458
+ return morphedNode;
459
+ } else {
460
+ morphedNode = toNode;
461
+ }
462
+ }
463
+ }
464
+ if (morphedNode === toNode) {
465
+ onNodeDiscarded(fromNode);
466
+ } else {
467
+ if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
468
+ return;
469
+ }
470
+ morphEl(morphedNode, toNode, childrenOnly);
471
+ if (keyedRemovalList) {
472
+ for (var i = 0, len = keyedRemovalList.length; i < len; i++) {
473
+ var elToRemove = fromNodesLookup[keyedRemovalList[i]];
474
+ if (elToRemove) {
475
+ removeNode(elToRemove, elToRemove.parentNode, false);
476
+ }
477
+ }
478
+ }
479
+ }
480
+ if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
481
+ if (morphedNode.actualize) {
482
+ morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
483
+ }
484
+ fromNode.parentNode.replaceChild(morphedNode, fromNode);
485
+ }
486
+ return morphedNode;
487
+ };
488
+ }
489
+
490
+ var morphdom = morphdomFactory(morphAttrs);
491
+
492
+ var name = "cable_ready";
493
+
494
+ var version = "5.0.1";
495
+
496
+ var description = "CableReady helps you create great real-time user experiences by making it simple to trigger client-side DOM changes from server-side Ruby.";
497
+
498
+ var keywords = [ "ruby", "rails", "websockets", "actioncable", "cable", "ssr", "stimulus_reflex", "client-side", "dom" ];
499
+
500
+ var homepage = "https://cableready.stimulusreflex.com";
501
+
502
+ var bugs = "https://github.com/stimulusreflex/cable_ready/issues";
503
+
504
+ var repository = "https://github.com/stimulusreflex/cable_ready";
505
+
506
+ var license = "MIT";
507
+
508
+ var author = "Nathan Hopkins <natehop@gmail.com>";
509
+
510
+ var contributors = [ "Andrew Mason <andrewmcodes@protonmail.com>", "Julian Rubisch <julian@julianrubisch.at>", "Marco Roth <marco.roth@intergga.ch>", "Nathan Hopkins <natehop@gmail.com>" ];
511
+
512
+ var main = "./dist/cable_ready.js";
513
+
514
+ var module = "./dist/cable_ready.js";
515
+
516
+ var browser = "./dist/cable_ready.js";
517
+
518
+ var unpkg = "./dist/cable_ready.umd.js";
519
+
520
+ var umd = "./dist/cable_ready.umd.js";
521
+
522
+ var files = [ "dist/*", "javascript/*" ];
523
+
524
+ var scripts = {
525
+ lint: "yarn run format --check",
526
+ format: "yarn run prettier-standard ./javascript/**/*.js rollup.config.mjs",
527
+ build: "yarn rollup -c",
528
+ watch: "yarn rollup -wc",
529
+ test: "web-test-runner javascript/test/**/*.test.js",
530
+ "docs:dev": "vitepress dev docs",
531
+ "docs:build": "vitepress build docs && cp ./docs/_redirects ./docs/.vitepress/dist",
532
+ "docs:preview": "vitepress preview docs"
533
+ };
534
+
535
+ var dependencies = {
536
+ morphdom: "2.6.1"
537
+ };
538
+
539
+ var devDependencies = {
540
+ "@open-wc/testing": "^3.1.7",
541
+ "@rollup/plugin-json": "^6.0.0",
542
+ "@rollup/plugin-node-resolve": "^15.0.1",
543
+ "@rollup/plugin-terser": "^0.4.0",
544
+ "@web/dev-server-esbuild": "^0.3.3",
545
+ "@web/dev-server-rollup": "^0.3.21",
546
+ "@web/test-runner": "^0.15.1",
547
+ "prettier-standard": "^16.4.1",
548
+ rollup: "^3.19.1",
549
+ sinon: "^15.0.2",
550
+ vite: "^4.1.4",
551
+ vitepress: "^1.0.0-beta.1",
552
+ "vitepress-plugin-search": "^1.0.4-alpha.19"
553
+ };
554
+
555
+ var packageInfo = {
556
+ name: name,
557
+ version: version,
558
+ description: description,
559
+ keywords: keywords,
560
+ homepage: homepage,
561
+ bugs: bugs,
562
+ repository: repository,
563
+ license: license,
564
+ author: author,
565
+ contributors: contributors,
566
+ main: main,
567
+ module: module,
568
+ browser: browser,
569
+ import: "./dist/cable_ready.js",
570
+ unpkg: unpkg,
571
+ umd: umd,
572
+ files: files,
573
+ scripts: scripts,
574
+ dependencies: dependencies,
575
+ devDependencies: devDependencies
576
+ };
577
+
578
+ const inputTags = {
579
+ INPUT: true,
580
+ TEXTAREA: true,
581
+ SELECT: true
582
+ };
583
+
584
+ const mutableTags = {
585
+ INPUT: true,
586
+ TEXTAREA: true,
587
+ OPTION: true
588
+ };
589
+
590
+ const textInputTypes = {
591
+ "datetime-local": true,
592
+ "select-multiple": true,
593
+ "select-one": true,
594
+ color: true,
595
+ date: true,
596
+ datetime: true,
597
+ email: true,
598
+ month: true,
599
+ number: true,
600
+ password: true,
601
+ range: true,
602
+ search: true,
603
+ tel: true,
604
+ text: true,
605
+ textarea: true,
606
+ time: true,
607
+ url: true,
608
+ week: true
609
+ };
610
+
611
+ let activeElement;
612
+
613
+ var ActiveElement = {
614
+ get element() {
615
+ return activeElement;
616
+ },
617
+ set(element) {
618
+ activeElement = element;
619
+ }
620
+ };
621
+
622
+ const isTextInput = element => inputTags[element.tagName] && textInputTypes[element.type];
623
+
624
+ const assignFocus = selector => {
625
+ const element = selector && selector.nodeType === Node.ELEMENT_NODE ? selector : document.querySelector(selector);
626
+ const focusElement = element || ActiveElement.element;
627
+ if (focusElement && focusElement.focus) focusElement.focus();
628
+ };
629
+
630
+ const dispatch = (element, name, detail = {}) => {
631
+ const init = {
632
+ bubbles: true,
633
+ cancelable: true,
634
+ detail: detail
635
+ };
636
+ const event = new CustomEvent(name, init);
637
+ element.dispatchEvent(event);
638
+ if (window.jQuery) window.jQuery(element).trigger(name, detail);
639
+ };
640
+
641
+ const xpathToElement = xpath => document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
642
+
643
+ const xpathToElementArray = (xpath, reverse = false) => {
644
+ const snapshotList = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
645
+ const snapshots = [];
646
+ for (let i = 0; i < snapshotList.snapshotLength; i++) {
647
+ snapshots.push(snapshotList.snapshotItem(i));
648
+ }
649
+ return reverse ? snapshots.reverse() : snapshots;
650
+ };
651
+
652
+ const getClassNames = names => Array.from(names).flat();
653
+
654
+ const processElements = (operation, callback) => {
655
+ Array.from(operation.selectAll ? operation.element : [ operation.element ]).forEach(callback);
656
+ };
657
+
658
+ const kebabize = createCompounder((function(result, word, index) {
659
+ return result + (index ? "-" : "") + word.toLowerCase();
660
+ }));
661
+
662
+ function createCompounder(callback) {
663
+ return function(str) {
664
+ return words(str).reduce(callback, "");
665
+ };
666
+ }
667
+
668
+ const words = str => {
669
+ str = str == null ? "" : str;
670
+ return str.match(/([A-Z]{2,}|[0-9]+|[A-Z]?[a-z]+|[A-Z])/g) || [];
671
+ };
672
+
673
+ const operate = (operation, callback) => {
674
+ if (!operation.cancel) {
675
+ operation.delay ? setTimeout(callback, operation.delay) : callback();
676
+ return true;
677
+ }
678
+ return false;
679
+ };
680
+
681
+ const before = (target, operation) => dispatch(target, `cable-ready:before-${kebabize(operation.operation)}`, operation);
682
+
683
+ const after = (target, operation) => dispatch(target, `cable-ready:after-${kebabize(operation.operation)}`, operation);
684
+
685
+ function debounce(fn, delay = 250) {
686
+ let timer;
687
+ return (...args) => {
688
+ const callback = () => fn.apply(this, args);
689
+ if (timer) clearTimeout(timer);
690
+ timer = setTimeout(callback, delay);
691
+ };
692
+ }
693
+
694
+ function handleErrors(response) {
695
+ if (!response.ok) throw Error(response.statusText);
696
+ return response;
697
+ }
698
+
699
+ function safeScalar(val) {
700
+ if (val !== undefined && ![ "string", "number", "boolean" ].includes(typeof val)) console.warn(`Operation expects a string, number or boolean, but got ${val} (${typeof val})`);
701
+ return val != null ? val : "";
702
+ }
703
+
704
+ function safeString(str) {
705
+ if (str !== undefined && typeof str !== "string") console.warn(`Operation expects a string, but got ${str} (${typeof str})`);
706
+ return str != null ? String(str) : "";
707
+ }
708
+
709
+ function safeArray(arr) {
710
+ if (arr !== undefined && !Array.isArray(arr)) console.warn(`Operation expects an array, but got ${arr} (${typeof arr})`);
711
+ return arr != null ? Array.from(arr) : [];
712
+ }
713
+
714
+ function safeObject(obj) {
715
+ if (obj !== undefined && typeof obj !== "object") console.warn(`Operation expects an object, but got ${obj} (${typeof obj})`);
716
+ return obj != null ? Object(obj) : {};
717
+ }
718
+
719
+ function safeStringOrArray(elem) {
720
+ if (elem !== undefined && !Array.isArray(elem) && typeof elem !== "string") console.warn(`Operation expects an Array or a String, but got ${elem} (${typeof elem})`);
721
+ return elem == null ? "" : Array.isArray(elem) ? Array.from(elem) : String(elem);
722
+ }
723
+
724
+ function fragmentToString(fragment) {
725
+ return (new XMLSerializer).serializeToString(fragment);
726
+ }
727
+
728
+ async function graciouslyFetch(url, additionalHeaders) {
729
+ try {
730
+ const response = await fetch(url, {
731
+ headers: {
732
+ "X-REQUESTED-WITH": "XmlHttpRequest",
733
+ ...additionalHeaders
734
+ }
735
+ });
736
+ if (response == undefined) return;
737
+ handleErrors(response);
738
+ return response;
739
+ } catch (e) {
740
+ console.error(`Could not fetch ${url}`);
741
+ }
742
+ }
743
+
744
+ class BoundedQueue {
745
+ constructor(maxSize) {
746
+ this.maxSize = maxSize;
747
+ this.queue = [];
748
+ }
749
+ push(item) {
750
+ if (this.isFull()) {
751
+ this.shift();
752
+ }
753
+ this.queue.push(item);
754
+ }
755
+ shift() {
756
+ return this.queue.shift();
757
+ }
758
+ isFull() {
759
+ return this.queue.length === this.maxSize;
760
+ }
761
+ }
762
+
763
+ Object.freeze({
764
+ __proto__: null,
765
+ BoundedQueue: BoundedQueue,
766
+ after: after,
767
+ assignFocus: assignFocus,
768
+ before: before,
769
+ debounce: debounce,
770
+ dispatch: dispatch,
771
+ fragmentToString: fragmentToString,
772
+ getClassNames: getClassNames,
773
+ graciouslyFetch: graciouslyFetch,
774
+ handleErrors: handleErrors,
775
+ isTextInput: isTextInput,
776
+ kebabize: kebabize,
777
+ operate: operate,
778
+ processElements: processElements,
779
+ safeArray: safeArray,
780
+ safeObject: safeObject,
781
+ safeScalar: safeScalar,
782
+ safeString: safeString,
783
+ safeStringOrArray: safeStringOrArray,
784
+ xpathToElement: xpathToElement,
785
+ xpathToElementArray: xpathToElementArray
786
+ });
787
+
788
+ const shouldMorph = operation => (fromEl, toEl) => !shouldMorphCallbacks.map((callback => typeof callback === "function" ? callback(operation, fromEl, toEl) : true)).includes(false);
789
+
790
+ const didMorph = operation => el => {
791
+ didMorphCallbacks.forEach((callback => {
792
+ if (typeof callback === "function") callback(operation, el);
793
+ }));
794
+ };
795
+
796
+ const verifyNotMutable = (detail, fromEl, toEl) => {
797
+ if (!mutableTags[fromEl.tagName] && fromEl.isEqualNode(toEl)) return false;
798
+ return true;
799
+ };
800
+
801
+ const verifyNotContentEditable = (detail, fromEl, toEl) => {
802
+ if (fromEl === ActiveElement.element && fromEl.isContentEditable) return false;
803
+ return true;
804
+ };
805
+
806
+ const verifyNotPermanent = (detail, fromEl, toEl) => {
807
+ const {permanentAttributeName: permanentAttributeName} = detail;
808
+ if (!permanentAttributeName) return true;
809
+ const permanent = fromEl.closest(`[${permanentAttributeName}]`);
810
+ if (!permanent && fromEl === ActiveElement.element && isTextInput(fromEl)) {
811
+ const ignore = {
812
+ value: true
813
+ };
814
+ Array.from(toEl.attributes).forEach((attribute => {
815
+ if (!ignore[attribute.name]) fromEl.setAttribute(attribute.name, attribute.value);
816
+ }));
817
+ return false;
818
+ }
819
+ return !permanent;
820
+ };
821
+
822
+ const shouldMorphCallbacks = [ verifyNotMutable, verifyNotPermanent, verifyNotContentEditable ];
823
+
824
+ const didMorphCallbacks = [];
825
+
826
+ Object.freeze({
827
+ __proto__: null,
828
+ didMorph: didMorph,
829
+ didMorphCallbacks: didMorphCallbacks,
830
+ shouldMorph: shouldMorph,
831
+ shouldMorphCallbacks: shouldMorphCallbacks,
832
+ verifyNotContentEditable: verifyNotContentEditable,
833
+ verifyNotMutable: verifyNotMutable,
834
+ verifyNotPermanent: verifyNotPermanent
835
+ });
836
+
837
+ var Operations = {
838
+ append: operation => {
839
+ processElements(operation, (element => {
840
+ before(element, operation);
841
+ operate(operation, (() => {
842
+ const {html: html, focusSelector: focusSelector} = operation;
843
+ element.insertAdjacentHTML("beforeend", safeScalar(html));
844
+ assignFocus(focusSelector);
845
+ }));
846
+ after(element, operation);
847
+ }));
848
+ },
849
+ graft: operation => {
850
+ processElements(operation, (element => {
851
+ before(element, operation);
852
+ operate(operation, (() => {
853
+ const {parent: parent, focusSelector: focusSelector} = operation;
854
+ const parentElement = document.querySelector(parent);
855
+ if (parentElement) {
856
+ parentElement.appendChild(element);
857
+ assignFocus(focusSelector);
858
+ }
859
+ }));
860
+ after(element, operation);
861
+ }));
862
+ },
863
+ innerHtml: operation => {
864
+ processElements(operation, (element => {
865
+ before(element, operation);
866
+ operate(operation, (() => {
867
+ const {html: html, focusSelector: focusSelector} = operation;
868
+ element.innerHTML = safeScalar(html);
869
+ assignFocus(focusSelector);
870
+ }));
871
+ after(element, operation);
872
+ }));
873
+ },
874
+ insertAdjacentHtml: operation => {
875
+ processElements(operation, (element => {
876
+ before(element, operation);
877
+ operate(operation, (() => {
878
+ const {html: html, position: position, focusSelector: focusSelector} = operation;
879
+ element.insertAdjacentHTML(position || "beforeend", safeScalar(html));
880
+ assignFocus(focusSelector);
881
+ }));
882
+ after(element, operation);
883
+ }));
884
+ },
885
+ insertAdjacentText: operation => {
886
+ processElements(operation, (element => {
887
+ before(element, operation);
888
+ operate(operation, (() => {
889
+ const {text: text, position: position, focusSelector: focusSelector} = operation;
890
+ element.insertAdjacentText(position || "beforeend", safeScalar(text));
891
+ assignFocus(focusSelector);
892
+ }));
893
+ after(element, operation);
894
+ }));
895
+ },
896
+ outerHtml: operation => {
897
+ processElements(operation, (element => {
898
+ const parent = element.parentElement;
899
+ const idx = parent && Array.from(parent.children).indexOf(element);
900
+ before(element, operation);
901
+ operate(operation, (() => {
902
+ const {html: html, focusSelector: focusSelector} = operation;
903
+ element.outerHTML = safeScalar(html);
904
+ assignFocus(focusSelector);
905
+ }));
906
+ after(parent ? parent.children[idx] : document.documentElement, operation);
907
+ }));
908
+ },
909
+ prepend: operation => {
910
+ processElements(operation, (element => {
911
+ before(element, operation);
912
+ operate(operation, (() => {
913
+ const {html: html, focusSelector: focusSelector} = operation;
914
+ element.insertAdjacentHTML("afterbegin", safeScalar(html));
915
+ assignFocus(focusSelector);
916
+ }));
917
+ after(element, operation);
918
+ }));
919
+ },
920
+ remove: operation => {
921
+ processElements(operation, (element => {
922
+ before(element, operation);
923
+ operate(operation, (() => {
924
+ const {focusSelector: focusSelector} = operation;
925
+ element.remove();
926
+ assignFocus(focusSelector);
927
+ }));
928
+ after(document, operation);
929
+ }));
930
+ },
931
+ replace: operation => {
932
+ processElements(operation, (element => {
933
+ const parent = element.parentElement;
934
+ const idx = parent && Array.from(parent.children).indexOf(element);
935
+ before(element, operation);
936
+ operate(operation, (() => {
937
+ const {html: html, focusSelector: focusSelector} = operation;
938
+ element.outerHTML = safeScalar(html);
939
+ assignFocus(focusSelector);
940
+ }));
941
+ after(parent ? parent.children[idx] : document.documentElement, operation);
942
+ }));
943
+ },
944
+ textContent: operation => {
945
+ processElements(operation, (element => {
946
+ before(element, operation);
947
+ operate(operation, (() => {
948
+ const {text: text, focusSelector: focusSelector} = operation;
949
+ element.textContent = safeScalar(text);
950
+ assignFocus(focusSelector);
951
+ }));
952
+ after(element, operation);
953
+ }));
954
+ },
955
+ addCssClass: operation => {
956
+ processElements(operation, (element => {
957
+ before(element, operation);
958
+ operate(operation, (() => {
959
+ const {name: name} = operation;
960
+ element.classList.add(...getClassNames([ safeStringOrArray(name) ]));
961
+ }));
962
+ after(element, operation);
963
+ }));
964
+ },
965
+ removeAttribute: operation => {
966
+ processElements(operation, (element => {
967
+ before(element, operation);
968
+ operate(operation, (() => {
969
+ const {name: name} = operation;
970
+ element.removeAttribute(safeString(name));
971
+ }));
972
+ after(element, operation);
973
+ }));
974
+ },
975
+ removeCssClass: operation => {
976
+ processElements(operation, (element => {
977
+ before(element, operation);
978
+ operate(operation, (() => {
979
+ const {name: name} = operation;
980
+ element.classList.remove(...getClassNames([ safeStringOrArray(name) ]));
981
+ if (element.classList.length === 0) element.removeAttribute("class");
982
+ }));
983
+ after(element, operation);
984
+ }));
985
+ },
986
+ setAttribute: operation => {
987
+ processElements(operation, (element => {
988
+ before(element, operation);
989
+ operate(operation, (() => {
990
+ const {name: name, value: value} = operation;
991
+ element.setAttribute(safeString(name), safeScalar(value));
992
+ }));
993
+ after(element, operation);
994
+ }));
995
+ },
996
+ setDatasetProperty: operation => {
997
+ processElements(operation, (element => {
998
+ before(element, operation);
999
+ operate(operation, (() => {
1000
+ const {name: name, value: value} = operation;
1001
+ element.dataset[safeString(name)] = safeScalar(value);
1002
+ }));
1003
+ after(element, operation);
1004
+ }));
1005
+ },
1006
+ setProperty: operation => {
1007
+ processElements(operation, (element => {
1008
+ before(element, operation);
1009
+ operate(operation, (() => {
1010
+ const {name: name, value: value} = operation;
1011
+ if (name in element) element[safeString(name)] = safeScalar(value);
1012
+ }));
1013
+ after(element, operation);
1014
+ }));
1015
+ },
1016
+ setStyle: operation => {
1017
+ processElements(operation, (element => {
1018
+ before(element, operation);
1019
+ operate(operation, (() => {
1020
+ const {name: name, value: value} = operation;
1021
+ element.style[safeString(name)] = safeScalar(value);
1022
+ }));
1023
+ after(element, operation);
1024
+ }));
1025
+ },
1026
+ setStyles: operation => {
1027
+ processElements(operation, (element => {
1028
+ before(element, operation);
1029
+ operate(operation, (() => {
1030
+ const {styles: styles} = operation;
1031
+ for (let [name, value] of Object.entries(styles)) element.style[safeString(name)] = safeScalar(value);
1032
+ }));
1033
+ after(element, operation);
1034
+ }));
1035
+ },
1036
+ setValue: operation => {
1037
+ processElements(operation, (element => {
1038
+ before(element, operation);
1039
+ operate(operation, (() => {
1040
+ const {value: value} = operation;
1041
+ element.value = safeScalar(value);
1042
+ }));
1043
+ after(element, operation);
1044
+ }));
1045
+ },
1046
+ dispatchEvent: operation => {
1047
+ processElements(operation, (element => {
1048
+ before(element, operation);
1049
+ operate(operation, (() => {
1050
+ const {name: name, detail: detail} = operation;
1051
+ dispatch(element, safeString(name), safeObject(detail));
1052
+ }));
1053
+ after(element, operation);
1054
+ }));
1055
+ },
1056
+ setMeta: operation => {
1057
+ before(document, operation);
1058
+ operate(operation, (() => {
1059
+ const {name: name, content: content} = operation;
1060
+ let meta = document.head.querySelector(`meta[name='${name}']`);
1061
+ if (!meta) {
1062
+ meta = document.createElement("meta");
1063
+ meta.name = safeString(name);
1064
+ document.head.appendChild(meta);
1065
+ }
1066
+ meta.content = safeScalar(content);
1067
+ }));
1068
+ after(document, operation);
1069
+ },
1070
+ setTitle: operation => {
1071
+ before(document, operation);
1072
+ operate(operation, (() => {
1073
+ const {title: title} = operation;
1074
+ document.title = safeScalar(title);
1075
+ }));
1076
+ after(document, operation);
1077
+ },
1078
+ clearStorage: operation => {
1079
+ before(document, operation);
1080
+ operate(operation, (() => {
1081
+ const {type: type} = operation;
1082
+ const storage = type === "session" ? sessionStorage : localStorage;
1083
+ storage.clear();
1084
+ }));
1085
+ after(document, operation);
1086
+ },
1087
+ go: operation => {
1088
+ before(window, operation);
1089
+ operate(operation, (() => {
1090
+ const {delta: delta} = operation;
1091
+ history.go(delta);
1092
+ }));
1093
+ after(window, operation);
1094
+ },
1095
+ pushState: operation => {
1096
+ before(window, operation);
1097
+ operate(operation, (() => {
1098
+ const {state: state, title: title, url: url} = operation;
1099
+ history.pushState(safeObject(state), safeString(title), safeString(url));
1100
+ }));
1101
+ after(window, operation);
1102
+ },
1103
+ redirectTo: operation => {
1104
+ before(window, operation);
1105
+ operate(operation, (() => {
1106
+ let {url: url, action: action, turbo: turbo} = operation;
1107
+ action = action || "advance";
1108
+ url = safeString(url);
1109
+ if (turbo === undefined) turbo = true;
1110
+ if (turbo) {
1111
+ if (window.Turbo) window.Turbo.visit(url, {
1112
+ action: action
1113
+ });
1114
+ if (window.Turbolinks) window.Turbolinks.visit(url, {
1115
+ action: action
1116
+ });
1117
+ if (!window.Turbo && !window.Turbolinks) window.location.href = url;
1118
+ } else {
1119
+ window.location.href = url;
1120
+ }
1121
+ }));
1122
+ after(window, operation);
1123
+ },
1124
+ reload: operation => {
1125
+ before(window, operation);
1126
+ operate(operation, (() => {
1127
+ window.location.reload();
1128
+ }));
1129
+ after(window, operation);
1130
+ },
1131
+ removeStorageItem: operation => {
1132
+ before(document, operation);
1133
+ operate(operation, (() => {
1134
+ const {key: key, type: type} = operation;
1135
+ const storage = type === "session" ? sessionStorage : localStorage;
1136
+ storage.removeItem(safeString(key));
1137
+ }));
1138
+ after(document, operation);
1139
+ },
1140
+ replaceState: operation => {
1141
+ before(window, operation);
1142
+ operate(operation, (() => {
1143
+ const {state: state, title: title, url: url} = operation;
1144
+ history.replaceState(safeObject(state), safeString(title), safeString(url));
1145
+ }));
1146
+ after(window, operation);
1147
+ },
1148
+ scrollIntoView: operation => {
1149
+ const {element: element} = operation;
1150
+ before(element, operation);
1151
+ operate(operation, (() => {
1152
+ element.scrollIntoView(operation);
1153
+ }));
1154
+ after(element, operation);
1155
+ },
1156
+ setCookie: operation => {
1157
+ before(document, operation);
1158
+ operate(operation, (() => {
1159
+ const {cookie: cookie} = operation;
1160
+ document.cookie = safeScalar(cookie);
1161
+ }));
1162
+ after(document, operation);
1163
+ },
1164
+ setFocus: operation => {
1165
+ const {element: element} = operation;
1166
+ before(element, operation);
1167
+ operate(operation, (() => {
1168
+ assignFocus(element);
1169
+ }));
1170
+ after(element, operation);
1171
+ },
1172
+ setStorageItem: operation => {
1173
+ before(document, operation);
1174
+ operate(operation, (() => {
1175
+ const {key: key, value: value, type: type} = operation;
1176
+ const storage = type === "session" ? sessionStorage : localStorage;
1177
+ storage.setItem(safeString(key), safeScalar(value));
1178
+ }));
1179
+ after(document, operation);
1180
+ },
1181
+ consoleLog: operation => {
1182
+ before(document, operation);
1183
+ operate(operation, (() => {
1184
+ const {message: message, level: level} = operation;
1185
+ level && [ "warn", "info", "error" ].includes(level) ? console[level](message) : console.log(message);
1186
+ }));
1187
+ after(document, operation);
1188
+ },
1189
+ consoleTable: operation => {
1190
+ before(document, operation);
1191
+ operate(operation, (() => {
1192
+ const {data: data, columns: columns} = operation;
1193
+ console.table(data, safeArray(columns));
1194
+ }));
1195
+ after(document, operation);
1196
+ },
1197
+ notification: operation => {
1198
+ before(document, operation);
1199
+ operate(operation, (() => {
1200
+ const {title: title, options: options} = operation;
1201
+ Notification.requestPermission().then((result => {
1202
+ operation.permission = result;
1203
+ if (result === "granted") new Notification(safeString(title), safeObject(options));
1204
+ }));
1205
+ }));
1206
+ after(document, operation);
1207
+ },
1208
+ morph: operation => {
1209
+ processElements(operation, (element => {
1210
+ const {html: html} = operation;
1211
+ const template = document.createElement("template");
1212
+ template.innerHTML = String(safeScalar(html)).trim();
1213
+ operation.content = template.content;
1214
+ const parent = element.parentElement;
1215
+ const idx = parent && Array.from(parent.children).indexOf(element);
1216
+ before(element, operation);
1217
+ operate(operation, (() => {
1218
+ const {childrenOnly: childrenOnly, focusSelector: focusSelector} = operation;
1219
+ morphdom(element, childrenOnly ? template.content : template.innerHTML, {
1220
+ childrenOnly: !!childrenOnly,
1221
+ onBeforeElUpdated: shouldMorph(operation),
1222
+ onElUpdated: didMorph(operation)
1223
+ });
1224
+ assignFocus(focusSelector);
1225
+ }));
1226
+ after(parent ? parent.children[idx] : document.documentElement, operation);
1227
+ }));
1228
+ }
1229
+ };
1230
+
1231
+ let operations = Operations;
1232
+
1233
+ const add = newOperations => {
1234
+ operations = {
1235
+ ...operations,
1236
+ ...newOperations
1237
+ };
1238
+ };
1239
+
1240
+ const addOperations = operations => {
1241
+ add(operations);
1242
+ };
1243
+
1244
+ const addOperation = (name, operation) => {
1245
+ const operations = {};
1246
+ operations[name] = operation;
1247
+ add(operations);
1248
+ };
1249
+
1250
+ var OperationStore = {
1251
+ get all() {
1252
+ return operations;
1253
+ }
1254
+ };
1255
+
1256
+ let missingElement = "warn";
1257
+
1258
+ var MissingElement$1 = {
1259
+ get behavior() {
1260
+ return missingElement;
1261
+ },
1262
+ set(value) {
1263
+ if ([ "warn", "ignore", "event", "exception" ].includes(value)) missingElement = value; else console.warn("Invalid 'onMissingElement' option. Defaulting to 'warn'.");
1264
+ }
1265
+ };
1266
+
1267
+ const perform = (operations, options = {
1268
+ onMissingElement: MissingElement$1.behavior
1269
+ }) => {
1270
+ const batches = {};
1271
+ operations.forEach((operation => {
1272
+ if (!!operation.batch) batches[operation.batch] = batches[operation.batch] ? ++batches[operation.batch] : 1;
1273
+ }));
1274
+ operations.forEach((operation => {
1275
+ const name = operation.operation;
1276
+ try {
1277
+ if (operation.selector) {
1278
+ if (operation.xpath) {
1279
+ operation.element = operation.selectAll ? xpathToElementArray(operation.selector) : xpathToElement(operation.selector);
1280
+ } else {
1281
+ operation.element = operation.selectAll ? document.querySelectorAll(operation.selector) : document.querySelector(operation.selector);
1282
+ }
1283
+ } else {
1284
+ operation.element = document;
1285
+ }
1286
+ if (operation.element || options.onMissingElement !== "ignore") {
1287
+ ActiveElement.set(document.activeElement);
1288
+ const cableReadyOperation = OperationStore.all[name];
1289
+ if (cableReadyOperation) {
1290
+ cableReadyOperation(operation);
1291
+ if (!!operation.batch && --batches[operation.batch] === 0) dispatch(document, "cable-ready:batch-complete", {
1292
+ batch: operation.batch
1293
+ });
1294
+ } else {
1295
+ console.error(`CableReady couldn't find the "${name}" operation. Make sure you use the camelized form when calling an operation method.`);
1296
+ }
1297
+ }
1298
+ } catch (e) {
1299
+ if (operation.element) {
1300
+ console.error(`CableReady detected an error in ${name || "operation"}: ${e.message}. If you need to support older browsers make sure you've included the corresponding polyfills. https://docs.stimulusreflex.com/setup#polyfills-for-ie11.`);
1301
+ console.error(e);
1302
+ } else {
1303
+ const warning = `CableReady ${name || ""} operation failed due to missing DOM element for selector: '${operation.selector}'`;
1304
+ switch (options.onMissingElement) {
1305
+ case "ignore":
1306
+ break;
1307
+
1308
+ case "event":
1309
+ dispatch(document, "cable-ready:missing-element", {
1310
+ warning: warning,
1311
+ operation: operation
1312
+ });
1313
+ break;
1314
+
1315
+ case "exception":
1316
+ throw warning;
1317
+
1318
+ default:
1319
+ console.warn(warning);
1320
+ }
1321
+ }
1322
+ }
1323
+ }));
1324
+ };
1325
+
1326
+ const performAsync = (operations, options = {
1327
+ onMissingElement: MissingElement$1.behavior
1328
+ }) => new Promise(((resolve, reject) => {
1329
+ try {
1330
+ resolve(perform(operations, options));
1331
+ } catch (err) {
1332
+ reject(err);
1333
+ }
1334
+ }));
1335
+
1336
+ class SubscribingElement extends HTMLElement {
1337
+ static get tagName() {
1338
+ throw new Error("Implement the tagName() getter in the inheriting class");
1339
+ }
1340
+ static define() {
1341
+ if (!customElements.get(this.tagName)) {
1342
+ customElements.define(this.tagName, this);
1343
+ }
1344
+ }
1345
+ disconnectedCallback() {
1346
+ if (this.channel) this.channel.unsubscribe();
1347
+ }
1348
+ createSubscription(consumer, channel, receivedCallback) {
1349
+ this.channel = consumer.subscriptions.create({
1350
+ channel: channel,
1351
+ identifier: this.identifier
1352
+ }, {
1353
+ received: receivedCallback
1354
+ });
1355
+ }
1356
+ get preview() {
1357
+ return document.documentElement.hasAttribute("data-turbolinks-preview") || document.documentElement.hasAttribute("data-turbo-preview");
1358
+ }
1359
+ get identifier() {
1360
+ return this.getAttribute("identifier");
1361
+ }
1362
+ }
1363
+
1364
+ let consumer;
1365
+
1366
+ const BACKOFF = [ 25, 50, 75, 100, 200, 250, 500, 800, 1e3, 2e3 ];
1367
+
1368
+ const wait = ms => new Promise((resolve => setTimeout(resolve, ms)));
1369
+
1370
+ const getConsumerWithRetry = async (retry = 0) => {
1371
+ if (consumer) return consumer;
1372
+ if (retry >= BACKOFF.length) {
1373
+ throw new Error("Couldn't obtain a Action Cable consumer within 5s");
1374
+ }
1375
+ await wait(BACKOFF[retry]);
1376
+ return await getConsumerWithRetry(retry + 1);
1377
+ };
1378
+
1379
+ var CableConsumer = {
1380
+ setConsumer(value) {
1381
+ consumer = value;
1382
+ },
1383
+ get consumer() {
1384
+ return consumer;
1385
+ },
1386
+ async getConsumer() {
1387
+ return await getConsumerWithRetry();
1388
+ }
1389
+ };
1390
+
1391
+ class StreamFromElement extends SubscribingElement {
1392
+ static get tagName() {
1393
+ return "cable-ready-stream-from";
1394
+ }
1395
+ async connectedCallback() {
1396
+ if (this.preview) return;
1397
+ const consumer = await CableConsumer.getConsumer();
1398
+ if (consumer) {
1399
+ this.createSubscription(consumer, "CableReady::Stream", this.performOperations.bind(this));
1400
+ } else {
1401
+ console.error("The `cable_ready_stream_from` helper cannot connect. You must initialize CableReady with an Action Cable consumer.");
1402
+ }
1403
+ }
1404
+ performOperations(data) {
1405
+ if (data.cableReady) perform(data.operations, {
1406
+ onMissingElement: this.onMissingElement
1407
+ });
1408
+ }
1409
+ get onMissingElement() {
1410
+ const value = this.getAttribute("missing") || MissingElement$1.behavior;
1411
+ if ([ "warn", "ignore", "event" ].includes(value)) return value; else {
1412
+ console.warn("Invalid 'missing' attribute. Defaulting to 'warn'.");
1413
+ return "warn";
1414
+ }
1415
+ }
1416
+ }
1417
+
1418
+ let debugging = false;
1419
+
1420
+ var Debug = {
1421
+ get enabled() {
1422
+ return debugging;
1423
+ },
1424
+ get disabled() {
1425
+ return !debugging;
1426
+ },
1427
+ get value() {
1428
+ return debugging;
1429
+ },
1430
+ set(value) {
1431
+ debugging = !!value;
1432
+ },
1433
+ set debug(value) {
1434
+ debugging = !!value;
1435
+ }
1436
+ };
1437
+
1438
+ const request = (data, blocks) => {
1439
+ if (Debug.disabled) return;
1440
+ const message = `↑ Updatable request affecting ${blocks.length} element(s): `;
1441
+ console.log(message, {
1442
+ elements: blocks.map((b => b.element)),
1443
+ identifiers: blocks.map((b => b.element.getAttribute("identifier"))),
1444
+ data: data
1445
+ });
1446
+ return message;
1447
+ };
1448
+
1449
+ const cancel = (timestamp, reason) => {
1450
+ if (Debug.disabled) return;
1451
+ const duration = new Date - timestamp;
1452
+ const message = `❌ Updatable request canceled after ${duration}ms: ${reason}`;
1453
+ console.log(message);
1454
+ return message;
1455
+ };
1456
+
1457
+ const response = (timestamp, element, urls) => {
1458
+ if (Debug.disabled) return;
1459
+ const duration = new Date - timestamp;
1460
+ const message = `↓ Updatable response: All URLs fetched in ${duration}ms`;
1461
+ console.log(message, {
1462
+ element: element,
1463
+ urls: urls
1464
+ });
1465
+ return message;
1466
+ };
1467
+
1468
+ const morphStart = (timestamp, element) => {
1469
+ if (Debug.disabled) return;
1470
+ const duration = new Date - timestamp;
1471
+ const message = `↻ Updatable morph: starting after ${duration}ms`;
1472
+ console.log(message, {
1473
+ element: element
1474
+ });
1475
+ return message;
1476
+ };
1477
+
1478
+ const morphEnd = (timestamp, element) => {
1479
+ if (Debug.disabled) return;
1480
+ const duration = new Date - timestamp;
1481
+ const message = `↺ Updatable morph: completed after ${duration}ms`;
1482
+ console.log(message, {
1483
+ element: element
1484
+ });
1485
+ return message;
1486
+ };
1487
+
1488
+ var Log = {
1489
+ request: request,
1490
+ cancel: cancel,
1491
+ response: response,
1492
+ morphStart: morphStart,
1493
+ morphEnd: morphEnd
1494
+ };
1495
+
1496
+ const template = `\n<style>\n :host {\n display: block;\n }\n</style>\n<slot></slot>\n`;
1497
+
1498
+ class UpdatesForElement extends SubscribingElement {
1499
+ static get tagName() {
1500
+ return "cable-ready-updates-for";
1501
+ }
1502
+ constructor() {
1503
+ super();
1504
+ const shadowRoot = this.attachShadow({
1505
+ mode: "open"
1506
+ });
1507
+ shadowRoot.innerHTML = template;
1508
+ this.triggerElementLog = new BoundedQueue(10);
1509
+ this.targetElementLog = new BoundedQueue(10);
1510
+ }
1511
+ async connectedCallback() {
1512
+ if (this.preview) return;
1513
+ this.update = debounce(this.update.bind(this), this.debounce);
1514
+ const consumer = await CableConsumer.getConsumer();
1515
+ if (consumer) {
1516
+ this.createSubscription(consumer, "CableReady::Stream", this.update);
1517
+ } else {
1518
+ console.error("The `cable_ready_updates_for` helper cannot connect. You must initialize CableReady with an Action Cable consumer.");
1519
+ }
1520
+ }
1521
+ async update(data) {
1522
+ this.lastUpdateTimestamp = new Date;
1523
+ const blocks = Array.from(document.querySelectorAll(this.query), (element => new Block(element))).filter((block => block.shouldUpdate(data)));
1524
+ this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.request(data, blocks)}`);
1525
+ if (blocks.length === 0) {
1526
+ this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.cancel(this.lastUpdateTimestamp, "All elements filtered out")}`);
1527
+ return;
1528
+ }
1529
+ if (blocks[0].element !== this) {
1530
+ this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.cancel(this.lastUpdateTimestamp, "Update already requested")}`);
1531
+ return;
1532
+ }
1533
+ ActiveElement.set(document.activeElement);
1534
+ this.html = {};
1535
+ const uniqueUrls = [ ...new Set(blocks.map((block => block.url))) ];
1536
+ await Promise.all(uniqueUrls.map((async url => {
1537
+ if (!this.html.hasOwnProperty(url)) {
1538
+ const response = await graciouslyFetch(url, {
1539
+ "X-Cable-Ready": "update"
1540
+ });
1541
+ this.html[url] = await response.text();
1542
+ }
1543
+ })));
1544
+ this.triggerElementLog.push(`${(new Date).toLocaleString()}: ${Log.response(this.lastUpdateTimestamp, this, uniqueUrls)}`);
1545
+ this.index = {};
1546
+ blocks.forEach((block => {
1547
+ this.index.hasOwnProperty(block.url) ? this.index[block.url]++ : this.index[block.url] = 0;
1548
+ block.process(data, this.html, this.index, this.lastUpdateTimestamp);
1549
+ }));
1550
+ }
1551
+ get query() {
1552
+ return `${this.tagName}[identifier="${this.identifier}"]`;
1553
+ }
1554
+ get identifier() {
1555
+ return this.getAttribute("identifier");
1556
+ }
1557
+ get debounce() {
1558
+ return this.hasAttribute("debounce") ? parseInt(this.getAttribute("debounce")) : 20;
1559
+ }
1560
+ }
1561
+
1562
+ class Block {
1563
+ constructor(element) {
1564
+ this.element = element;
1565
+ }
1566
+ async process(data, html, fragmentsIndex, startTimestamp) {
1567
+ const blockIndex = fragmentsIndex[this.url];
1568
+ const template = document.createElement("template");
1569
+ this.element.setAttribute("updating", "updating");
1570
+ template.innerHTML = String(html[this.url]).trim();
1571
+ await this.resolveTurboFrames(template.content);
1572
+ const fragments = template.content.querySelectorAll(this.query);
1573
+ if (fragments.length <= blockIndex) {
1574
+ console.warn(`Update aborted due to insufficient number of elements. The offending url is ${this.url}, the offending element is:`, this.element);
1575
+ return;
1576
+ }
1577
+ const operation = {
1578
+ element: this.element,
1579
+ html: fragments[blockIndex],
1580
+ permanentAttributeName: "data-ignore-updates"
1581
+ };
1582
+ dispatch(this.element, "cable-ready:before-update", operation);
1583
+ this.element.targetElementLog.push(`${(new Date).toLocaleString()}: ${Log.morphStart(startTimestamp, this.element)}`);
1584
+ morphdom(this.element, fragments[blockIndex], {
1585
+ childrenOnly: true,
1586
+ onBeforeElUpdated: shouldMorph(operation),
1587
+ onElUpdated: _ => {
1588
+ this.element.removeAttribute("updating");
1589
+ dispatch(this.element, "cable-ready:after-update", operation);
1590
+ assignFocus(operation.focusSelector);
1591
+ }
1592
+ });
1593
+ this.element.targetElementLog.push(`${(new Date).toLocaleString()}: ${Log.morphEnd(startTimestamp, this.element)}`);
1594
+ }
1595
+ async resolveTurboFrames(documentFragment) {
1596
+ const reloadingTurboFrames = [ ...documentFragment.querySelectorAll('turbo-frame[src]:not([loading="lazy"])') ];
1597
+ return Promise.all(reloadingTurboFrames.map((frame => new Promise((async resolve => {
1598
+ const frameResponse = await graciouslyFetch(frame.getAttribute("src"), {
1599
+ "Turbo-Frame": frame.id,
1600
+ "X-Cable-Ready": "update"
1601
+ });
1602
+ const frameTemplate = document.createElement("template");
1603
+ frameTemplate.innerHTML = await frameResponse.text();
1604
+ await this.resolveTurboFrames(frameTemplate.content);
1605
+ const selector = `turbo-frame#${frame.id}`;
1606
+ const frameContent = frameTemplate.content.querySelector(selector);
1607
+ const content = frameContent ? frameContent.innerHTML.trim() : "";
1608
+ documentFragment.querySelector(selector).innerHTML = content;
1609
+ resolve();
1610
+ })))));
1611
+ }
1612
+ shouldUpdate(data) {
1613
+ return !this.ignoresInnerUpdates && this.hasChangesSelectedForUpdate(data);
1614
+ }
1615
+ hasChangesSelectedForUpdate(data) {
1616
+ const only = this.element.getAttribute("only");
1617
+ return !(only && data.changed && !only.split(" ").some((attribute => data.changed.includes(attribute))));
1618
+ }
1619
+ get ignoresInnerUpdates() {
1620
+ return this.element.hasAttribute("ignore-inner-updates") && this.element.hasAttribute("performing-inner-update");
1621
+ }
1622
+ get url() {
1623
+ return this.element.hasAttribute("url") ? this.element.getAttribute("url") : location.href;
1624
+ }
1625
+ get identifier() {
1626
+ return this.element.identifier;
1627
+ }
1628
+ get query() {
1629
+ return this.element.query;
1630
+ }
1631
+ }
1632
+
1633
+ const registerInnerUpdates = () => {
1634
+ document.addEventListener("stimulus-reflex:before", (event => {
1635
+ recursiveMarkUpdatesForElements(event.detail.element);
1636
+ }));
1637
+ document.addEventListener("stimulus-reflex:after", (event => {
1638
+ setTimeout((() => {
1639
+ recursiveUnmarkUpdatesForElements(event.detail.element);
1640
+ }));
1641
+ }));
1642
+ document.addEventListener("turbo:submit-start", (event => {
1643
+ recursiveMarkUpdatesForElements(event.target);
1644
+ }));
1645
+ document.addEventListener("turbo:submit-end", (event => {
1646
+ setTimeout((() => {
1647
+ recursiveUnmarkUpdatesForElements(event.target);
1648
+ }));
1649
+ }));
1650
+ document.addEventListener("turbo-boost:command:start", (event => {
1651
+ recursiveMarkUpdatesForElements(event.target);
1652
+ }));
1653
+ document.addEventListener("turbo-boost:command:finish", (event => {
1654
+ setTimeout((() => {
1655
+ recursiveUnmarkUpdatesForElements(event.target);
1656
+ }));
1657
+ }));
1658
+ document.addEventListener("turbo-boost:command:error", (event => {
1659
+ setTimeout((() => {
1660
+ recursiveUnmarkUpdatesForElements(event.target);
1661
+ }));
1662
+ }));
1663
+ };
1664
+
1665
+ const recursiveMarkUpdatesForElements = leaf => {
1666
+ const closestUpdatesFor = leaf && leaf.parentElement && leaf.parentElement.closest("cable-ready-updates-for");
1667
+ if (closestUpdatesFor) {
1668
+ closestUpdatesFor.setAttribute("performing-inner-update", "");
1669
+ recursiveMarkUpdatesForElements(closestUpdatesFor);
1670
+ }
1671
+ };
1672
+
1673
+ const recursiveUnmarkUpdatesForElements = leaf => {
1674
+ const closestUpdatesFor = leaf && leaf.parentElement && leaf.parentElement.closest("cable-ready-updates-for");
1675
+ if (closestUpdatesFor) {
1676
+ closestUpdatesFor.removeAttribute("performing-inner-update");
1677
+ recursiveUnmarkUpdatesForElements(closestUpdatesFor);
1678
+ }
1679
+ };
1680
+
1681
+ const defineElements$1 = () => {
1682
+ registerInnerUpdates();
1683
+ StreamFromElement.define();
1684
+ UpdatesForElement.define();
1685
+ };
1686
+
1687
+ const initialize = (initializeOptions = {}) => {
1688
+ const {consumer: consumer, onMissingElement: onMissingElement, debug: debug} = initializeOptions;
1689
+ Debug.set(!!debug);
1690
+ if (consumer) {
1691
+ CableConsumer.setConsumer(consumer);
1692
+ } else {
1693
+ console.error("CableReady requires a reference to your Action Cable `consumer` for its helpers to function.\nEnsure that you have imported the `CableReady` package as well as `consumer` from your `channels` folder, then call `CableReady.initialize({ consumer })`.");
1694
+ }
1695
+ if (onMissingElement) {
1696
+ MissingElement.set(onMissingElement);
1697
+ }
1698
+ defineElements$1();
1699
+ };
1700
+
1701
+ const global = {
1702
+ perform: perform,
1703
+ performAsync: performAsync,
1704
+ shouldMorphCallbacks: shouldMorphCallbacks,
1705
+ didMorphCallbacks: didMorphCallbacks,
1706
+ initialize: initialize,
1707
+ addOperation: addOperation,
1708
+ addOperations: addOperations,
1709
+ version: packageInfo.version,
1710
+ cable: CableConsumer,
1711
+ get DOMOperations() {
1712
+ console.warn("DEPRECATED: Please use `CableReady.operations` instead of `CableReady.DOMOperations`");
1713
+ return OperationStore.all;
1714
+ },
1715
+ get operations() {
1716
+ return OperationStore.all;
1717
+ },
1718
+ get consumer() {
1719
+ return CableConsumer.consumer;
1720
+ }
1721
+ };
1722
+
1723
+ window.CableReady = global;
1724
+
1725
+ class CableReadyElement extends HTMLElement {
1726
+ static define() {
1727
+ if (!customElements.get("cable-ready")) {
1728
+ customElements.define("cable-ready", this);
1729
+ }
1730
+ }
1731
+ connectedCallback() {
1732
+ setTimeout((() => {
1733
+ try {
1734
+ const operations = JSON.parse(this.scriptElement.textContent);
1735
+ global.perform(operations);
1736
+ } catch (error) {
1737
+ console.error(error);
1738
+ } finally {
1739
+ try {
1740
+ this.remove();
1741
+ } catch {}
1742
+ }
1743
+ }));
1744
+ }
1745
+ get scriptElement() {
1746
+ if (this.firstElementChild instanceof HTMLScriptElement && this.firstElementChild.getAttribute("type") === "application/json") {
1747
+ return this.firstElementChild;
1748
+ }
1749
+ throw new Error('First child element in a `<cable-ready>` tag must be `<script type="application/json">`.');
1750
+ }
1751
+ }
1752
+
1753
+ const defineElements = () => {
1754
+ CableReadyElement.define();
1755
+ };
1756
+
1757
+ defineElements();
1758
+
1759
+ export { CableReadyElement };