@hotwired/turbo 8.0.3 → 8.0.5
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/dist/turbo.es2017-esm.js +170 -158
- package/dist/turbo.es2017-umd.js +170 -158
- package/package.json +1 -1
package/dist/turbo.es2017-esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.
|
|
2
|
+
Turbo 8.0.5
|
|
3
3
|
Copyright © 2024 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
@@ -126,7 +126,7 @@ class FrameElement extends HTMLElement {
|
|
|
126
126
|
loaded = Promise.resolve()
|
|
127
127
|
|
|
128
128
|
static get observedAttributes() {
|
|
129
|
-
return ["disabled", "
|
|
129
|
+
return ["disabled", "loading", "src"]
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
constructor() {
|
|
@@ -149,11 +149,9 @@ class FrameElement extends HTMLElement {
|
|
|
149
149
|
attributeChangedCallback(name) {
|
|
150
150
|
if (name == "loading") {
|
|
151
151
|
this.delegate.loadingStyleChanged();
|
|
152
|
-
} else if (name == "complete") {
|
|
153
|
-
this.delegate.completeChanged();
|
|
154
152
|
} else if (name == "src") {
|
|
155
153
|
this.delegate.sourceURLChanged();
|
|
156
|
-
} else {
|
|
154
|
+
} else if (name == "disabled") {
|
|
157
155
|
this.delegate.disabledChanged();
|
|
158
156
|
}
|
|
159
157
|
}
|
|
@@ -633,14 +631,18 @@ async function around(callback, reader) {
|
|
|
633
631
|
return [before, after]
|
|
634
632
|
}
|
|
635
633
|
|
|
636
|
-
function doesNotTargetIFrame(
|
|
637
|
-
if (
|
|
638
|
-
|
|
634
|
+
function doesNotTargetIFrame(name) {
|
|
635
|
+
if (name === "_blank") {
|
|
636
|
+
return false
|
|
637
|
+
} else if (name) {
|
|
638
|
+
for (const element of document.getElementsByName(name)) {
|
|
639
639
|
if (element instanceof HTMLIFrameElement) return false
|
|
640
640
|
}
|
|
641
|
-
}
|
|
642
641
|
|
|
643
|
-
|
|
642
|
+
return true
|
|
643
|
+
} else {
|
|
644
|
+
return true
|
|
645
|
+
}
|
|
644
646
|
}
|
|
645
647
|
|
|
646
648
|
function findLinkFromClickTarget(target) {
|
|
@@ -746,7 +748,7 @@ class FetchRequest {
|
|
|
746
748
|
this.fetchOptions = {
|
|
747
749
|
credentials: "same-origin",
|
|
748
750
|
redirect: "follow",
|
|
749
|
-
method: method,
|
|
751
|
+
method: method.toUpperCase(),
|
|
750
752
|
headers: { ...this.defaultHeaders },
|
|
751
753
|
body: body,
|
|
752
754
|
signal: this.abortSignal,
|
|
@@ -769,7 +771,7 @@ class FetchRequest {
|
|
|
769
771
|
|
|
770
772
|
this.url = url;
|
|
771
773
|
this.fetchOptions.body = body;
|
|
772
|
-
this.fetchOptions.method = fetchMethod;
|
|
774
|
+
this.fetchOptions.method = fetchMethod.toUpperCase();
|
|
773
775
|
}
|
|
774
776
|
|
|
775
777
|
get headers() {
|
|
@@ -1400,17 +1402,9 @@ function submissionDoesNotDismissDialog(form, submitter) {
|
|
|
1400
1402
|
}
|
|
1401
1403
|
|
|
1402
1404
|
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
1403
|
-
|
|
1404
|
-
const target = submitter?.getAttribute("formtarget") || form.target;
|
|
1405
|
-
|
|
1406
|
-
for (const element of document.getElementsByName(target)) {
|
|
1407
|
-
if (element instanceof HTMLIFrameElement) return false
|
|
1408
|
-
}
|
|
1405
|
+
const target = submitter?.getAttribute("formtarget") || form.getAttribute("target");
|
|
1409
1406
|
|
|
1410
|
-
|
|
1411
|
-
} else {
|
|
1412
|
-
return true
|
|
1413
|
-
}
|
|
1407
|
+
return doesNotTargetIFrame(target)
|
|
1414
1408
|
}
|
|
1415
1409
|
|
|
1416
1410
|
class View {
|
|
@@ -1563,7 +1557,7 @@ class LinkInterceptor {
|
|
|
1563
1557
|
}
|
|
1564
1558
|
|
|
1565
1559
|
clickBubbled = (event) => {
|
|
1566
|
-
if (this.
|
|
1560
|
+
if (this.clickEventIsSignificant(event)) {
|
|
1567
1561
|
this.clickEvent = event;
|
|
1568
1562
|
} else {
|
|
1569
1563
|
delete this.clickEvent;
|
|
@@ -1571,7 +1565,7 @@ class LinkInterceptor {
|
|
|
1571
1565
|
}
|
|
1572
1566
|
|
|
1573
1567
|
linkClicked = (event) => {
|
|
1574
|
-
if (this.clickEvent && this.
|
|
1568
|
+
if (this.clickEvent && this.clickEventIsSignificant(event)) {
|
|
1575
1569
|
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
|
|
1576
1570
|
this.clickEvent.preventDefault();
|
|
1577
1571
|
event.preventDefault();
|
|
@@ -1585,9 +1579,11 @@ class LinkInterceptor {
|
|
|
1585
1579
|
delete this.clickEvent;
|
|
1586
1580
|
}
|
|
1587
1581
|
|
|
1588
|
-
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1582
|
+
clickEventIsSignificant(event) {
|
|
1583
|
+
const target = event.composed ? event.target?.parentElement : event.target;
|
|
1584
|
+
const element = findLinkFromClickTarget(target) || target;
|
|
1585
|
+
|
|
1586
|
+
return element instanceof Element && element.closest("turbo-frame, html") == this.element
|
|
1591
1587
|
}
|
|
1592
1588
|
}
|
|
1593
1589
|
|
|
@@ -1622,7 +1618,7 @@ class LinkClickObserver {
|
|
|
1622
1618
|
if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
|
|
1623
1619
|
const target = (event.composedPath && event.composedPath()[0]) || event.target;
|
|
1624
1620
|
const link = findLinkFromClickTarget(target);
|
|
1625
|
-
if (link && doesNotTargetIFrame(link)) {
|
|
1621
|
+
if (link && doesNotTargetIFrame(link.target)) {
|
|
1626
1622
|
const location = getLocationForLink(link);
|
|
1627
1623
|
if (this.delegate.willFollowLinkToLocation(link, location, event)) {
|
|
1628
1624
|
event.preventDefault();
|
|
@@ -1791,6 +1787,10 @@ class Renderer {
|
|
|
1791
1787
|
return true
|
|
1792
1788
|
}
|
|
1793
1789
|
|
|
1790
|
+
get shouldAutofocus() {
|
|
1791
|
+
return true
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
1794
|
get reloadReason() {
|
|
1795
1795
|
return
|
|
1796
1796
|
}
|
|
@@ -1815,9 +1815,11 @@ class Renderer {
|
|
|
1815
1815
|
}
|
|
1816
1816
|
|
|
1817
1817
|
focusFirstAutofocusableElement() {
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
element
|
|
1818
|
+
if (this.shouldAutofocus) {
|
|
1819
|
+
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
1820
|
+
if (element) {
|
|
1821
|
+
element.focus();
|
|
1822
|
+
}
|
|
1821
1823
|
}
|
|
1822
1824
|
}
|
|
1823
1825
|
|
|
@@ -3168,7 +3170,7 @@ class LinkPrefetchObserver {
|
|
|
3168
3170
|
}
|
|
3169
3171
|
|
|
3170
3172
|
#tryToUsePrefetchedRequest = (event) => {
|
|
3171
|
-
if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "
|
|
3173
|
+
if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "GET") {
|
|
3172
3174
|
const cached = prefetchCache.get(event.detail.url.toString());
|
|
3173
3175
|
|
|
3174
3176
|
if (cached) {
|
|
@@ -3385,6 +3387,7 @@ class Navigator {
|
|
|
3385
3387
|
|
|
3386
3388
|
visitCompleted(visit) {
|
|
3387
3389
|
this.delegate.visitCompleted(visit);
|
|
3390
|
+
delete this.currentVisit;
|
|
3388
3391
|
}
|
|
3389
3392
|
|
|
3390
3393
|
locationWithActionIsSamePage(location, action) {
|
|
@@ -4567,6 +4570,81 @@ var Idiomorph = (function () {
|
|
|
4567
4570
|
}
|
|
4568
4571
|
})();
|
|
4569
4572
|
|
|
4573
|
+
function morphElements(currentElement, newElement, { callbacks, ...options } = {}) {
|
|
4574
|
+
Idiomorph.morph(currentElement, newElement, {
|
|
4575
|
+
...options,
|
|
4576
|
+
callbacks: new DefaultIdiomorphCallbacks(callbacks)
|
|
4577
|
+
});
|
|
4578
|
+
}
|
|
4579
|
+
|
|
4580
|
+
function morphChildren(currentElement, newElement) {
|
|
4581
|
+
morphElements(currentElement, newElement.children, {
|
|
4582
|
+
morphStyle: "innerHTML"
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4586
|
+
class DefaultIdiomorphCallbacks {
|
|
4587
|
+
#beforeNodeMorphed
|
|
4588
|
+
|
|
4589
|
+
constructor({ beforeNodeMorphed } = {}) {
|
|
4590
|
+
this.#beforeNodeMorphed = beforeNodeMorphed || (() => true);
|
|
4591
|
+
}
|
|
4592
|
+
|
|
4593
|
+
beforeNodeAdded = (node) => {
|
|
4594
|
+
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4595
|
+
}
|
|
4596
|
+
|
|
4597
|
+
beforeNodeMorphed = (currentElement, newElement) => {
|
|
4598
|
+
if (currentElement instanceof Element) {
|
|
4599
|
+
if (!currentElement.hasAttribute("data-turbo-permanent") && this.#beforeNodeMorphed(currentElement, newElement)) {
|
|
4600
|
+
const event = dispatch("turbo:before-morph-element", {
|
|
4601
|
+
cancelable: true,
|
|
4602
|
+
target: currentElement,
|
|
4603
|
+
detail: { currentElement, newElement }
|
|
4604
|
+
});
|
|
4605
|
+
|
|
4606
|
+
return !event.defaultPrevented
|
|
4607
|
+
} else {
|
|
4608
|
+
return false
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
}
|
|
4612
|
+
|
|
4613
|
+
beforeAttributeUpdated = (attributeName, target, mutationType) => {
|
|
4614
|
+
const event = dispatch("turbo:before-morph-attribute", {
|
|
4615
|
+
cancelable: true,
|
|
4616
|
+
target,
|
|
4617
|
+
detail: { attributeName, mutationType }
|
|
4618
|
+
});
|
|
4619
|
+
|
|
4620
|
+
return !event.defaultPrevented
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4623
|
+
beforeNodeRemoved = (node) => {
|
|
4624
|
+
return this.beforeNodeMorphed(node)
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4627
|
+
afterNodeMorphed = (currentElement, newElement) => {
|
|
4628
|
+
if (currentElement instanceof Element) {
|
|
4629
|
+
dispatch("turbo:morph-element", {
|
|
4630
|
+
target: currentElement,
|
|
4631
|
+
detail: { currentElement, newElement }
|
|
4632
|
+
});
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
|
|
4637
|
+
class MorphingFrameRenderer extends FrameRenderer {
|
|
4638
|
+
static renderElement(currentElement, newElement) {
|
|
4639
|
+
dispatch("turbo:before-frame-morph", {
|
|
4640
|
+
target: currentElement,
|
|
4641
|
+
detail: { currentElement, newElement }
|
|
4642
|
+
});
|
|
4643
|
+
|
|
4644
|
+
morphChildren(currentElement, newElement);
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
|
|
4570
4648
|
class PageRenderer extends Renderer {
|
|
4571
4649
|
static renderElement(currentElement, newElement) {
|
|
4572
4650
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
@@ -4779,119 +4857,47 @@ class PageRenderer extends Renderer {
|
|
|
4779
4857
|
}
|
|
4780
4858
|
}
|
|
4781
4859
|
|
|
4782
|
-
class
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
}
|
|
4786
|
-
|
|
4787
|
-
get renderMethod() {
|
|
4788
|
-
return "morph"
|
|
4789
|
-
}
|
|
4790
|
-
|
|
4791
|
-
// Private
|
|
4792
|
-
|
|
4793
|
-
async #morphBody() {
|
|
4794
|
-
this.#morphElements(this.currentElement, this.newElement);
|
|
4795
|
-
this.#reloadRemoteFrames();
|
|
4796
|
-
|
|
4797
|
-
dispatch("turbo:morph", {
|
|
4798
|
-
detail: {
|
|
4799
|
-
currentElement: this.currentElement,
|
|
4800
|
-
newElement: this.newElement
|
|
4801
|
-
}
|
|
4802
|
-
});
|
|
4803
|
-
}
|
|
4804
|
-
|
|
4805
|
-
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4806
|
-
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4807
|
-
|
|
4808
|
-
Idiomorph.morph(currentElement, newElement, {
|
|
4809
|
-
morphStyle: morphStyle,
|
|
4860
|
+
class MorphingPageRenderer extends PageRenderer {
|
|
4861
|
+
static renderElement(currentElement, newElement) {
|
|
4862
|
+
morphElements(currentElement, newElement, {
|
|
4810
4863
|
callbacks: {
|
|
4811
|
-
|
|
4812
|
-
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4813
|
-
beforeAttributeUpdated: this.#shouldUpdateAttribute,
|
|
4814
|
-
beforeNodeRemoved: this.#shouldRemoveElement,
|
|
4815
|
-
afterNodeMorphed: this.#didMorphElement
|
|
4864
|
+
beforeNodeMorphed: element => !canRefreshFrame(element)
|
|
4816
4865
|
}
|
|
4817
4866
|
});
|
|
4818
|
-
}
|
|
4819
4867
|
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
}
|
|
4823
|
-
|
|
4824
|
-
#shouldMorphElement = (oldNode, newNode) => {
|
|
4825
|
-
if (oldNode instanceof HTMLElement) {
|
|
4826
|
-
if (!oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))) {
|
|
4827
|
-
const event = dispatch("turbo:before-morph-element", {
|
|
4828
|
-
cancelable: true,
|
|
4829
|
-
target: oldNode,
|
|
4830
|
-
detail: {
|
|
4831
|
-
newElement: newNode
|
|
4832
|
-
}
|
|
4833
|
-
});
|
|
4834
|
-
|
|
4835
|
-
return !event.defaultPrevented
|
|
4836
|
-
} else {
|
|
4837
|
-
return false
|
|
4838
|
-
}
|
|
4868
|
+
for (const frame of currentElement.querySelectorAll("turbo-frame")) {
|
|
4869
|
+
if (canRefreshFrame(frame)) refreshFrame(frame);
|
|
4839
4870
|
}
|
|
4840
|
-
}
|
|
4841
|
-
|
|
4842
|
-
#shouldUpdateAttribute = (attributeName, target, mutationType) => {
|
|
4843
|
-
const event = dispatch("turbo:before-morph-attribute", { cancelable: true, target, detail: { attributeName, mutationType } });
|
|
4844
4871
|
|
|
4845
|
-
|
|
4872
|
+
dispatch("turbo:morph", { detail: { currentElement, newElement } });
|
|
4846
4873
|
}
|
|
4847
4874
|
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
dispatch("turbo:morph-element", {
|
|
4851
|
-
target: oldNode,
|
|
4852
|
-
detail: {
|
|
4853
|
-
newElement: newNode
|
|
4854
|
-
}
|
|
4855
|
-
});
|
|
4856
|
-
}
|
|
4857
|
-
}
|
|
4858
|
-
|
|
4859
|
-
#shouldRemoveElement = (node) => {
|
|
4860
|
-
return this.#shouldMorphElement(node)
|
|
4875
|
+
async preservingPermanentElements(callback) {
|
|
4876
|
+
return await callback()
|
|
4861
4877
|
}
|
|
4862
4878
|
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4866
|
-
this.#renderFrameWithMorph(frame);
|
|
4867
|
-
frame.reload();
|
|
4868
|
-
}
|
|
4869
|
-
});
|
|
4879
|
+
get renderMethod() {
|
|
4880
|
+
return "morph"
|
|
4870
4881
|
}
|
|
4871
4882
|
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
event.detail.render = this.#morphFrameUpdate;
|
|
4875
|
-
}, { once: true });
|
|
4883
|
+
get shouldAutofocus() {
|
|
4884
|
+
return false
|
|
4876
4885
|
}
|
|
4886
|
+
}
|
|
4877
4887
|
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
}
|
|
4888
|
+
function canRefreshFrame(frame) {
|
|
4889
|
+
return frame instanceof FrameElement &&
|
|
4890
|
+
frame.src &&
|
|
4891
|
+
frame.refresh === "morph" &&
|
|
4892
|
+
!frame.closest("[data-turbo-permanent]")
|
|
4893
|
+
}
|
|
4885
4894
|
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4895
|
+
function refreshFrame(frame) {
|
|
4896
|
+
frame.addEventListener("turbo:before-frame-render", ({ detail }) => {
|
|
4897
|
+
detail.render = MorphingFrameRenderer.renderElement;
|
|
4898
|
+
}, { once: true });
|
|
4889
4899
|
|
|
4890
|
-
|
|
4891
|
-
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4892
|
-
return !frame.closest('[data-turbo-permanent]')
|
|
4893
|
-
})
|
|
4894
|
-
}
|
|
4900
|
+
frame.reload();
|
|
4895
4901
|
}
|
|
4896
4902
|
|
|
4897
4903
|
class SnapshotCache {
|
|
@@ -4960,9 +4966,9 @@ class PageView extends View {
|
|
|
4960
4966
|
|
|
4961
4967
|
renderPage(snapshot, isPreview = false, willRender = true, visit) {
|
|
4962
4968
|
const shouldMorphPage = this.isPageRefresh(visit) && this.snapshot.shouldMorphPage;
|
|
4963
|
-
const rendererClass = shouldMorphPage ?
|
|
4969
|
+
const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;
|
|
4964
4970
|
|
|
4965
|
-
const renderer = new rendererClass(this.snapshot, snapshot,
|
|
4971
|
+
const renderer = new rendererClass(this.snapshot, snapshot, rendererClass.renderElement, isPreview, willRender);
|
|
4966
4972
|
|
|
4967
4973
|
if (!renderer.shouldRender) {
|
|
4968
4974
|
this.forceReloaded = true;
|
|
@@ -5198,7 +5204,7 @@ class Session {
|
|
|
5198
5204
|
|
|
5199
5205
|
refresh(url, requestId) {
|
|
5200
5206
|
const isRecentRequest = requestId && this.recentRequests.has(requestId);
|
|
5201
|
-
if (!isRecentRequest) {
|
|
5207
|
+
if (!isRecentRequest && !this.navigator.currentVisit) {
|
|
5202
5208
|
this.visit(url, { action: "replace", shouldCacheSnapshot: false });
|
|
5203
5209
|
}
|
|
5204
5210
|
}
|
|
@@ -5773,20 +5779,12 @@ class FrameController {
|
|
|
5773
5779
|
|
|
5774
5780
|
sourceURLReloaded() {
|
|
5775
5781
|
const { src } = this.element;
|
|
5776
|
-
this
|
|
5777
|
-
this.element.removeAttribute("complete");
|
|
5778
|
-
});
|
|
5782
|
+
this.element.removeAttribute("complete");
|
|
5779
5783
|
this.element.src = null;
|
|
5780
5784
|
this.element.src = src;
|
|
5781
5785
|
return this.element.loaded
|
|
5782
5786
|
}
|
|
5783
5787
|
|
|
5784
|
-
completeChanged() {
|
|
5785
|
-
if (this.#isIgnoringChangesTo("complete")) return
|
|
5786
|
-
|
|
5787
|
-
this.#loadSourceURL();
|
|
5788
|
-
}
|
|
5789
|
-
|
|
5790
5788
|
loadingStyleChanged() {
|
|
5791
5789
|
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
5792
5790
|
this.appearanceObserver.start();
|
|
@@ -6211,13 +6209,11 @@ class FrameController {
|
|
|
6211
6209
|
}
|
|
6212
6210
|
|
|
6213
6211
|
set complete(value) {
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
}
|
|
6220
|
-
});
|
|
6212
|
+
if (value) {
|
|
6213
|
+
this.element.setAttribute("complete", "");
|
|
6214
|
+
} else {
|
|
6215
|
+
this.element.removeAttribute("complete");
|
|
6216
|
+
}
|
|
6221
6217
|
}
|
|
6222
6218
|
|
|
6223
6219
|
get isActive() {
|
|
@@ -6298,13 +6294,27 @@ const StreamActions = {
|
|
|
6298
6294
|
},
|
|
6299
6295
|
|
|
6300
6296
|
replace() {
|
|
6301
|
-
|
|
6297
|
+
const method = this.getAttribute("method");
|
|
6298
|
+
|
|
6299
|
+
this.targetElements.forEach((targetElement) => {
|
|
6300
|
+
if (method === "morph") {
|
|
6301
|
+
morphElements(targetElement, this.templateContent);
|
|
6302
|
+
} else {
|
|
6303
|
+
targetElement.replaceWith(this.templateContent);
|
|
6304
|
+
}
|
|
6305
|
+
});
|
|
6302
6306
|
},
|
|
6303
6307
|
|
|
6304
6308
|
update() {
|
|
6309
|
+
const method = this.getAttribute("method");
|
|
6310
|
+
|
|
6305
6311
|
this.targetElements.forEach((targetElement) => {
|
|
6306
|
-
|
|
6307
|
-
|
|
6312
|
+
if (method === "morph") {
|
|
6313
|
+
morphChildren(targetElement, this.templateContent);
|
|
6314
|
+
} else {
|
|
6315
|
+
targetElement.innerHTML = "";
|
|
6316
|
+
targetElement.append(this.templateContent);
|
|
6317
|
+
}
|
|
6308
6318
|
});
|
|
6309
6319
|
},
|
|
6310
6320
|
|
|
@@ -6318,20 +6328,22 @@ const StreamActions = {
|
|
|
6318
6328
|
/**
|
|
6319
6329
|
* Renders updates to the page from a stream of messages.
|
|
6320
6330
|
*
|
|
6321
|
-
* Using the `action` attribute, this can be configured one of
|
|
6331
|
+
* Using the `action` attribute, this can be configured one of eight ways:
|
|
6322
6332
|
*
|
|
6323
|
-
* - `append` - appends the result to the container
|
|
6324
|
-
* - `prepend` - prepends the result to the container
|
|
6325
|
-
* - `replace` - replaces the contents of the container
|
|
6326
|
-
* - `remove` - removes the container
|
|
6327
|
-
* - `before` - inserts the result before the target
|
|
6328
6333
|
* - `after` - inserts the result after the target
|
|
6334
|
+
* - `append` - appends the result to the target
|
|
6335
|
+
* - `before` - inserts the result before the target
|
|
6336
|
+
* - `prepend` - prepends the result to the target
|
|
6337
|
+
* - `refresh` - initiates a page refresh
|
|
6338
|
+
* - `remove` - removes the target
|
|
6339
|
+
* - `replace` - replaces the outer HTML of the target
|
|
6340
|
+
* - `update` - replaces the inner HTML of the target
|
|
6329
6341
|
*
|
|
6330
6342
|
* @customElement turbo-stream
|
|
6331
6343
|
* @example
|
|
6332
6344
|
* <turbo-stream action="append" target="dom_id">
|
|
6333
6345
|
* <template>
|
|
6334
|
-
* Content to append to
|
|
6346
|
+
* Content to append to target designated with the dom_id.
|
|
6335
6347
|
* </template>
|
|
6336
6348
|
* </turbo-stream>
|
|
6337
6349
|
*/
|
package/dist/turbo.es2017-umd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.
|
|
2
|
+
Turbo 8.0.5
|
|
3
3
|
Copyright © 2024 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
@@ -132,7 +132,7 @@ Copyright © 2024 37signals LLC
|
|
|
132
132
|
loaded = Promise.resolve()
|
|
133
133
|
|
|
134
134
|
static get observedAttributes() {
|
|
135
|
-
return ["disabled", "
|
|
135
|
+
return ["disabled", "loading", "src"]
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
constructor() {
|
|
@@ -155,11 +155,9 @@ Copyright © 2024 37signals LLC
|
|
|
155
155
|
attributeChangedCallback(name) {
|
|
156
156
|
if (name == "loading") {
|
|
157
157
|
this.delegate.loadingStyleChanged();
|
|
158
|
-
} else if (name == "complete") {
|
|
159
|
-
this.delegate.completeChanged();
|
|
160
158
|
} else if (name == "src") {
|
|
161
159
|
this.delegate.sourceURLChanged();
|
|
162
|
-
} else {
|
|
160
|
+
} else if (name == "disabled") {
|
|
163
161
|
this.delegate.disabledChanged();
|
|
164
162
|
}
|
|
165
163
|
}
|
|
@@ -639,14 +637,18 @@ Copyright © 2024 37signals LLC
|
|
|
639
637
|
return [before, after]
|
|
640
638
|
}
|
|
641
639
|
|
|
642
|
-
function doesNotTargetIFrame(
|
|
643
|
-
if (
|
|
644
|
-
|
|
640
|
+
function doesNotTargetIFrame(name) {
|
|
641
|
+
if (name === "_blank") {
|
|
642
|
+
return false
|
|
643
|
+
} else if (name) {
|
|
644
|
+
for (const element of document.getElementsByName(name)) {
|
|
645
645
|
if (element instanceof HTMLIFrameElement) return false
|
|
646
646
|
}
|
|
647
|
-
}
|
|
648
647
|
|
|
649
|
-
|
|
648
|
+
return true
|
|
649
|
+
} else {
|
|
650
|
+
return true
|
|
651
|
+
}
|
|
650
652
|
}
|
|
651
653
|
|
|
652
654
|
function findLinkFromClickTarget(target) {
|
|
@@ -752,7 +754,7 @@ Copyright © 2024 37signals LLC
|
|
|
752
754
|
this.fetchOptions = {
|
|
753
755
|
credentials: "same-origin",
|
|
754
756
|
redirect: "follow",
|
|
755
|
-
method: method,
|
|
757
|
+
method: method.toUpperCase(),
|
|
756
758
|
headers: { ...this.defaultHeaders },
|
|
757
759
|
body: body,
|
|
758
760
|
signal: this.abortSignal,
|
|
@@ -775,7 +777,7 @@ Copyright © 2024 37signals LLC
|
|
|
775
777
|
|
|
776
778
|
this.url = url;
|
|
777
779
|
this.fetchOptions.body = body;
|
|
778
|
-
this.fetchOptions.method = fetchMethod;
|
|
780
|
+
this.fetchOptions.method = fetchMethod.toUpperCase();
|
|
779
781
|
}
|
|
780
782
|
|
|
781
783
|
get headers() {
|
|
@@ -1406,17 +1408,9 @@ Copyright © 2024 37signals LLC
|
|
|
1406
1408
|
}
|
|
1407
1409
|
|
|
1408
1410
|
function submissionDoesNotTargetIFrame(form, submitter) {
|
|
1409
|
-
|
|
1410
|
-
const target = submitter?.getAttribute("formtarget") || form.target;
|
|
1411
|
-
|
|
1412
|
-
for (const element of document.getElementsByName(target)) {
|
|
1413
|
-
if (element instanceof HTMLIFrameElement) return false
|
|
1414
|
-
}
|
|
1411
|
+
const target = submitter?.getAttribute("formtarget") || form.getAttribute("target");
|
|
1415
1412
|
|
|
1416
|
-
|
|
1417
|
-
} else {
|
|
1418
|
-
return true
|
|
1419
|
-
}
|
|
1413
|
+
return doesNotTargetIFrame(target)
|
|
1420
1414
|
}
|
|
1421
1415
|
|
|
1422
1416
|
class View {
|
|
@@ -1569,7 +1563,7 @@ Copyright © 2024 37signals LLC
|
|
|
1569
1563
|
}
|
|
1570
1564
|
|
|
1571
1565
|
clickBubbled = (event) => {
|
|
1572
|
-
if (this.
|
|
1566
|
+
if (this.clickEventIsSignificant(event)) {
|
|
1573
1567
|
this.clickEvent = event;
|
|
1574
1568
|
} else {
|
|
1575
1569
|
delete this.clickEvent;
|
|
@@ -1577,7 +1571,7 @@ Copyright © 2024 37signals LLC
|
|
|
1577
1571
|
}
|
|
1578
1572
|
|
|
1579
1573
|
linkClicked = (event) => {
|
|
1580
|
-
if (this.clickEvent && this.
|
|
1574
|
+
if (this.clickEvent && this.clickEventIsSignificant(event)) {
|
|
1581
1575
|
if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
|
|
1582
1576
|
this.clickEvent.preventDefault();
|
|
1583
1577
|
event.preventDefault();
|
|
@@ -1591,9 +1585,11 @@ Copyright © 2024 37signals LLC
|
|
|
1591
1585
|
delete this.clickEvent;
|
|
1592
1586
|
}
|
|
1593
1587
|
|
|
1594
|
-
|
|
1595
|
-
const
|
|
1596
|
-
|
|
1588
|
+
clickEventIsSignificant(event) {
|
|
1589
|
+
const target = event.composed ? event.target?.parentElement : event.target;
|
|
1590
|
+
const element = findLinkFromClickTarget(target) || target;
|
|
1591
|
+
|
|
1592
|
+
return element instanceof Element && element.closest("turbo-frame, html") == this.element
|
|
1597
1593
|
}
|
|
1598
1594
|
}
|
|
1599
1595
|
|
|
@@ -1628,7 +1624,7 @@ Copyright © 2024 37signals LLC
|
|
|
1628
1624
|
if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
|
|
1629
1625
|
const target = (event.composedPath && event.composedPath()[0]) || event.target;
|
|
1630
1626
|
const link = findLinkFromClickTarget(target);
|
|
1631
|
-
if (link && doesNotTargetIFrame(link)) {
|
|
1627
|
+
if (link && doesNotTargetIFrame(link.target)) {
|
|
1632
1628
|
const location = getLocationForLink(link);
|
|
1633
1629
|
if (this.delegate.willFollowLinkToLocation(link, location, event)) {
|
|
1634
1630
|
event.preventDefault();
|
|
@@ -1797,6 +1793,10 @@ Copyright © 2024 37signals LLC
|
|
|
1797
1793
|
return true
|
|
1798
1794
|
}
|
|
1799
1795
|
|
|
1796
|
+
get shouldAutofocus() {
|
|
1797
|
+
return true
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
1800
|
get reloadReason() {
|
|
1801
1801
|
return
|
|
1802
1802
|
}
|
|
@@ -1821,9 +1821,11 @@ Copyright © 2024 37signals LLC
|
|
|
1821
1821
|
}
|
|
1822
1822
|
|
|
1823
1823
|
focusFirstAutofocusableElement() {
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
element
|
|
1824
|
+
if (this.shouldAutofocus) {
|
|
1825
|
+
const element = this.connectedSnapshot.firstAutofocusableElement;
|
|
1826
|
+
if (element) {
|
|
1827
|
+
element.focus();
|
|
1828
|
+
}
|
|
1827
1829
|
}
|
|
1828
1830
|
}
|
|
1829
1831
|
|
|
@@ -3174,7 +3176,7 @@ Copyright © 2024 37signals LLC
|
|
|
3174
3176
|
}
|
|
3175
3177
|
|
|
3176
3178
|
#tryToUsePrefetchedRequest = (event) => {
|
|
3177
|
-
if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "
|
|
3179
|
+
if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "GET") {
|
|
3178
3180
|
const cached = prefetchCache.get(event.detail.url.toString());
|
|
3179
3181
|
|
|
3180
3182
|
if (cached) {
|
|
@@ -3391,6 +3393,7 @@ Copyright © 2024 37signals LLC
|
|
|
3391
3393
|
|
|
3392
3394
|
visitCompleted(visit) {
|
|
3393
3395
|
this.delegate.visitCompleted(visit);
|
|
3396
|
+
delete this.currentVisit;
|
|
3394
3397
|
}
|
|
3395
3398
|
|
|
3396
3399
|
locationWithActionIsSamePage(location, action) {
|
|
@@ -4573,6 +4576,81 @@ Copyright © 2024 37signals LLC
|
|
|
4573
4576
|
}
|
|
4574
4577
|
})();
|
|
4575
4578
|
|
|
4579
|
+
function morphElements(currentElement, newElement, { callbacks, ...options } = {}) {
|
|
4580
|
+
Idiomorph.morph(currentElement, newElement, {
|
|
4581
|
+
...options,
|
|
4582
|
+
callbacks: new DefaultIdiomorphCallbacks(callbacks)
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4586
|
+
function morphChildren(currentElement, newElement) {
|
|
4587
|
+
morphElements(currentElement, newElement.children, {
|
|
4588
|
+
morphStyle: "innerHTML"
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4591
|
+
|
|
4592
|
+
class DefaultIdiomorphCallbacks {
|
|
4593
|
+
#beforeNodeMorphed
|
|
4594
|
+
|
|
4595
|
+
constructor({ beforeNodeMorphed } = {}) {
|
|
4596
|
+
this.#beforeNodeMorphed = beforeNodeMorphed || (() => true);
|
|
4597
|
+
}
|
|
4598
|
+
|
|
4599
|
+
beforeNodeAdded = (node) => {
|
|
4600
|
+
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4603
|
+
beforeNodeMorphed = (currentElement, newElement) => {
|
|
4604
|
+
if (currentElement instanceof Element) {
|
|
4605
|
+
if (!currentElement.hasAttribute("data-turbo-permanent") && this.#beforeNodeMorphed(currentElement, newElement)) {
|
|
4606
|
+
const event = dispatch("turbo:before-morph-element", {
|
|
4607
|
+
cancelable: true,
|
|
4608
|
+
target: currentElement,
|
|
4609
|
+
detail: { currentElement, newElement }
|
|
4610
|
+
});
|
|
4611
|
+
|
|
4612
|
+
return !event.defaultPrevented
|
|
4613
|
+
} else {
|
|
4614
|
+
return false
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
|
|
4619
|
+
beforeAttributeUpdated = (attributeName, target, mutationType) => {
|
|
4620
|
+
const event = dispatch("turbo:before-morph-attribute", {
|
|
4621
|
+
cancelable: true,
|
|
4622
|
+
target,
|
|
4623
|
+
detail: { attributeName, mutationType }
|
|
4624
|
+
});
|
|
4625
|
+
|
|
4626
|
+
return !event.defaultPrevented
|
|
4627
|
+
}
|
|
4628
|
+
|
|
4629
|
+
beforeNodeRemoved = (node) => {
|
|
4630
|
+
return this.beforeNodeMorphed(node)
|
|
4631
|
+
}
|
|
4632
|
+
|
|
4633
|
+
afterNodeMorphed = (currentElement, newElement) => {
|
|
4634
|
+
if (currentElement instanceof Element) {
|
|
4635
|
+
dispatch("turbo:morph-element", {
|
|
4636
|
+
target: currentElement,
|
|
4637
|
+
detail: { currentElement, newElement }
|
|
4638
|
+
});
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
}
|
|
4642
|
+
|
|
4643
|
+
class MorphingFrameRenderer extends FrameRenderer {
|
|
4644
|
+
static renderElement(currentElement, newElement) {
|
|
4645
|
+
dispatch("turbo:before-frame-morph", {
|
|
4646
|
+
target: currentElement,
|
|
4647
|
+
detail: { currentElement, newElement }
|
|
4648
|
+
});
|
|
4649
|
+
|
|
4650
|
+
morphChildren(currentElement, newElement);
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
|
|
4576
4654
|
class PageRenderer extends Renderer {
|
|
4577
4655
|
static renderElement(currentElement, newElement) {
|
|
4578
4656
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
|
@@ -4785,119 +4863,47 @@ Copyright © 2024 37signals LLC
|
|
|
4785
4863
|
}
|
|
4786
4864
|
}
|
|
4787
4865
|
|
|
4788
|
-
class
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
}
|
|
4792
|
-
|
|
4793
|
-
get renderMethod() {
|
|
4794
|
-
return "morph"
|
|
4795
|
-
}
|
|
4796
|
-
|
|
4797
|
-
// Private
|
|
4798
|
-
|
|
4799
|
-
async #morphBody() {
|
|
4800
|
-
this.#morphElements(this.currentElement, this.newElement);
|
|
4801
|
-
this.#reloadRemoteFrames();
|
|
4802
|
-
|
|
4803
|
-
dispatch("turbo:morph", {
|
|
4804
|
-
detail: {
|
|
4805
|
-
currentElement: this.currentElement,
|
|
4806
|
-
newElement: this.newElement
|
|
4807
|
-
}
|
|
4808
|
-
});
|
|
4809
|
-
}
|
|
4810
|
-
|
|
4811
|
-
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
|
4812
|
-
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
|
4813
|
-
|
|
4814
|
-
Idiomorph.morph(currentElement, newElement, {
|
|
4815
|
-
morphStyle: morphStyle,
|
|
4866
|
+
class MorphingPageRenderer extends PageRenderer {
|
|
4867
|
+
static renderElement(currentElement, newElement) {
|
|
4868
|
+
morphElements(currentElement, newElement, {
|
|
4816
4869
|
callbacks: {
|
|
4817
|
-
|
|
4818
|
-
beforeNodeMorphed: this.#shouldMorphElement,
|
|
4819
|
-
beforeAttributeUpdated: this.#shouldUpdateAttribute,
|
|
4820
|
-
beforeNodeRemoved: this.#shouldRemoveElement,
|
|
4821
|
-
afterNodeMorphed: this.#didMorphElement
|
|
4870
|
+
beforeNodeMorphed: element => !canRefreshFrame(element)
|
|
4822
4871
|
}
|
|
4823
4872
|
});
|
|
4824
|
-
}
|
|
4825
4873
|
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
}
|
|
4829
|
-
|
|
4830
|
-
#shouldMorphElement = (oldNode, newNode) => {
|
|
4831
|
-
if (oldNode instanceof HTMLElement) {
|
|
4832
|
-
if (!oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))) {
|
|
4833
|
-
const event = dispatch("turbo:before-morph-element", {
|
|
4834
|
-
cancelable: true,
|
|
4835
|
-
target: oldNode,
|
|
4836
|
-
detail: {
|
|
4837
|
-
newElement: newNode
|
|
4838
|
-
}
|
|
4839
|
-
});
|
|
4840
|
-
|
|
4841
|
-
return !event.defaultPrevented
|
|
4842
|
-
} else {
|
|
4843
|
-
return false
|
|
4844
|
-
}
|
|
4874
|
+
for (const frame of currentElement.querySelectorAll("turbo-frame")) {
|
|
4875
|
+
if (canRefreshFrame(frame)) refreshFrame(frame);
|
|
4845
4876
|
}
|
|
4846
|
-
}
|
|
4847
|
-
|
|
4848
|
-
#shouldUpdateAttribute = (attributeName, target, mutationType) => {
|
|
4849
|
-
const event = dispatch("turbo:before-morph-attribute", { cancelable: true, target, detail: { attributeName, mutationType } });
|
|
4850
4877
|
|
|
4851
|
-
|
|
4878
|
+
dispatch("turbo:morph", { detail: { currentElement, newElement } });
|
|
4852
4879
|
}
|
|
4853
4880
|
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
dispatch("turbo:morph-element", {
|
|
4857
|
-
target: oldNode,
|
|
4858
|
-
detail: {
|
|
4859
|
-
newElement: newNode
|
|
4860
|
-
}
|
|
4861
|
-
});
|
|
4862
|
-
}
|
|
4863
|
-
}
|
|
4864
|
-
|
|
4865
|
-
#shouldRemoveElement = (node) => {
|
|
4866
|
-
return this.#shouldMorphElement(node)
|
|
4881
|
+
async preservingPermanentElements(callback) {
|
|
4882
|
+
return await callback()
|
|
4867
4883
|
}
|
|
4868
4884
|
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
if (this.#isFrameReloadedWithMorph(frame)) {
|
|
4872
|
-
this.#renderFrameWithMorph(frame);
|
|
4873
|
-
frame.reload();
|
|
4874
|
-
}
|
|
4875
|
-
});
|
|
4885
|
+
get renderMethod() {
|
|
4886
|
+
return "morph"
|
|
4876
4887
|
}
|
|
4877
4888
|
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
event.detail.render = this.#morphFrameUpdate;
|
|
4881
|
-
}, { once: true });
|
|
4889
|
+
get shouldAutofocus() {
|
|
4890
|
+
return false
|
|
4882
4891
|
}
|
|
4892
|
+
}
|
|
4883
4893
|
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
}
|
|
4894
|
+
function canRefreshFrame(frame) {
|
|
4895
|
+
return frame instanceof FrameElement &&
|
|
4896
|
+
frame.src &&
|
|
4897
|
+
frame.refresh === "morph" &&
|
|
4898
|
+
!frame.closest("[data-turbo-permanent]")
|
|
4899
|
+
}
|
|
4891
4900
|
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4901
|
+
function refreshFrame(frame) {
|
|
4902
|
+
frame.addEventListener("turbo:before-frame-render", ({ detail }) => {
|
|
4903
|
+
detail.render = MorphingFrameRenderer.renderElement;
|
|
4904
|
+
}, { once: true });
|
|
4895
4905
|
|
|
4896
|
-
|
|
4897
|
-
return Array.from(document.querySelectorAll('turbo-frame[src]')).filter(frame => {
|
|
4898
|
-
return !frame.closest('[data-turbo-permanent]')
|
|
4899
|
-
})
|
|
4900
|
-
}
|
|
4906
|
+
frame.reload();
|
|
4901
4907
|
}
|
|
4902
4908
|
|
|
4903
4909
|
class SnapshotCache {
|
|
@@ -4966,9 +4972,9 @@ Copyright © 2024 37signals LLC
|
|
|
4966
4972
|
|
|
4967
4973
|
renderPage(snapshot, isPreview = false, willRender = true, visit) {
|
|
4968
4974
|
const shouldMorphPage = this.isPageRefresh(visit) && this.snapshot.shouldMorphPage;
|
|
4969
|
-
const rendererClass = shouldMorphPage ?
|
|
4975
|
+
const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;
|
|
4970
4976
|
|
|
4971
|
-
const renderer = new rendererClass(this.snapshot, snapshot,
|
|
4977
|
+
const renderer = new rendererClass(this.snapshot, snapshot, rendererClass.renderElement, isPreview, willRender);
|
|
4972
4978
|
|
|
4973
4979
|
if (!renderer.shouldRender) {
|
|
4974
4980
|
this.forceReloaded = true;
|
|
@@ -5204,7 +5210,7 @@ Copyright © 2024 37signals LLC
|
|
|
5204
5210
|
|
|
5205
5211
|
refresh(url, requestId) {
|
|
5206
5212
|
const isRecentRequest = requestId && this.recentRequests.has(requestId);
|
|
5207
|
-
if (!isRecentRequest) {
|
|
5213
|
+
if (!isRecentRequest && !this.navigator.currentVisit) {
|
|
5208
5214
|
this.visit(url, { action: "replace", shouldCacheSnapshot: false });
|
|
5209
5215
|
}
|
|
5210
5216
|
}
|
|
@@ -5779,20 +5785,12 @@ Copyright © 2024 37signals LLC
|
|
|
5779
5785
|
|
|
5780
5786
|
sourceURLReloaded() {
|
|
5781
5787
|
const { src } = this.element;
|
|
5782
|
-
this
|
|
5783
|
-
this.element.removeAttribute("complete");
|
|
5784
|
-
});
|
|
5788
|
+
this.element.removeAttribute("complete");
|
|
5785
5789
|
this.element.src = null;
|
|
5786
5790
|
this.element.src = src;
|
|
5787
5791
|
return this.element.loaded
|
|
5788
5792
|
}
|
|
5789
5793
|
|
|
5790
|
-
completeChanged() {
|
|
5791
|
-
if (this.#isIgnoringChangesTo("complete")) return
|
|
5792
|
-
|
|
5793
|
-
this.#loadSourceURL();
|
|
5794
|
-
}
|
|
5795
|
-
|
|
5796
5794
|
loadingStyleChanged() {
|
|
5797
5795
|
if (this.loadingStyle == FrameLoadingStyle.lazy) {
|
|
5798
5796
|
this.appearanceObserver.start();
|
|
@@ -6217,13 +6215,11 @@ Copyright © 2024 37signals LLC
|
|
|
6217
6215
|
}
|
|
6218
6216
|
|
|
6219
6217
|
set complete(value) {
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
}
|
|
6226
|
-
});
|
|
6218
|
+
if (value) {
|
|
6219
|
+
this.element.setAttribute("complete", "");
|
|
6220
|
+
} else {
|
|
6221
|
+
this.element.removeAttribute("complete");
|
|
6222
|
+
}
|
|
6227
6223
|
}
|
|
6228
6224
|
|
|
6229
6225
|
get isActive() {
|
|
@@ -6304,13 +6300,27 @@ Copyright © 2024 37signals LLC
|
|
|
6304
6300
|
},
|
|
6305
6301
|
|
|
6306
6302
|
replace() {
|
|
6307
|
-
|
|
6303
|
+
const method = this.getAttribute("method");
|
|
6304
|
+
|
|
6305
|
+
this.targetElements.forEach((targetElement) => {
|
|
6306
|
+
if (method === "morph") {
|
|
6307
|
+
morphElements(targetElement, this.templateContent);
|
|
6308
|
+
} else {
|
|
6309
|
+
targetElement.replaceWith(this.templateContent);
|
|
6310
|
+
}
|
|
6311
|
+
});
|
|
6308
6312
|
},
|
|
6309
6313
|
|
|
6310
6314
|
update() {
|
|
6315
|
+
const method = this.getAttribute("method");
|
|
6316
|
+
|
|
6311
6317
|
this.targetElements.forEach((targetElement) => {
|
|
6312
|
-
|
|
6313
|
-
|
|
6318
|
+
if (method === "morph") {
|
|
6319
|
+
morphChildren(targetElement, this.templateContent);
|
|
6320
|
+
} else {
|
|
6321
|
+
targetElement.innerHTML = "";
|
|
6322
|
+
targetElement.append(this.templateContent);
|
|
6323
|
+
}
|
|
6314
6324
|
});
|
|
6315
6325
|
},
|
|
6316
6326
|
|
|
@@ -6324,20 +6334,22 @@ Copyright © 2024 37signals LLC
|
|
|
6324
6334
|
/**
|
|
6325
6335
|
* Renders updates to the page from a stream of messages.
|
|
6326
6336
|
*
|
|
6327
|
-
* Using the `action` attribute, this can be configured one of
|
|
6337
|
+
* Using the `action` attribute, this can be configured one of eight ways:
|
|
6328
6338
|
*
|
|
6329
|
-
* - `append` - appends the result to the container
|
|
6330
|
-
* - `prepend` - prepends the result to the container
|
|
6331
|
-
* - `replace` - replaces the contents of the container
|
|
6332
|
-
* - `remove` - removes the container
|
|
6333
|
-
* - `before` - inserts the result before the target
|
|
6334
6339
|
* - `after` - inserts the result after the target
|
|
6340
|
+
* - `append` - appends the result to the target
|
|
6341
|
+
* - `before` - inserts the result before the target
|
|
6342
|
+
* - `prepend` - prepends the result to the target
|
|
6343
|
+
* - `refresh` - initiates a page refresh
|
|
6344
|
+
* - `remove` - removes the target
|
|
6345
|
+
* - `replace` - replaces the outer HTML of the target
|
|
6346
|
+
* - `update` - replaces the inner HTML of the target
|
|
6335
6347
|
*
|
|
6336
6348
|
* @customElement turbo-stream
|
|
6337
6349
|
* @example
|
|
6338
6350
|
* <turbo-stream action="append" target="dom_id">
|
|
6339
6351
|
* <template>
|
|
6340
|
-
* Content to append to
|
|
6352
|
+
* Content to append to target designated with the dom_id.
|
|
6341
6353
|
* </template>
|
|
6342
6354
|
* </turbo-stream>
|
|
6343
6355
|
*/
|
package/package.json
CHANGED