phoenix_live_view 0.20.2 → 0.20.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/js/phoenix_live_view/constants.js +3 -1
- package/assets/js/phoenix_live_view/dom.js +78 -12
- package/assets/js/phoenix_live_view/dom_patch.js +96 -58
- package/assets/js/phoenix_live_view/hooks.js +71 -17
- package/assets/js/phoenix_live_view/js.js +39 -8
- package/assets/js/phoenix_live_view/live_socket.js +22 -12
- package/assets/js/phoenix_live_view/live_uploader.js +8 -1
- package/assets/js/phoenix_live_view/rendered.js +52 -49
- package/assets/js/phoenix_live_view/upload_entry.js +10 -1
- package/assets/js/phoenix_live_view/view.js +52 -21
- package/assets/package.json +11 -9
- package/package.json +9 -2
- package/priv/static/phoenix_live_view.cjs.js +333 -167
- package/priv/static/phoenix_live_view.cjs.js.map +2 -2
- package/priv/static/phoenix_live_view.esm.js +333 -167
- package/priv/static/phoenix_live_view.esm.js.map +2 -2
- package/priv/static/phoenix_live_view.js +333 -167
- package/priv/static/phoenix_live_view.min.js +4 -5
|
@@ -53,7 +53,8 @@ var LiveView = (() => {
|
|
|
53
53
|
"phx-keydown-loading",
|
|
54
54
|
"phx-keyup-loading",
|
|
55
55
|
"phx-blur-loading",
|
|
56
|
-
"phx-focus-loading"
|
|
56
|
+
"phx-focus-loading",
|
|
57
|
+
"phx-hook-loading"
|
|
57
58
|
];
|
|
58
59
|
var PHX_COMPONENT = "data-phx-component";
|
|
59
60
|
var PHX_LIVE_LINK = "data-phx-link";
|
|
@@ -85,6 +86,7 @@ var LiveView = (() => {
|
|
|
85
86
|
var PHX_VIEWPORT_BOTTOM = "viewport-bottom";
|
|
86
87
|
var PHX_TRIGGER_ACTION = "trigger-action";
|
|
87
88
|
var PHX_FEEDBACK_FOR = "feedback-for";
|
|
89
|
+
var PHX_FEEDBACK_GROUP = "feedback-group";
|
|
88
90
|
var PHX_HAS_FOCUSED = "phx-has-focused";
|
|
89
91
|
var FOCUSABLE_INPUTS = ["text", "textarea", "number", "email", "password", "search", "tel", "url", "date", "time", "datetime-local", "color", "range"];
|
|
90
92
|
var CHECKABLE_INPUTS = ["checkbox", "radio"];
|
|
@@ -340,7 +342,9 @@ var LiveView = (() => {
|
|
|
340
342
|
return inputEl.hasAttribute("data-phx-auto-upload");
|
|
341
343
|
},
|
|
342
344
|
findUploadInputs(node) {
|
|
343
|
-
|
|
345
|
+
const formId = node.id;
|
|
346
|
+
const inputsOutsideForm = this.all(document, `input[type="file"][${PHX_UPLOAD_REF}][form="${formId}"]`);
|
|
347
|
+
return this.all(node, `input[type="file"][${PHX_UPLOAD_REF}]`).concat(inputsOutsideForm);
|
|
344
348
|
},
|
|
345
349
|
findComponentNodeList(node, cid) {
|
|
346
350
|
return this.filterWithinSameLiveView(this.all(node, `[${PHX_COMPONENT}="${cid}"]`), node);
|
|
@@ -534,7 +538,9 @@ var LiveView = (() => {
|
|
|
534
538
|
});
|
|
535
539
|
}
|
|
536
540
|
if (this.once(el, "bind-debounce")) {
|
|
537
|
-
el.addEventListener("blur", () =>
|
|
541
|
+
el.addEventListener("blur", () => {
|
|
542
|
+
callback();
|
|
543
|
+
});
|
|
538
544
|
}
|
|
539
545
|
}
|
|
540
546
|
},
|
|
@@ -567,16 +573,39 @@ var LiveView = (() => {
|
|
|
567
573
|
el.setAttribute("data-phx-hook", "Phoenix.InfiniteScroll");
|
|
568
574
|
}
|
|
569
575
|
},
|
|
570
|
-
maybeHideFeedback(container,
|
|
576
|
+
maybeHideFeedback(container, forms, phxFeedbackFor, phxFeedbackGroup) {
|
|
571
577
|
let feedbacks = [];
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
578
|
+
let inputNamesFocused = {};
|
|
579
|
+
let feedbackGroups = {};
|
|
580
|
+
forms.forEach((form) => {
|
|
581
|
+
Array.from(form.elements).forEach((input) => {
|
|
582
|
+
const group = input.getAttribute(phxFeedbackGroup);
|
|
583
|
+
if (group && !(group in feedbackGroups)) {
|
|
584
|
+
feedbackGroups[group] = true;
|
|
577
585
|
}
|
|
578
|
-
|
|
586
|
+
if (!(input.name in inputNamesFocused)) {
|
|
587
|
+
inputNamesFocused[input.name] = false;
|
|
588
|
+
}
|
|
589
|
+
if (this.private(input, PHX_HAS_FOCUSED) || this.private(input, PHX_HAS_SUBMITTED)) {
|
|
590
|
+
inputNamesFocused[input.name] = true;
|
|
591
|
+
if (group) {
|
|
592
|
+
feedbackGroups[group] = false;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
});
|
|
579
596
|
});
|
|
597
|
+
for (const [name, focused] of Object.entries(inputNamesFocused)) {
|
|
598
|
+
if (!focused) {
|
|
599
|
+
feedbacks.push(name);
|
|
600
|
+
if (name.endsWith("[]")) {
|
|
601
|
+
feedbacks.push(name.slice(0, -2));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
for (const [group, noFeedback] of Object.entries(feedbackGroups)) {
|
|
606
|
+
if (noFeedback)
|
|
607
|
+
feedbacks.push(group);
|
|
608
|
+
}
|
|
580
609
|
if (feedbacks.length > 0) {
|
|
581
610
|
let selector = feedbacks.map((f) => `[${phxFeedbackFor}="${f}"]`).join(", ");
|
|
582
611
|
DOM.all(container, selector, (el) => el.classList.add(PHX_NO_FEEDBACK_CLASS));
|
|
@@ -607,11 +636,19 @@ var LiveView = (() => {
|
|
|
607
636
|
isPhxSticky(node) {
|
|
608
637
|
return node.getAttribute && node.getAttribute(PHX_STICKY) !== null;
|
|
609
638
|
},
|
|
639
|
+
isChildOfAny(el, parents) {
|
|
640
|
+
return !!parents.find((parent) => parent.contains(el));
|
|
641
|
+
},
|
|
610
642
|
firstPhxChild(el) {
|
|
611
643
|
return this.isPhxChild(el) ? el : this.all(el, `[${PHX_PARENT_ID}]`)[0];
|
|
612
644
|
},
|
|
613
645
|
dispatchEvent(target, name, opts = {}) {
|
|
614
|
-
let
|
|
646
|
+
let defaultBubble = true;
|
|
647
|
+
let isUploadTarget = target.nodeName === "INPUT" && target.type === "file";
|
|
648
|
+
if (isUploadTarget && name === "click") {
|
|
649
|
+
defaultBubble = false;
|
|
650
|
+
}
|
|
651
|
+
let bubbles = opts.bubbles === void 0 ? defaultBubble : !!opts.bubbles;
|
|
615
652
|
let eventOpts = { bubbles, cancelable: true, detail: opts.detail || {} };
|
|
616
653
|
let event = name === "click" ? new MouseEvent("click", eventOpts) : new CustomEvent(name, eventOpts);
|
|
617
654
|
target.dispatchEvent(event);
|
|
@@ -626,20 +663,27 @@ var LiveView = (() => {
|
|
|
626
663
|
}
|
|
627
664
|
},
|
|
628
665
|
mergeAttrs(target, source, opts = {}) {
|
|
629
|
-
let exclude = opts.exclude || [];
|
|
666
|
+
let exclude = new Set(opts.exclude || []);
|
|
630
667
|
let isIgnored = opts.isIgnored;
|
|
631
668
|
let sourceAttrs = source.attributes;
|
|
632
669
|
for (let i = sourceAttrs.length - 1; i >= 0; i--) {
|
|
633
670
|
let name = sourceAttrs[i].name;
|
|
634
|
-
if (exclude.
|
|
635
|
-
|
|
671
|
+
if (!exclude.has(name)) {
|
|
672
|
+
const sourceValue = source.getAttribute(name);
|
|
673
|
+
if (target.getAttribute(name) !== sourceValue && (!isIgnored || isIgnored && name.startsWith("data-"))) {
|
|
674
|
+
target.setAttribute(name, sourceValue);
|
|
675
|
+
}
|
|
676
|
+
} else {
|
|
677
|
+
if (name === "value" && target.value === source.value) {
|
|
678
|
+
target.setAttribute("value", source.getAttribute(name));
|
|
679
|
+
}
|
|
636
680
|
}
|
|
637
681
|
}
|
|
638
682
|
let targetAttrs = target.attributes;
|
|
639
683
|
for (let i = targetAttrs.length - 1; i >= 0; i--) {
|
|
640
684
|
let name = targetAttrs[i].name;
|
|
641
685
|
if (isIgnored) {
|
|
642
|
-
if (name.startsWith("data-") && !source.hasAttribute(name)) {
|
|
686
|
+
if (name.startsWith("data-") && !source.hasAttribute(name) && ![PHX_REF, PHX_REF_SRC].includes(name)) {
|
|
643
687
|
target.removeAttribute(name);
|
|
644
688
|
}
|
|
645
689
|
} else {
|
|
@@ -663,6 +707,9 @@ var LiveView = (() => {
|
|
|
663
707
|
return el.setSelectionRange && (el.type === "text" || el.type === "textarea");
|
|
664
708
|
},
|
|
665
709
|
restoreFocus(focused, selectionStart, selectionEnd) {
|
|
710
|
+
if (focused instanceof HTMLSelectElement) {
|
|
711
|
+
focused.focus();
|
|
712
|
+
}
|
|
666
713
|
if (!DOM.isTextualInput(focused)) {
|
|
667
714
|
return;
|
|
668
715
|
}
|
|
@@ -786,15 +833,22 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
786
833
|
var UploadEntry = class {
|
|
787
834
|
static isActive(fileEl, file) {
|
|
788
835
|
let isNew = file._phxRef === void 0;
|
|
836
|
+
let isPreflightInProgress = UploadEntry.isPreflightInProgress(file);
|
|
789
837
|
let activeRefs = fileEl.getAttribute(PHX_ACTIVE_ENTRY_REFS).split(",");
|
|
790
838
|
let isActive = activeRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
|
|
791
|
-
return file.size > 0 && (isNew || isActive);
|
|
839
|
+
return file.size > 0 && (isNew || isActive || !isPreflightInProgress);
|
|
792
840
|
}
|
|
793
841
|
static isPreflighted(fileEl, file) {
|
|
794
842
|
let preflightedRefs = fileEl.getAttribute(PHX_PREFLIGHTED_REFS).split(",");
|
|
795
843
|
let isPreflighted = preflightedRefs.indexOf(LiveUploader.genFileRef(file)) >= 0;
|
|
796
844
|
return isPreflighted && this.isActive(fileEl, file);
|
|
797
845
|
}
|
|
846
|
+
static isPreflightInProgress(file) {
|
|
847
|
+
return file._preflightInProgress === true;
|
|
848
|
+
}
|
|
849
|
+
static markPreflightInProgress(file) {
|
|
850
|
+
file._preflightInProgress = true;
|
|
851
|
+
}
|
|
798
852
|
constructor(fileEl, file, view) {
|
|
799
853
|
this.ref = LiveUploader.genFileRef(file);
|
|
800
854
|
this.fileEl = fileEl;
|
|
@@ -961,12 +1015,16 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
961
1015
|
return Array.from(fileInputs).filter((input) => this.filesAwaitingPreflight(input).length > 0);
|
|
962
1016
|
}
|
|
963
1017
|
static filesAwaitingPreflight(input) {
|
|
964
|
-
return this.activeFiles(input).filter((f) => !UploadEntry.isPreflighted(input, f));
|
|
1018
|
+
return this.activeFiles(input).filter((f) => !UploadEntry.isPreflighted(input, f) && !UploadEntry.isPreflightInProgress(f));
|
|
1019
|
+
}
|
|
1020
|
+
static markPreflightInProgress(entries) {
|
|
1021
|
+
entries.forEach((entry) => UploadEntry.markPreflightInProgress(entry.file));
|
|
965
1022
|
}
|
|
966
1023
|
constructor(inputEl, view, onComplete) {
|
|
967
1024
|
this.view = view;
|
|
968
1025
|
this.onComplete = onComplete;
|
|
969
1026
|
this._entries = Array.from(LiveUploader.filesAwaitingPreflight(inputEl) || []).map((file) => new UploadEntry(inputEl, file, view));
|
|
1027
|
+
LiveUploader.markPreflightInProgress(this._entries);
|
|
970
1028
|
this.numEntriesInProgress = this._entries.length;
|
|
971
1029
|
}
|
|
972
1030
|
entries() {
|
|
@@ -1107,23 +1165,50 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1107
1165
|
}
|
|
1108
1166
|
}
|
|
1109
1167
|
};
|
|
1110
|
-
var
|
|
1111
|
-
|
|
1112
|
-
|
|
1168
|
+
var findScrollContainer = (el) => {
|
|
1169
|
+
if (["scroll", "auto"].indexOf(getComputedStyle(el).overflowY) >= 0)
|
|
1170
|
+
return el;
|
|
1171
|
+
if (document.documentElement === el)
|
|
1172
|
+
return null;
|
|
1173
|
+
return findScrollContainer(el.parentElement);
|
|
1174
|
+
};
|
|
1175
|
+
var scrollTop = (scrollContainer) => {
|
|
1176
|
+
if (scrollContainer) {
|
|
1177
|
+
return scrollContainer.scrollTop;
|
|
1178
|
+
} else {
|
|
1179
|
+
return document.documentElement.scrollTop || document.body.scrollTop;
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
var bottom = (scrollContainer) => {
|
|
1183
|
+
if (scrollContainer) {
|
|
1184
|
+
return scrollContainer.getBoundingClientRect().bottom;
|
|
1185
|
+
} else {
|
|
1186
|
+
return window.innerHeight || document.documentElement.clientHeight;
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
var top = (scrollContainer) => {
|
|
1190
|
+
if (scrollContainer) {
|
|
1191
|
+
return scrollContainer.getBoundingClientRect().top;
|
|
1192
|
+
} else {
|
|
1193
|
+
return 0;
|
|
1194
|
+
}
|
|
1195
|
+
};
|
|
1196
|
+
var isAtViewportTop = (el, scrollContainer) => {
|
|
1113
1197
|
let rect = el.getBoundingClientRect();
|
|
1114
|
-
return rect.top >=
|
|
1198
|
+
return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer);
|
|
1115
1199
|
};
|
|
1116
|
-
var isAtViewportBottom = (el) => {
|
|
1200
|
+
var isAtViewportBottom = (el, scrollContainer) => {
|
|
1117
1201
|
let rect = el.getBoundingClientRect();
|
|
1118
|
-
return rect.right >=
|
|
1202
|
+
return rect.right >= top(scrollContainer) && rect.left >= 0 && rect.bottom <= bottom(scrollContainer);
|
|
1119
1203
|
};
|
|
1120
|
-
var isWithinViewport = (el) => {
|
|
1204
|
+
var isWithinViewport = (el, scrollContainer) => {
|
|
1121
1205
|
let rect = el.getBoundingClientRect();
|
|
1122
|
-
return rect.top >=
|
|
1206
|
+
return rect.top >= top(scrollContainer) && rect.left >= 0 && rect.top <= bottom(scrollContainer);
|
|
1123
1207
|
};
|
|
1124
1208
|
Hooks.InfiniteScroll = {
|
|
1125
1209
|
mounted() {
|
|
1126
|
-
|
|
1210
|
+
this.scrollContainer = findScrollContainer(this.el);
|
|
1211
|
+
let scrollBefore = scrollTop(this.scrollContainer);
|
|
1127
1212
|
let topOverran = false;
|
|
1128
1213
|
let throttleInterval = 500;
|
|
1129
1214
|
let pendingOp = null;
|
|
@@ -1137,22 +1222,26 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1137
1222
|
pendingOp = () => firstChild.scrollIntoView({ block: "start" });
|
|
1138
1223
|
this.liveSocket.execJSHookPush(this.el, topEvent, { id: firstChild.id }, () => {
|
|
1139
1224
|
pendingOp = null;
|
|
1140
|
-
|
|
1141
|
-
firstChild.
|
|
1142
|
-
|
|
1225
|
+
window.requestAnimationFrame(() => {
|
|
1226
|
+
if (!isWithinViewport(firstChild, this.scrollContainer)) {
|
|
1227
|
+
firstChild.scrollIntoView({ block: "start" });
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1143
1230
|
});
|
|
1144
1231
|
});
|
|
1145
1232
|
let onLastChildAtBottom = this.throttle(throttleInterval, (bottomEvent, lastChild) => {
|
|
1146
1233
|
pendingOp = () => lastChild.scrollIntoView({ block: "end" });
|
|
1147
1234
|
this.liveSocket.execJSHookPush(this.el, bottomEvent, { id: lastChild.id }, () => {
|
|
1148
1235
|
pendingOp = null;
|
|
1149
|
-
|
|
1150
|
-
lastChild.
|
|
1151
|
-
|
|
1236
|
+
window.requestAnimationFrame(() => {
|
|
1237
|
+
if (!isWithinViewport(lastChild, this.scrollContainer)) {
|
|
1238
|
+
lastChild.scrollIntoView({ block: "end" });
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1152
1241
|
});
|
|
1153
1242
|
});
|
|
1154
|
-
this.onScroll = (
|
|
1155
|
-
let scrollNow = scrollTop();
|
|
1243
|
+
this.onScroll = (_e) => {
|
|
1244
|
+
let scrollNow = scrollTop(this.scrollContainer);
|
|
1156
1245
|
if (pendingOp) {
|
|
1157
1246
|
scrollBefore = scrollNow;
|
|
1158
1247
|
return pendingOp();
|
|
@@ -1170,17 +1259,25 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1170
1259
|
} else if (isScrollingDown && topOverran && rect.top <= 0) {
|
|
1171
1260
|
topOverran = false;
|
|
1172
1261
|
}
|
|
1173
|
-
if (topEvent && isScrollingUp && isAtViewportTop(firstChild)) {
|
|
1262
|
+
if (topEvent && isScrollingUp && isAtViewportTop(firstChild, this.scrollContainer)) {
|
|
1174
1263
|
onFirstChildAtTop(topEvent, firstChild);
|
|
1175
|
-
} else if (bottomEvent && isScrollingDown && isAtViewportBottom(lastChild)) {
|
|
1264
|
+
} else if (bottomEvent && isScrollingDown && isAtViewportBottom(lastChild, this.scrollContainer)) {
|
|
1176
1265
|
onLastChildAtBottom(bottomEvent, lastChild);
|
|
1177
1266
|
}
|
|
1178
1267
|
scrollBefore = scrollNow;
|
|
1179
1268
|
};
|
|
1180
|
-
|
|
1269
|
+
if (this.scrollContainer) {
|
|
1270
|
+
this.scrollContainer.addEventListener("scroll", this.onScroll);
|
|
1271
|
+
} else {
|
|
1272
|
+
window.addEventListener("scroll", this.onScroll);
|
|
1273
|
+
}
|
|
1181
1274
|
},
|
|
1182
1275
|
destroyed() {
|
|
1183
|
-
|
|
1276
|
+
if (this.scrollContainer) {
|
|
1277
|
+
this.scrollContainer.removeEventListener("scroll", this.onScroll);
|
|
1278
|
+
} else {
|
|
1279
|
+
window.removeEventListener("scroll", this.onScroll);
|
|
1280
|
+
}
|
|
1184
1281
|
},
|
|
1185
1282
|
throttle(interval, callback) {
|
|
1186
1283
|
let lastCallAt = 0;
|
|
@@ -1627,6 +1724,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1627
1724
|
removeNode(curFromNodeChild, fromEl, true);
|
|
1628
1725
|
}
|
|
1629
1726
|
curFromNodeChild = matchingFromEl;
|
|
1727
|
+
curFromNodeKey = getNodeKey(curFromNodeChild);
|
|
1630
1728
|
}
|
|
1631
1729
|
} else {
|
|
1632
1730
|
isCompatible = false;
|
|
@@ -1759,6 +1857,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1759
1857
|
this.html = html;
|
|
1760
1858
|
this.streams = streams;
|
|
1761
1859
|
this.streamInserts = {};
|
|
1860
|
+
this.streamComponentRestore = {};
|
|
1762
1861
|
this.targetCID = targetCID;
|
|
1763
1862
|
this.cidPatch = isCid(this.targetCID);
|
|
1764
1863
|
this.pendingRemoves = [];
|
|
@@ -1788,7 +1887,6 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1788
1887
|
}
|
|
1789
1888
|
markPrunableContentForRemoval() {
|
|
1790
1889
|
let phxUpdate = this.liveSocket.binding(PHX_UPDATE);
|
|
1791
|
-
dom_default.all(this.container, `[${phxUpdate}=${PHX_STREAM}]`, (el) => el.innerHTML = "");
|
|
1792
1890
|
dom_default.all(this.container, `[${phxUpdate}=append] > *, [${phxUpdate}=prepend] > *`, (el) => {
|
|
1793
1891
|
el.setAttribute(PHX_PRUNE, "");
|
|
1794
1892
|
});
|
|
@@ -1803,12 +1901,13 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1803
1901
|
let { selectionStart, selectionEnd } = focused && dom_default.hasSelectionRange(focused) ? focused : {};
|
|
1804
1902
|
let phxUpdate = liveSocket.binding(PHX_UPDATE);
|
|
1805
1903
|
let phxFeedbackFor = liveSocket.binding(PHX_FEEDBACK_FOR);
|
|
1904
|
+
let phxFeedbackGroup = liveSocket.binding(PHX_FEEDBACK_GROUP);
|
|
1806
1905
|
let disableWith = liveSocket.binding(PHX_DISABLE_WITH);
|
|
1807
1906
|
let phxViewportTop = liveSocket.binding(PHX_VIEWPORT_TOP);
|
|
1808
1907
|
let phxViewportBottom = liveSocket.binding(PHX_VIEWPORT_BOTTOM);
|
|
1809
1908
|
let phxTriggerExternal = liveSocket.binding(PHX_TRIGGER_ACTION);
|
|
1810
1909
|
let added = [];
|
|
1811
|
-
let
|
|
1910
|
+
let trackedForms = new Set();
|
|
1812
1911
|
let updates = [];
|
|
1813
1912
|
let appendPrependUpdates = [];
|
|
1814
1913
|
let externalFormTriggered = null;
|
|
@@ -1816,16 +1915,12 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1816
1915
|
this.trackBefore("updated", container, container);
|
|
1817
1916
|
liveSocket.time("morphdom", () => {
|
|
1818
1917
|
this.streams.forEach(([ref, inserts, deleteIds, reset]) => {
|
|
1819
|
-
|
|
1820
|
-
this.streamInserts[key] = { ref, streamAt, limit,
|
|
1918
|
+
inserts.forEach(([key, streamAt, limit]) => {
|
|
1919
|
+
this.streamInserts[key] = { ref, streamAt, limit, reset };
|
|
1821
1920
|
});
|
|
1822
1921
|
if (reset !== void 0) {
|
|
1823
1922
|
dom_default.all(container, `[${PHX_STREAM_REF}="${ref}"]`, (child) => {
|
|
1824
|
-
|
|
1825
|
-
this.streamInserts[child.id].resetKept = true;
|
|
1826
|
-
} else {
|
|
1827
|
-
this.removeStreamChildElement(child);
|
|
1828
|
-
}
|
|
1923
|
+
this.removeStreamChildElement(child);
|
|
1829
1924
|
});
|
|
1830
1925
|
}
|
|
1831
1926
|
deleteIds.forEach((id) => {
|
|
@@ -1835,6 +1930,17 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1835
1930
|
}
|
|
1836
1931
|
});
|
|
1837
1932
|
});
|
|
1933
|
+
if (isJoinPatch) {
|
|
1934
|
+
dom_default.all(this.container, `[${phxUpdate}=${PHX_STREAM}]`, (el) => {
|
|
1935
|
+
this.liveSocket.owner(el, (view2) => {
|
|
1936
|
+
if (view2 === this.view) {
|
|
1937
|
+
Array.from(el.children).forEach((child) => {
|
|
1938
|
+
this.removeStreamChildElement(child);
|
|
1939
|
+
});
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
});
|
|
1943
|
+
}
|
|
1838
1944
|
morphdom_esm_default(targetContainer, html, {
|
|
1839
1945
|
childrenOnly: targetContainer.getAttribute(PHX_COMPONENT) === null,
|
|
1840
1946
|
getNodeKey: (node) => {
|
|
@@ -1850,11 +1956,17 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1850
1956
|
return from.getAttribute(phxUpdate) === PHX_STREAM;
|
|
1851
1957
|
},
|
|
1852
1958
|
addChild: (parent, child) => {
|
|
1853
|
-
let { ref, streamAt
|
|
1959
|
+
let { ref, streamAt } = this.getStreamInsert(child);
|
|
1854
1960
|
if (ref === void 0) {
|
|
1855
1961
|
return parent.appendChild(child);
|
|
1856
1962
|
}
|
|
1857
|
-
|
|
1963
|
+
this.setStreamRef(child, ref);
|
|
1964
|
+
child.querySelectorAll(`[${PHX_MAGIC_ID}][${PHX_SKIP}]`).forEach((el) => {
|
|
1965
|
+
const component = this.streamComponentRestore[el.getAttribute(PHX_MAGIC_ID)];
|
|
1966
|
+
if (component) {
|
|
1967
|
+
el.replaceWith(component);
|
|
1968
|
+
}
|
|
1969
|
+
});
|
|
1858
1970
|
if (streamAt === 0) {
|
|
1859
1971
|
parent.insertAdjacentElement("afterbegin", child);
|
|
1860
1972
|
} else if (streamAt === -1) {
|
|
@@ -1863,18 +1975,6 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1863
1975
|
let sibling = Array.from(parent.children)[streamAt];
|
|
1864
1976
|
parent.insertBefore(child, sibling);
|
|
1865
1977
|
}
|
|
1866
|
-
let children = limit !== null && Array.from(parent.children);
|
|
1867
|
-
let childrenToRemove = [];
|
|
1868
|
-
if (limit && limit < 0 && children.length > limit * -1) {
|
|
1869
|
-
childrenToRemove = children.slice(0, children.length + limit);
|
|
1870
|
-
} else if (limit && limit >= 0 && children.length > limit) {
|
|
1871
|
-
childrenToRemove = children.slice(limit);
|
|
1872
|
-
}
|
|
1873
|
-
childrenToRemove.forEach((removeChild) => {
|
|
1874
|
-
if (!this.streamInserts[removeChild.id]) {
|
|
1875
|
-
this.removeStreamChildElement(removeChild);
|
|
1876
|
-
}
|
|
1877
|
-
});
|
|
1878
1978
|
},
|
|
1879
1979
|
onBeforeNodeAdded: (el) => {
|
|
1880
1980
|
dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom);
|
|
@@ -1883,7 +1983,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1883
1983
|
},
|
|
1884
1984
|
onNodeAdded: (el) => {
|
|
1885
1985
|
if (el.getAttribute) {
|
|
1886
|
-
this.maybeReOrderStream(el);
|
|
1986
|
+
this.maybeReOrderStream(el, true);
|
|
1887
1987
|
}
|
|
1888
1988
|
if (el instanceof HTMLImageElement && el.srcset) {
|
|
1889
1989
|
el.srcset = el.srcset;
|
|
@@ -1894,32 +1994,13 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1894
1994
|
externalFormTriggered = el;
|
|
1895
1995
|
}
|
|
1896
1996
|
if (el.getAttribute && el.getAttribute("name") && dom_default.isFormInput(el)) {
|
|
1897
|
-
|
|
1997
|
+
trackedForms.add(el.form);
|
|
1898
1998
|
}
|
|
1899
1999
|
if (dom_default.isPhxChild(el) && view.ownsElement(el) || dom_default.isPhxSticky(el) && view.ownsElement(el.parentNode)) {
|
|
1900
2000
|
this.trackAfter("phxChildAdded", el);
|
|
1901
2001
|
}
|
|
1902
2002
|
added.push(el);
|
|
1903
2003
|
},
|
|
1904
|
-
onBeforeElChildrenUpdated: (fromEl, toEl) => {
|
|
1905
|
-
if (fromEl.getAttribute(phxUpdate) === PHX_STREAM) {
|
|
1906
|
-
let toIds = Array.from(toEl.children).map((child) => child.id);
|
|
1907
|
-
Array.from(fromEl.children).filter((child) => {
|
|
1908
|
-
let { resetKept } = this.getStreamInsert(child);
|
|
1909
|
-
return resetKept;
|
|
1910
|
-
}).sort((a, b) => {
|
|
1911
|
-
let aIdx = toIds.indexOf(a.id);
|
|
1912
|
-
let bIdx = toIds.indexOf(b.id);
|
|
1913
|
-
if (aIdx === bIdx) {
|
|
1914
|
-
return 0;
|
|
1915
|
-
} else if (aIdx < bIdx) {
|
|
1916
|
-
return -1;
|
|
1917
|
-
} else {
|
|
1918
|
-
return 1;
|
|
1919
|
-
}
|
|
1920
|
-
}).forEach((child) => fromEl.appendChild(child));
|
|
1921
|
-
}
|
|
1922
|
-
},
|
|
1923
2004
|
onNodeDiscarded: (el) => this.onNodeDiscarded(el),
|
|
1924
2005
|
onBeforeNodeDiscarded: (el) => {
|
|
1925
2006
|
if (el.getAttribute && el.getAttribute(PHX_PRUNE) !== null) {
|
|
@@ -1941,12 +2022,13 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1941
2022
|
externalFormTriggered = el;
|
|
1942
2023
|
}
|
|
1943
2024
|
updates.push(el);
|
|
1944
|
-
this.maybeReOrderStream(el);
|
|
2025
|
+
this.maybeReOrderStream(el, false);
|
|
1945
2026
|
},
|
|
1946
2027
|
onBeforeElUpdated: (fromEl, toEl) => {
|
|
1947
2028
|
dom_default.maybeAddPrivateHooks(toEl, phxViewportTop, phxViewportBottom);
|
|
1948
2029
|
dom_default.cleanChildNodes(toEl, phxUpdate);
|
|
1949
2030
|
if (this.skipCIDSibling(toEl)) {
|
|
2031
|
+
this.maybeReOrderStream(fromEl);
|
|
1950
2032
|
return false;
|
|
1951
2033
|
}
|
|
1952
2034
|
if (dom_default.isPhxSticky(fromEl)) {
|
|
@@ -1982,22 +2064,26 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
1982
2064
|
}
|
|
1983
2065
|
dom_default.copyPrivates(toEl, fromEl);
|
|
1984
2066
|
let isFocusedFormEl = focused && fromEl.isSameNode(focused) && dom_default.isFormInput(fromEl);
|
|
1985
|
-
|
|
2067
|
+
let focusedSelectChanged = isFocusedFormEl && this.isChangedSelect(fromEl, toEl);
|
|
2068
|
+
if (isFocusedFormEl && fromEl.type !== "hidden" && !focusedSelectChanged) {
|
|
1986
2069
|
this.trackBefore("updated", fromEl, toEl);
|
|
1987
2070
|
dom_default.mergeFocusedInput(fromEl, toEl);
|
|
1988
2071
|
dom_default.syncAttrsToProps(fromEl);
|
|
1989
2072
|
updates.push(fromEl);
|
|
1990
2073
|
dom_default.applyStickyOperations(fromEl);
|
|
1991
|
-
|
|
2074
|
+
trackedForms.add(fromEl.form);
|
|
1992
2075
|
return false;
|
|
1993
2076
|
} else {
|
|
2077
|
+
if (focusedSelectChanged) {
|
|
2078
|
+
fromEl.blur();
|
|
2079
|
+
}
|
|
1994
2080
|
if (dom_default.isPhxUpdate(toEl, phxUpdate, ["append", "prepend"])) {
|
|
1995
2081
|
appendPrependUpdates.push(new DOMPostMorphRestorer(fromEl, toEl, toEl.getAttribute(phxUpdate)));
|
|
1996
2082
|
}
|
|
1997
2083
|
dom_default.syncAttrsToProps(toEl);
|
|
1998
2084
|
dom_default.applyStickyOperations(toEl);
|
|
1999
2085
|
if (toEl.getAttribute("name") && dom_default.isFormInput(toEl)) {
|
|
2000
|
-
|
|
2086
|
+
trackedForms.add(toEl.form);
|
|
2001
2087
|
}
|
|
2002
2088
|
this.trackBefore("updated", fromEl, toEl);
|
|
2003
2089
|
return true;
|
|
@@ -2013,7 +2099,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2013
2099
|
appendPrependUpdates.forEach((update) => update.perform());
|
|
2014
2100
|
});
|
|
2015
2101
|
}
|
|
2016
|
-
dom_default.maybeHideFeedback(targetContainer,
|
|
2102
|
+
dom_default.maybeHideFeedback(targetContainer, trackedForms, phxFeedbackFor, phxFeedbackGroup);
|
|
2017
2103
|
liveSocket.silenceEvents(() => dom_default.restoreFocus(focused, selectionStart, selectionEnd));
|
|
2018
2104
|
dom_default.dispatchEvent(document, "phx:update");
|
|
2019
2105
|
added.forEach((el) => this.trackAfter("added", el));
|
|
@@ -2041,6 +2127,11 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2041
2127
|
}
|
|
2042
2128
|
removeStreamChildElement(child) {
|
|
2043
2129
|
if (!this.maybePendingRemove(child)) {
|
|
2130
|
+
if (this.streamInserts[child.id]) {
|
|
2131
|
+
child.querySelectorAll(`[${PHX_MAGIC_ID}]`).forEach((el) => {
|
|
2132
|
+
this.streamComponentRestore[el.getAttribute(PHX_MAGIC_ID)] = el;
|
|
2133
|
+
});
|
|
2134
|
+
}
|
|
2044
2135
|
child.remove();
|
|
2045
2136
|
this.onNodeDiscarded(child);
|
|
2046
2137
|
}
|
|
@@ -2049,12 +2140,18 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2049
2140
|
let insert = el.id ? this.streamInserts[el.id] : {};
|
|
2050
2141
|
return insert || {};
|
|
2051
2142
|
}
|
|
2052
|
-
|
|
2053
|
-
|
|
2143
|
+
setStreamRef(el, ref) {
|
|
2144
|
+
dom_default.putSticky(el, PHX_STREAM_REF, (el2) => el2.setAttribute(PHX_STREAM_REF, ref));
|
|
2145
|
+
}
|
|
2146
|
+
maybeReOrderStream(el, isNew) {
|
|
2147
|
+
let { ref, streamAt, reset } = this.getStreamInsert(el);
|
|
2054
2148
|
if (streamAt === void 0) {
|
|
2055
2149
|
return;
|
|
2056
2150
|
}
|
|
2057
|
-
|
|
2151
|
+
this.setStreamRef(el, ref);
|
|
2152
|
+
if (!reset && !isNew) {
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2058
2155
|
if (streamAt === 0) {
|
|
2059
2156
|
el.parentElement.insertBefore(el, el.parentElement.firstElementChild);
|
|
2060
2157
|
} else if (streamAt > 0) {
|
|
@@ -2071,6 +2168,16 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2071
2168
|
}
|
|
2072
2169
|
}
|
|
2073
2170
|
}
|
|
2171
|
+
this.maybeLimitStream(el);
|
|
2172
|
+
}
|
|
2173
|
+
maybeLimitStream(el) {
|
|
2174
|
+
let { limit } = this.getStreamInsert(el);
|
|
2175
|
+
let children = limit !== null && Array.from(el.parentElement.children);
|
|
2176
|
+
if (limit && limit < 0 && children.length > limit * -1) {
|
|
2177
|
+
children.slice(0, children.length + limit).forEach((child) => this.removeStreamChildElement(child));
|
|
2178
|
+
} else if (limit && limit >= 0 && children.length > limit) {
|
|
2179
|
+
children.slice(limit).forEach((child) => this.removeStreamChildElement(child));
|
|
2180
|
+
}
|
|
2074
2181
|
}
|
|
2075
2182
|
transitionPendingRemoves() {
|
|
2076
2183
|
let { pendingRemoves, liveSocket } = this;
|
|
@@ -2088,6 +2195,20 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2088
2195
|
});
|
|
2089
2196
|
}
|
|
2090
2197
|
}
|
|
2198
|
+
isChangedSelect(fromEl, toEl) {
|
|
2199
|
+
if (!(fromEl instanceof HTMLSelectElement) || fromEl.multiple) {
|
|
2200
|
+
return false;
|
|
2201
|
+
}
|
|
2202
|
+
if (fromEl.options.length !== toEl.options.length) {
|
|
2203
|
+
return true;
|
|
2204
|
+
}
|
|
2205
|
+
let fromSelected = fromEl.selectedOptions[0];
|
|
2206
|
+
let toSelected = toEl.selectedOptions[0];
|
|
2207
|
+
if (fromSelected && fromSelected.hasAttribute("selected")) {
|
|
2208
|
+
toSelected.setAttribute("selected", fromSelected.getAttribute("selected"));
|
|
2209
|
+
}
|
|
2210
|
+
return !fromEl.isEqualNode(toEl);
|
|
2211
|
+
}
|
|
2091
2212
|
isCIDPatch() {
|
|
2092
2213
|
return this.cidPatch;
|
|
2093
2214
|
}
|
|
@@ -2129,66 +2250,42 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2129
2250
|
"track",
|
|
2130
2251
|
"wbr"
|
|
2131
2252
|
]);
|
|
2132
|
-
var endingTagNameChars = new Set([">", "/", " ", "\n", " ", "\r"]);
|
|
2133
2253
|
var quoteChars = new Set(["'", '"']);
|
|
2134
2254
|
var modifyRoot = (html, attrs, clearInnerHTML) => {
|
|
2135
2255
|
let i = 0;
|
|
2136
2256
|
let insideComment = false;
|
|
2137
2257
|
let beforeTag, afterTag, tag, tagNameEndsAt, id, newHTML;
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
let iAtOpen = i;
|
|
2258
|
+
let lookahead = html.match(/^(\s*(?:<!--.*?-->\s*)*)<([^\s\/>]+)/);
|
|
2259
|
+
if (lookahead === null) {
|
|
2260
|
+
throw new Error(`malformed html ${html}`);
|
|
2261
|
+
}
|
|
2262
|
+
i = lookahead[0].length;
|
|
2263
|
+
beforeTag = lookahead[1];
|
|
2264
|
+
tag = lookahead[2];
|
|
2265
|
+
tagNameEndsAt = i;
|
|
2266
|
+
for (i; i < html.length; i++) {
|
|
2267
|
+
if (html.charAt(i) === ">") {
|
|
2268
|
+
break;
|
|
2269
|
+
}
|
|
2270
|
+
if (html.charAt(i) === "=") {
|
|
2271
|
+
let isId = html.slice(i - 3, i) === " id";
|
|
2153
2272
|
i++;
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2273
|
+
let char = html.charAt(i);
|
|
2274
|
+
if (quoteChars.has(char)) {
|
|
2275
|
+
let attrStartsAt = i;
|
|
2276
|
+
i++;
|
|
2277
|
+
for (i; i < html.length; i++) {
|
|
2278
|
+
if (html.charAt(i) === char) {
|
|
2279
|
+
break;
|
|
2280
|
+
}
|
|
2157
2281
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
tag = html.slice(iAtOpen + 1, tagNameEndsAt);
|
|
2161
|
-
for (i; i < html.length; i++) {
|
|
2162
|
-
if (html.charAt(i) === ">") {
|
|
2282
|
+
if (isId) {
|
|
2283
|
+
id = html.slice(attrStartsAt + 1, i);
|
|
2163
2284
|
break;
|
|
2164
2285
|
}
|
|
2165
|
-
if (html.charAt(i) === "=") {
|
|
2166
|
-
let isId = html.slice(i - 3, i) === " id";
|
|
2167
|
-
i++;
|
|
2168
|
-
let char2 = html.charAt(i);
|
|
2169
|
-
if (quoteChars.has(char2)) {
|
|
2170
|
-
let attrStartsAt = i;
|
|
2171
|
-
i++;
|
|
2172
|
-
for (i; i < html.length; i++) {
|
|
2173
|
-
if (html.charAt(i) === char2) {
|
|
2174
|
-
break;
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
if (isId) {
|
|
2178
|
-
id = html.slice(attrStartsAt + 1, i);
|
|
2179
|
-
break;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
2286
|
}
|
|
2184
|
-
break;
|
|
2185
|
-
} else {
|
|
2186
|
-
i++;
|
|
2187
2287
|
}
|
|
2188
2288
|
}
|
|
2189
|
-
if (!tag) {
|
|
2190
|
-
throw new Error(`malformed html ${html}`);
|
|
2191
|
-
}
|
|
2192
2289
|
let closeAt = html.length - 1;
|
|
2193
2290
|
insideComment = false;
|
|
2194
2291
|
while (closeAt >= beforeTag.length + tag.length) {
|
|
@@ -2263,6 +2360,11 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2263
2360
|
getComponent(diff, cid) {
|
|
2264
2361
|
return diff[COMPONENTS][cid];
|
|
2265
2362
|
}
|
|
2363
|
+
resetRender(cid) {
|
|
2364
|
+
if (this.rendered[COMPONENTS][cid]) {
|
|
2365
|
+
this.rendered[COMPONENTS][cid].reset = true;
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2266
2368
|
mergeDiff(diff) {
|
|
2267
2369
|
let newc = diff[COMPONENTS];
|
|
2268
2370
|
let cache = {};
|
|
@@ -2390,8 +2492,8 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2390
2492
|
if (isRoot) {
|
|
2391
2493
|
let skip = false;
|
|
2392
2494
|
let attrs;
|
|
2393
|
-
if (changeTracking ||
|
|
2394
|
-
skip = !rendered.newRender;
|
|
2495
|
+
if (changeTracking || rendered.magicId) {
|
|
2496
|
+
skip = changeTracking && !rendered.newRender;
|
|
2395
2497
|
attrs = __spreadValues({ [PHX_MAGIC_ID]: rendered.magicId }, rootAttrs);
|
|
2396
2498
|
} else {
|
|
2397
2499
|
attrs = rootAttrs;
|
|
@@ -2441,8 +2543,9 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2441
2543
|
let skip = onlyCids && !onlyCids.has(cid);
|
|
2442
2544
|
component.newRender = !skip;
|
|
2443
2545
|
component.magicId = `${this.parentViewId()}-c-${cid}`;
|
|
2444
|
-
let changeTracking =
|
|
2546
|
+
let changeTracking = !component.reset;
|
|
2445
2547
|
let [html, streams] = this.recursiveToString(component, components, onlyCids, changeTracking, attrs);
|
|
2548
|
+
delete component.reset;
|
|
2446
2549
|
return [html, streams];
|
|
2447
2550
|
}
|
|
2448
2551
|
};
|
|
@@ -2526,6 +2629,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2526
2629
|
|
|
2527
2630
|
// js/phoenix_live_view/js.js
|
|
2528
2631
|
var focusStack = null;
|
|
2632
|
+
var default_transition_time = 200;
|
|
2529
2633
|
var JS = {
|
|
2530
2634
|
exec(eventType, phxEvent, view, sourceEl, defaults) {
|
|
2531
2635
|
let [defaultKind, defaultArgs] = defaults || [null, { callback: defaults && defaults.callback }];
|
|
@@ -2547,7 +2651,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2547
2651
|
const rect = el.getBoundingClientRect();
|
|
2548
2652
|
return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth);
|
|
2549
2653
|
},
|
|
2550
|
-
exec_exec(eventType, phxEvent, view, sourceEl, el,
|
|
2654
|
+
exec_exec(eventType, phxEvent, view, sourceEl, el, { attr, to }) {
|
|
2551
2655
|
let nodes = to ? dom_default.all(document, to) : [sourceEl];
|
|
2552
2656
|
nodes.forEach((node) => {
|
|
2553
2657
|
let encodedJS = node.getAttribute(attr);
|
|
@@ -2563,14 +2667,14 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2563
2667
|
dom_default.dispatchEvent(el, event, { detail, bubbles });
|
|
2564
2668
|
},
|
|
2565
2669
|
exec_push(eventType, phxEvent, view, sourceEl, el, args) {
|
|
2566
|
-
if (!view.isConnected()) {
|
|
2567
|
-
return;
|
|
2568
|
-
}
|
|
2569
2670
|
let { event, data, target, page_loading, loading, value, dispatcher, callback } = args;
|
|
2570
2671
|
let pushOpts = { loading, value, target, page_loading: !!page_loading };
|
|
2571
2672
|
let targetSrc = eventType === "change" && dispatcher ? dispatcher : sourceEl;
|
|
2572
2673
|
let phxTarget = target || targetSrc.getAttribute(view.binding("target")) || targetSrc;
|
|
2573
2674
|
view.withinTargets(phxTarget, (targetView, targetCtx) => {
|
|
2675
|
+
if (!targetView.isConnected()) {
|
|
2676
|
+
return;
|
|
2677
|
+
}
|
|
2574
2678
|
if (eventType === "change") {
|
|
2575
2679
|
let { newCid, _target } = args;
|
|
2576
2680
|
_target = _target || (dom_default.isFormInput(sourceEl) ? sourceEl.name : void 0);
|
|
@@ -2615,6 +2719,24 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2615
2719
|
exec_remove_class(eventType, phxEvent, view, sourceEl, el, { names, transition, time }) {
|
|
2616
2720
|
this.addOrRemoveClasses(el, [], names, transition, time, view);
|
|
2617
2721
|
},
|
|
2722
|
+
exec_toggle_class(eventType, phxEvent, view, sourceEl, el, { to, names, transition, time }) {
|
|
2723
|
+
this.toggleClasses(el, names, transition, view);
|
|
2724
|
+
},
|
|
2725
|
+
exec_toggle_attr(eventType, phxEvent, view, sourceEl, el, { attr: [attr, val1, val2] }) {
|
|
2726
|
+
if (el.hasAttribute(attr)) {
|
|
2727
|
+
if (val2 !== void 0) {
|
|
2728
|
+
if (el.getAttribute(attr) === val1) {
|
|
2729
|
+
this.setOrRemoveAttrs(el, [[attr, val2]], []);
|
|
2730
|
+
} else {
|
|
2731
|
+
this.setOrRemoveAttrs(el, [[attr, val1]], []);
|
|
2732
|
+
}
|
|
2733
|
+
} else {
|
|
2734
|
+
this.setOrRemoveAttrs(el, [], [attr]);
|
|
2735
|
+
}
|
|
2736
|
+
} else {
|
|
2737
|
+
this.setOrRemoveAttrs(el, [[attr, val1]], []);
|
|
2738
|
+
}
|
|
2739
|
+
},
|
|
2618
2740
|
exec_transition(eventType, phxEvent, view, sourceEl, el, { time, transition }) {
|
|
2619
2741
|
this.addOrRemoveClasses(el, [], [], transition, time, view);
|
|
2620
2742
|
},
|
|
@@ -2644,6 +2766,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2644
2766
|
}
|
|
2645
2767
|
},
|
|
2646
2768
|
toggle(eventType, view, el, display, ins, outs, time) {
|
|
2769
|
+
time = time || default_transition_time;
|
|
2647
2770
|
let [inClasses, inStartClasses, inEndClasses] = ins || [[], [], []];
|
|
2648
2771
|
let [outClasses, outStartClasses, outEndClasses] = outs || [[], [], []];
|
|
2649
2772
|
if (inClasses.length > 0 || outClasses.length > 0) {
|
|
@@ -2697,7 +2820,16 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2697
2820
|
}
|
|
2698
2821
|
}
|
|
2699
2822
|
},
|
|
2823
|
+
toggleClasses(el, classes, transition, time, view) {
|
|
2824
|
+
window.requestAnimationFrame(() => {
|
|
2825
|
+
let [prevAdds, prevRemoves] = dom_default.getSticky(el, "classes", [[], []]);
|
|
2826
|
+
let newAdds = classes.filter((name) => prevAdds.indexOf(name) < 0 && !el.classList.contains(name));
|
|
2827
|
+
let newRemoves = classes.filter((name) => prevRemoves.indexOf(name) < 0 && el.classList.contains(name));
|
|
2828
|
+
this.addOrRemoveClasses(el, newAdds, newRemoves, transition, time, view);
|
|
2829
|
+
});
|
|
2830
|
+
},
|
|
2700
2831
|
addOrRemoveClasses(el, adds, removes, transition, time, view) {
|
|
2832
|
+
time = time || default_transition_time;
|
|
2701
2833
|
let [transitionRun, transitionStart, transitionEnd] = transition || [[], [], []];
|
|
2702
2834
|
if (transitionRun.length > 0) {
|
|
2703
2835
|
let onStart = () => {
|
|
@@ -2751,24 +2883,37 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2751
2883
|
|
|
2752
2884
|
// js/phoenix_live_view/view.js
|
|
2753
2885
|
var serializeForm = (form, metadata, onlyNames = []) => {
|
|
2754
|
-
|
|
2755
|
-
let
|
|
2756
|
-
if (submitter && submitter.
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2886
|
+
const _a = metadata, { submitter } = _a, meta = __objRest(_a, ["submitter"]);
|
|
2887
|
+
let injectedElement;
|
|
2888
|
+
if (submitter && submitter.name) {
|
|
2889
|
+
const input = document.createElement("input");
|
|
2890
|
+
input.type = "hidden";
|
|
2891
|
+
const formId = submitter.getAttribute("form");
|
|
2892
|
+
if (formId) {
|
|
2893
|
+
input.setAttribute("form", form);
|
|
2894
|
+
}
|
|
2895
|
+
input.name = submitter.name;
|
|
2896
|
+
input.value = submitter.value;
|
|
2897
|
+
submitter.parentElement.insertBefore(input, submitter);
|
|
2898
|
+
injectedElement = input;
|
|
2899
|
+
}
|
|
2900
|
+
const formData = new FormData(form);
|
|
2901
|
+
const toRemove = [];
|
|
2760
2902
|
formData.forEach((val, key, _index) => {
|
|
2761
2903
|
if (val instanceof File) {
|
|
2762
2904
|
toRemove.push(key);
|
|
2763
2905
|
}
|
|
2764
2906
|
});
|
|
2765
2907
|
toRemove.forEach((key) => formData.delete(key));
|
|
2766
|
-
|
|
2908
|
+
const params = new URLSearchParams();
|
|
2767
2909
|
for (let [key, val] of formData.entries()) {
|
|
2768
2910
|
if (onlyNames.length === 0 || onlyNames.indexOf(key) >= 0) {
|
|
2769
2911
|
params.append(key, val);
|
|
2770
2912
|
}
|
|
2771
2913
|
}
|
|
2914
|
+
if (submitter && injectedElement) {
|
|
2915
|
+
submitter.parentElement.removeChild(injectedElement);
|
|
2916
|
+
}
|
|
2772
2917
|
for (let metaKey in meta) {
|
|
2773
2918
|
params.append(metaKey, meta[metaKey]);
|
|
2774
2919
|
}
|
|
@@ -2972,6 +3117,9 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
2972
3117
|
if (phxStatic) {
|
|
2973
3118
|
toEl.setAttribute(PHX_STATIC, phxStatic);
|
|
2974
3119
|
}
|
|
3120
|
+
if (fromEl) {
|
|
3121
|
+
fromEl.setAttribute(PHX_ROOT_ID, this.root.id);
|
|
3122
|
+
}
|
|
2975
3123
|
return this.joinChild(toEl);
|
|
2976
3124
|
});
|
|
2977
3125
|
if (newChildren.length === 0) {
|
|
@@ -3051,6 +3199,9 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3051
3199
|
let updatedHookIds = new Set();
|
|
3052
3200
|
patch.after("added", (el) => {
|
|
3053
3201
|
this.liveSocket.triggerDOM("onNodeAdded", [el]);
|
|
3202
|
+
let phxViewportTop = this.binding(PHX_VIEWPORT_TOP);
|
|
3203
|
+
let phxViewportBottom = this.binding(PHX_VIEWPORT_BOTTOM);
|
|
3204
|
+
dom_default.maybeAddPrivateHooks(el, phxViewportTop, phxViewportBottom);
|
|
3054
3205
|
this.maybeAddNewHook(el);
|
|
3055
3206
|
if (el.getAttribute) {
|
|
3056
3207
|
this.maybeMounted(el);
|
|
@@ -3427,10 +3578,11 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3427
3578
|
}
|
|
3428
3579
|
dom_default.all(document, `[${PHX_REF_SRC}="${this.id}"][${PHX_REF}="${ref}"]`, (el) => {
|
|
3429
3580
|
let disabledVal = el.getAttribute(PHX_DISABLED);
|
|
3581
|
+
let readOnlyVal = el.getAttribute(PHX_READONLY);
|
|
3430
3582
|
el.removeAttribute(PHX_REF);
|
|
3431
3583
|
el.removeAttribute(PHX_REF_SRC);
|
|
3432
|
-
if (
|
|
3433
|
-
el.readOnly = false;
|
|
3584
|
+
if (readOnlyVal !== null) {
|
|
3585
|
+
el.readOnly = readOnlyVal === "true" ? true : false;
|
|
3434
3586
|
el.removeAttribute(PHX_READONLY);
|
|
3435
3587
|
}
|
|
3436
3588
|
if (disabledVal !== null) {
|
|
@@ -3472,6 +3624,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3472
3624
|
if (disableText !== "") {
|
|
3473
3625
|
el.innerText = disableText;
|
|
3474
3626
|
}
|
|
3627
|
+
el.setAttribute(PHX_DISABLED, el.getAttribute(PHX_DISABLED) || el.disabled);
|
|
3475
3628
|
el.setAttribute("disabled", "");
|
|
3476
3629
|
}
|
|
3477
3630
|
});
|
|
@@ -3573,6 +3726,9 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3573
3726
|
let refGenerator = () => this.putRef([inputEl, inputEl.form], "change", opts);
|
|
3574
3727
|
let formData;
|
|
3575
3728
|
let meta = this.extractMeta(inputEl.form);
|
|
3729
|
+
if (inputEl instanceof HTMLButtonElement) {
|
|
3730
|
+
meta.submitter = inputEl;
|
|
3731
|
+
}
|
|
3576
3732
|
if (inputEl.getAttribute(this.binding("change"))) {
|
|
3577
3733
|
formData = serializeForm(inputEl.form, __spreadValues({ _target: opts._target }, meta), [inputEl.name]);
|
|
3578
3734
|
} else {
|
|
@@ -3597,6 +3753,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3597
3753
|
this.uploadFiles(inputEl.form, targetCtx, ref, cid, (_uploads) => {
|
|
3598
3754
|
callback && callback(resp);
|
|
3599
3755
|
this.triggerAwaitingSubmit(inputEl.form);
|
|
3756
|
+
this.undoRefs(ref);
|
|
3600
3757
|
});
|
|
3601
3758
|
}
|
|
3602
3759
|
} else {
|
|
@@ -3795,7 +3952,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3795
3952
|
let template = document.createElement("template");
|
|
3796
3953
|
template.innerHTML = html;
|
|
3797
3954
|
return dom_default.all(this.el, `form[${phxChange}]`).filter((form) => form.id && this.ownsElement(form)).filter((form) => form.elements.length > 0).filter((form) => form.getAttribute(this.binding(PHX_AUTO_RECOVER)) !== "ignore").map((form) => {
|
|
3798
|
-
const phxChangeValue = form.getAttribute(phxChange)
|
|
3955
|
+
const phxChangeValue = CSS.escape(form.getAttribute(phxChange));
|
|
3799
3956
|
let newForm = template.content.querySelector(`form[id="${form.id}"][${phxChange}="${phxChangeValue}"]`);
|
|
3800
3957
|
if (newForm) {
|
|
3801
3958
|
return [form, newForm, this.targetComponentID(newForm)];
|
|
@@ -3805,18 +3962,19 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
3805
3962
|
}).filter(([form, newForm, newCid]) => newForm);
|
|
3806
3963
|
}
|
|
3807
3964
|
maybePushComponentsDestroyed(destroyedCIDs) {
|
|
3808
|
-
let willDestroyCIDs = destroyedCIDs.filter((cid) => {
|
|
3965
|
+
let willDestroyCIDs = destroyedCIDs.concat(this.pruningCIDs).filter((cid) => {
|
|
3809
3966
|
return dom_default.findComponentNodeList(this.el, cid).length === 0;
|
|
3810
3967
|
});
|
|
3968
|
+
this.pruningCIDs = willDestroyCIDs.concat([]);
|
|
3811
3969
|
if (willDestroyCIDs.length > 0) {
|
|
3812
|
-
this.
|
|
3970
|
+
willDestroyCIDs.forEach((cid) => this.rendered.resetRender(cid));
|
|
3813
3971
|
this.pushWithReply(null, "cids_will_destroy", { cids: willDestroyCIDs }, () => {
|
|
3814
|
-
this.pruningCIDs = this.pruningCIDs.filter((cid) => willDestroyCIDs.indexOf(cid) !== -1);
|
|
3815
3972
|
let completelyDestroyCIDs = willDestroyCIDs.filter((cid) => {
|
|
3816
3973
|
return dom_default.findComponentNodeList(this.el, cid).length === 0;
|
|
3817
3974
|
});
|
|
3818
3975
|
if (completelyDestroyCIDs.length > 0) {
|
|
3819
3976
|
this.pushWithReply(null, "cids_destroyed", { cids: completelyDestroyCIDs }, (resp) => {
|
|
3977
|
+
this.pruningCIDs = this.pruningCIDs.filter((cid) => resp.cids.indexOf(cid) === -1);
|
|
3820
3978
|
this.rendered.pruneCIDs(resp.cids);
|
|
3821
3979
|
});
|
|
3822
3980
|
}
|
|
@@ -4132,22 +4290,26 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4132
4290
|
this.main.destroy();
|
|
4133
4291
|
this.main = this.newRootView(newMainEl, flash, liveReferer);
|
|
4134
4292
|
this.main.setRedirect(href);
|
|
4135
|
-
this.transitionRemoves();
|
|
4293
|
+
this.transitionRemoves(null, true);
|
|
4136
4294
|
this.main.join((joinCount, onDone) => {
|
|
4137
4295
|
if (joinCount === 1 && this.commitPendingLink(linkRef)) {
|
|
4138
4296
|
this.requestDOMUpdate(() => {
|
|
4139
4297
|
dom_default.findPhxSticky(document).forEach((el) => newMainEl.appendChild(el));
|
|
4140
4298
|
this.outgoingMainEl.replaceWith(newMainEl);
|
|
4141
4299
|
this.outgoingMainEl = null;
|
|
4142
|
-
callback &&
|
|
4300
|
+
callback && callback(linkRef);
|
|
4143
4301
|
onDone();
|
|
4144
4302
|
});
|
|
4145
4303
|
}
|
|
4146
4304
|
});
|
|
4147
4305
|
}
|
|
4148
|
-
transitionRemoves(elements) {
|
|
4306
|
+
transitionRemoves(elements, skipSticky) {
|
|
4149
4307
|
let removeAttr = this.binding("remove");
|
|
4150
4308
|
elements = elements || dom_default.all(document, `[${removeAttr}]`);
|
|
4309
|
+
if (skipSticky) {
|
|
4310
|
+
const stickies = dom_default.findPhxSticky(document) || [];
|
|
4311
|
+
elements = elements.filter((el) => !dom_default.isChildOfAny(el, stickies));
|
|
4312
|
+
}
|
|
4151
4313
|
elements.forEach((el) => {
|
|
4152
4314
|
this.execJS(el, el.getAttribute(removeAttr), "remove");
|
|
4153
4315
|
});
|
|
@@ -4363,6 +4525,8 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4363
4525
|
if (capture) {
|
|
4364
4526
|
target = e.target.matches(`[${click}]`) ? e.target : e.target.querySelector(`[${click}]`);
|
|
4365
4527
|
} else {
|
|
4528
|
+
if (e.detail === 0)
|
|
4529
|
+
this.clickStartedAtTarget = e.target;
|
|
4366
4530
|
let clickStartedAtTarget = this.clickStartedAtTarget || e.target;
|
|
4367
4531
|
target = closestPhxBinding(clickStartedAtTarget, click);
|
|
4368
4532
|
this.dispatchClickAway(e, clickStartedAtTarget);
|
|
@@ -4392,7 +4556,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4392
4556
|
let phxClickAway = this.binding("click-away");
|
|
4393
4557
|
dom_default.all(document, `[${phxClickAway}]`, (el) => {
|
|
4394
4558
|
if (!(el.isSameNode(clickStartedAt) || el.contains(clickStartedAt))) {
|
|
4395
|
-
this.withinOwners(
|
|
4559
|
+
this.withinOwners(el, (view) => {
|
|
4396
4560
|
let phxEvent = el.getAttribute(phxClickAway);
|
|
4397
4561
|
if (js_default.isVisible(el) && js_default.isInViewport(el)) {
|
|
4398
4562
|
js_default.exec("click", phxEvent, view, el, ["push", { data: this.eventMeta("click", e, e.target) }]);
|
|
@@ -4484,7 +4648,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4484
4648
|
return callback ? callback(done) : done;
|
|
4485
4649
|
}
|
|
4486
4650
|
pushHistoryPatch(href, linkState, targetEl) {
|
|
4487
|
-
if (!this.isConnected()) {
|
|
4651
|
+
if (!this.isConnected() || !this.main.isMain()) {
|
|
4488
4652
|
return browser_default.redirect(href);
|
|
4489
4653
|
}
|
|
4490
4654
|
this.withPageLoading({ to: href, kind: "patch" }, (done) => {
|
|
@@ -4503,7 +4667,7 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4503
4667
|
this.registerNewLocation(window.location);
|
|
4504
4668
|
}
|
|
4505
4669
|
historyRedirect(href, linkState, flash) {
|
|
4506
|
-
if (!this.isConnected()) {
|
|
4670
|
+
if (!this.isConnected() || !this.main.isMain()) {
|
|
4507
4671
|
return browser_default.redirect(href, flash);
|
|
4508
4672
|
}
|
|
4509
4673
|
if (/^\/$|^\/[^\/]+.*$/.test(href)) {
|
|
@@ -4604,9 +4768,11 @@ removing illegal node: "${(childNode.outerHTML || childNode.nodeValue).trim()}"
|
|
|
4604
4768
|
let form = e.target;
|
|
4605
4769
|
dom_default.resetForm(form, this.binding(PHX_FEEDBACK_FOR));
|
|
4606
4770
|
let input = Array.from(form.elements).find((el) => el.type === "reset");
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4771
|
+
if (input) {
|
|
4772
|
+
window.requestAnimationFrame(() => {
|
|
4773
|
+
input.dispatchEvent(new Event("input", { bubbles: true, cancelable: false }));
|
|
4774
|
+
});
|
|
4775
|
+
}
|
|
4610
4776
|
});
|
|
4611
4777
|
}
|
|
4612
4778
|
debounce(el, event, eventType, callback) {
|