turbo-rails 2.0.16 → 2.0.20
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/turbo.js +136 -57
- data/app/assets/javascripts/turbo.min.js +6 -6
- data/app/assets/javascripts/turbo.min.js.map +1 -1
- data/app/models/concerns/turbo/broadcastable.rb +1 -1
- data/lib/turbo/version.rb +1 -1
- metadata +3 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 06430d7095a020ded9bf6f76888c703184a7ffdd0c99e91f5461644c7fbdd062
|
|
4
|
+
data.tar.gz: b8b15ac1f37352d7a75782fe095c621340bb648eb24b5e36009634441efe098f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e4d105df336ab191ba9c3673bec4d47d7b4aa561cc3a865ada719ea5c478f70587a55bdd0b97a55b5846ab39afd6b18d863e50f74ec0c40657a407b00ad2cb2a
|
|
7
|
+
data.tar.gz: 9b293373d747dbe2964328636a3c5d4eae68fbf522a2f704948c0ea53b671c90ad8b13c8049e1a327a25127691e3cc9c3814634ae5cb9d174f94d9ff54c4f3b0
|
data/README.md
CHANGED
|
@@ -206,7 +206,7 @@ Turbo can coexist with Rails UJS, but you need to take a series of upgrade steps
|
|
|
206
206
|
|
|
207
207
|
## Testing
|
|
208
208
|
|
|
209
|
-
The [`Turbo::TestAssertions`](./lib/turbo/test_assertions.rb) concern provides Turbo Stream test helpers that assert the presence or absence
|
|
209
|
+
The [`Turbo::TestAssertions`](./lib/turbo/test_assertions.rb) concern provides Turbo Stream test helpers that assert the presence or absence of `<turbo-stream>` elements in a rendered fragment of HTML. `Turbo::TestAssertions` are automatically included in [`ActiveSupport::TestCase`](https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html) and depend on the presence of [`rails-dom-testing`](https://github.com/rails/rails-dom-testing/) assertions.
|
|
210
210
|
|
|
211
211
|
The [`Turbo::TestAssertions::IntegrationTestAssertions`](./lib/turbo/test_assertions/integration_test_assertions.rb) are built on top of `Turbo::TestAssertions`, and add support for passing a `status:` keyword. They are automatically included in [`ActionDispatch::IntegrationTest`](https://edgeguides.rubyonrails.org/testing.html#integration-testing).
|
|
212
212
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.
|
|
2
|
+
Turbo 8.0.19
|
|
3
3
|
Copyright © 2025 37signals LLC
|
|
4
4
|
*/
|
|
5
5
|
(function(prototype) {
|
|
@@ -409,7 +409,11 @@ function doesNotTargetIFrame(name) {
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
function findLinkFromClickTarget(target) {
|
|
412
|
-
|
|
412
|
+
const link = findClosestRecursively(target, "a[href], a[xlink\\:href]");
|
|
413
|
+
if (!link) return null;
|
|
414
|
+
if (link.hasAttribute("download")) return null;
|
|
415
|
+
if (link.hasAttribute("target") && link.target !== "_self") return null;
|
|
416
|
+
return link;
|
|
413
417
|
}
|
|
414
418
|
|
|
415
419
|
function getLocationForLink(link) {
|
|
@@ -488,8 +492,8 @@ function getExtension(url) {
|
|
|
488
492
|
}
|
|
489
493
|
|
|
490
494
|
function isPrefixedBy(baseURL, url) {
|
|
491
|
-
const prefix =
|
|
492
|
-
return baseURL.href ===
|
|
495
|
+
const prefix = addTrailingSlash(url.origin + url.pathname);
|
|
496
|
+
return addTrailingSlash(baseURL.href) === prefix || baseURL.href.startsWith(prefix);
|
|
493
497
|
}
|
|
494
498
|
|
|
495
499
|
function locationIsVisitable(location, rootLocation) {
|
|
@@ -517,10 +521,6 @@ function getLastPathComponent(url) {
|
|
|
517
521
|
return getPathComponents(url).slice(-1)[0];
|
|
518
522
|
}
|
|
519
523
|
|
|
520
|
-
function getPrefix(url) {
|
|
521
|
-
return addTrailingSlash(url.origin + url.pathname);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
524
|
function addTrailingSlash(value) {
|
|
525
525
|
return value.endsWith("/") ? value : value + "/";
|
|
526
526
|
}
|
|
@@ -588,14 +588,12 @@ class LimitedSet extends Set {
|
|
|
588
588
|
|
|
589
589
|
const recentRequests = new LimitedSet(20);
|
|
590
590
|
|
|
591
|
-
const nativeFetch = window.fetch;
|
|
592
|
-
|
|
593
591
|
function fetchWithTurboHeaders(url, options = {}) {
|
|
594
592
|
const modifiedHeaders = new Headers(options.headers || {});
|
|
595
593
|
const requestUID = uuid();
|
|
596
594
|
recentRequests.add(requestUID);
|
|
597
595
|
modifiedHeaders.append("X-Turbo-Request-Id", requestUID);
|
|
598
|
-
return
|
|
596
|
+
return window.fetch(url, {
|
|
599
597
|
...options,
|
|
600
598
|
headers: modifiedHeaders
|
|
601
599
|
});
|
|
@@ -1243,8 +1241,8 @@ class View {
|
|
|
1243
1241
|
scrollToAnchor(anchor) {
|
|
1244
1242
|
const element = this.snapshot.getElementForAnchor(anchor);
|
|
1245
1243
|
if (element) {
|
|
1246
|
-
this.scrollToElement(element);
|
|
1247
1244
|
this.focusElement(element);
|
|
1245
|
+
this.scrollToElement(element);
|
|
1248
1246
|
} else {
|
|
1249
1247
|
this.scrollToPosition({
|
|
1250
1248
|
x: 0,
|
|
@@ -1725,12 +1723,8 @@ var Idiomorph = function() {
|
|
|
1725
1723
|
}
|
|
1726
1724
|
function morphOuterHTML(ctx, oldNode, newNode) {
|
|
1727
1725
|
const oldParent = normalizeParent(oldNode);
|
|
1728
|
-
let childNodes = Array.from(oldParent.childNodes);
|
|
1729
|
-
const index = childNodes.indexOf(oldNode);
|
|
1730
|
-
const rightMargin = childNodes.length - (index + 1);
|
|
1731
1726
|
morphChildren(ctx, oldParent, newNode, oldNode, oldNode.nextSibling);
|
|
1732
|
-
|
|
1733
|
-
return childNodes.slice(index, childNodes.length - rightMargin);
|
|
1727
|
+
return Array.from(oldParent.childNodes);
|
|
1734
1728
|
}
|
|
1735
1729
|
function saveAndRestoreFocus(ctx, fn) {
|
|
1736
1730
|
if (!ctx.config.restoreFocus) return fn();
|
|
@@ -1740,8 +1734,8 @@ var Idiomorph = function() {
|
|
|
1740
1734
|
}
|
|
1741
1735
|
const {id: activeElementId, selectionStart: selectionStart, selectionEnd: selectionEnd} = activeElement;
|
|
1742
1736
|
const results = fn();
|
|
1743
|
-
if (activeElementId && activeElementId !== document.activeElement?.id) {
|
|
1744
|
-
activeElement = ctx.target.querySelector(
|
|
1737
|
+
if (activeElementId && activeElementId !== document.activeElement?.getAttribute("id")) {
|
|
1738
|
+
activeElement = ctx.target.querySelector(`[id="${activeElementId}"]`);
|
|
1745
1739
|
activeElement?.focus();
|
|
1746
1740
|
}
|
|
1747
1741
|
if (activeElement && !activeElement.selectionEnd && selectionEnd) {
|
|
@@ -1768,11 +1762,14 @@ var Idiomorph = function() {
|
|
|
1768
1762
|
continue;
|
|
1769
1763
|
}
|
|
1770
1764
|
}
|
|
1771
|
-
if (newChild instanceof Element
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1765
|
+
if (newChild instanceof Element) {
|
|
1766
|
+
const newChildId = newChild.getAttribute("id");
|
|
1767
|
+
if (ctx.persistentIds.has(newChildId)) {
|
|
1768
|
+
const movedChild = moveBeforeById(oldParent, newChildId, insertionPoint, ctx);
|
|
1769
|
+
morphNode(movedChild, newChild, ctx);
|
|
1770
|
+
insertionPoint = movedChild.nextSibling;
|
|
1771
|
+
continue;
|
|
1772
|
+
}
|
|
1776
1773
|
}
|
|
1777
1774
|
const insertedNode = createNode(oldParent, newChild, insertionPoint, ctx);
|
|
1778
1775
|
if (insertedNode) {
|
|
@@ -1824,7 +1821,7 @@ var Idiomorph = function() {
|
|
|
1824
1821
|
softMatch = undefined;
|
|
1825
1822
|
}
|
|
1826
1823
|
}
|
|
1827
|
-
if (
|
|
1824
|
+
if (ctx.activeElementAndParents.includes(cursor)) break;
|
|
1828
1825
|
cursor = cursor.nextSibling;
|
|
1829
1826
|
}
|
|
1830
1827
|
return softMatch || null;
|
|
@@ -1843,7 +1840,7 @@ var Idiomorph = function() {
|
|
|
1843
1840
|
function isSoftMatch(oldNode, newNode) {
|
|
1844
1841
|
const oldElt = oldNode;
|
|
1845
1842
|
const newElt = newNode;
|
|
1846
|
-
return oldElt.nodeType === newElt.nodeType && oldElt.tagName === newElt.tagName && (!oldElt.id || oldElt.id === newElt.id);
|
|
1843
|
+
return oldElt.nodeType === newElt.nodeType && oldElt.tagName === newElt.tagName && (!oldElt.getAttribute?.("id") || oldElt.getAttribute?.("id") === newElt.getAttribute?.("id"));
|
|
1847
1844
|
}
|
|
1848
1845
|
return findBestMatch;
|
|
1849
1846
|
}();
|
|
@@ -1866,13 +1863,13 @@ var Idiomorph = function() {
|
|
|
1866
1863
|
return cursor;
|
|
1867
1864
|
}
|
|
1868
1865
|
function moveBeforeById(parentNode, id, after, ctx) {
|
|
1869
|
-
const target = ctx.target.querySelector(
|
|
1866
|
+
const target = ctx.target.getAttribute?.("id") === id && ctx.target || ctx.target.querySelector(`[id="${id}"]`) || ctx.pantry.querySelector(`[id="${id}"]`);
|
|
1870
1867
|
removeElementFromAncestorsIdMaps(target, ctx);
|
|
1871
1868
|
moveBefore(parentNode, target, after);
|
|
1872
1869
|
return target;
|
|
1873
1870
|
}
|
|
1874
1871
|
function removeElementFromAncestorsIdMaps(element, ctx) {
|
|
1875
|
-
const id = element.id;
|
|
1872
|
+
const id = element.getAttribute("id");
|
|
1876
1873
|
while (element = element.parentNode) {
|
|
1877
1874
|
let idSet = ctx.idMap.get(element);
|
|
1878
1875
|
if (idSet) {
|
|
@@ -2116,6 +2113,7 @@ var Idiomorph = function() {
|
|
|
2116
2113
|
idMap: idMap,
|
|
2117
2114
|
persistentIds: persistentIds,
|
|
2118
2115
|
pantry: createPantry(),
|
|
2116
|
+
activeElementAndParents: createActiveElementAndParents(oldNode),
|
|
2119
2117
|
callbacks: mergedConfig.callbacks,
|
|
2120
2118
|
head: mergedConfig.head
|
|
2121
2119
|
};
|
|
@@ -2133,16 +2131,29 @@ var Idiomorph = function() {
|
|
|
2133
2131
|
document.body.insertAdjacentElement("afterend", pantry);
|
|
2134
2132
|
return pantry;
|
|
2135
2133
|
}
|
|
2134
|
+
function createActiveElementAndParents(oldNode) {
|
|
2135
|
+
let activeElementAndParents = [];
|
|
2136
|
+
let elt = document.activeElement;
|
|
2137
|
+
if (elt?.tagName !== "BODY" && oldNode.contains(elt)) {
|
|
2138
|
+
while (elt) {
|
|
2139
|
+
activeElementAndParents.push(elt);
|
|
2140
|
+
if (elt === oldNode) break;
|
|
2141
|
+
elt = elt.parentElement;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
return activeElementAndParents;
|
|
2145
|
+
}
|
|
2136
2146
|
function findIdElements(root) {
|
|
2137
2147
|
let elements = Array.from(root.querySelectorAll("[id]"));
|
|
2138
|
-
if (root.id) {
|
|
2148
|
+
if (root.getAttribute?.("id")) {
|
|
2139
2149
|
elements.push(root);
|
|
2140
2150
|
}
|
|
2141
2151
|
return elements;
|
|
2142
2152
|
}
|
|
2143
2153
|
function populateIdMapWithTree(idMap, persistentIds, root, elements) {
|
|
2144
2154
|
for (const elt of elements) {
|
|
2145
|
-
|
|
2155
|
+
const id = elt.getAttribute("id");
|
|
2156
|
+
if (persistentIds.has(id)) {
|
|
2146
2157
|
let current = elt;
|
|
2147
2158
|
while (current) {
|
|
2148
2159
|
let idSet = idMap.get(current);
|
|
@@ -2150,7 +2161,7 @@ var Idiomorph = function() {
|
|
|
2150
2161
|
idSet = new Set;
|
|
2151
2162
|
idMap.set(current, idSet);
|
|
2152
2163
|
}
|
|
2153
|
-
idSet.add(
|
|
2164
|
+
idSet.add(id);
|
|
2154
2165
|
if (current === root) break;
|
|
2155
2166
|
current = current.parentElement;
|
|
2156
2167
|
}
|
|
@@ -2213,7 +2224,7 @@ var Idiomorph = function() {
|
|
|
2213
2224
|
return newContent;
|
|
2214
2225
|
} else if (newContent instanceof Node) {
|
|
2215
2226
|
if (newContent.parentNode) {
|
|
2216
|
-
return
|
|
2227
|
+
return new SlicedParentNode(newContent);
|
|
2217
2228
|
} else {
|
|
2218
2229
|
const dummyParent = document.createElement("div");
|
|
2219
2230
|
dummyParent.append(newContent);
|
|
@@ -2227,19 +2238,43 @@ var Idiomorph = function() {
|
|
|
2227
2238
|
return dummyParent;
|
|
2228
2239
|
}
|
|
2229
2240
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
+
class SlicedParentNode {
|
|
2242
|
+
constructor(node) {
|
|
2243
|
+
this.originalNode = node;
|
|
2244
|
+
this.realParentNode = node.parentNode;
|
|
2245
|
+
this.previousSibling = node.previousSibling;
|
|
2246
|
+
this.nextSibling = node.nextSibling;
|
|
2247
|
+
}
|
|
2248
|
+
get childNodes() {
|
|
2249
|
+
const nodes = [];
|
|
2250
|
+
let cursor = this.previousSibling ? this.previousSibling.nextSibling : this.realParentNode.firstChild;
|
|
2251
|
+
while (cursor && cursor != this.nextSibling) {
|
|
2252
|
+
nodes.push(cursor);
|
|
2253
|
+
cursor = cursor.nextSibling;
|
|
2241
2254
|
}
|
|
2242
|
-
|
|
2255
|
+
return nodes;
|
|
2256
|
+
}
|
|
2257
|
+
querySelectorAll(selector) {
|
|
2258
|
+
return this.childNodes.reduce(((results, node) => {
|
|
2259
|
+
if (node instanceof Element) {
|
|
2260
|
+
if (node.matches(selector)) results.push(node);
|
|
2261
|
+
const nodeList = node.querySelectorAll(selector);
|
|
2262
|
+
for (let i = 0; i < nodeList.length; i++) {
|
|
2263
|
+
results.push(nodeList[i]);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return results;
|
|
2267
|
+
}), []);
|
|
2268
|
+
}
|
|
2269
|
+
insertBefore(node, referenceNode) {
|
|
2270
|
+
return this.realParentNode.insertBefore(node, referenceNode);
|
|
2271
|
+
}
|
|
2272
|
+
moveBefore(node, referenceNode) {
|
|
2273
|
+
return this.realParentNode.moveBefore(node, referenceNode);
|
|
2274
|
+
}
|
|
2275
|
+
get __idiomorphRoot() {
|
|
2276
|
+
return this.originalNode;
|
|
2277
|
+
}
|
|
2243
2278
|
}
|
|
2244
2279
|
function parseContent(newContent) {
|
|
2245
2280
|
let parser = new DOMParser;
|
|
@@ -2281,12 +2316,25 @@ function morphElements(currentElement, newElement, {callbacks: callbacks, ...opt
|
|
|
2281
2316
|
});
|
|
2282
2317
|
}
|
|
2283
2318
|
|
|
2284
|
-
function morphChildren(currentElement, newElement) {
|
|
2319
|
+
function morphChildren(currentElement, newElement, options = {}) {
|
|
2285
2320
|
morphElements(currentElement, newElement.childNodes, {
|
|
2321
|
+
...options,
|
|
2286
2322
|
morphStyle: "innerHTML"
|
|
2287
2323
|
});
|
|
2288
2324
|
}
|
|
2289
2325
|
|
|
2326
|
+
function shouldRefreshFrameWithMorphing(currentFrame, newFrame) {
|
|
2327
|
+
return currentFrame instanceof FrameElement && currentFrame.shouldReloadWithMorph && (!newFrame || areFramesCompatibleForRefreshing(currentFrame, newFrame)) && !currentFrame.closest("[data-turbo-permanent]");
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
function areFramesCompatibleForRefreshing(currentFrame, newFrame) {
|
|
2331
|
+
return newFrame instanceof Element && newFrame.nodeName === "TURBO-FRAME" && currentFrame.id === newFrame.id && (!newFrame.getAttribute("src") || urlsAreEqual(currentFrame.src, newFrame.getAttribute("src")));
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
function closestFrameReloadableWithMorphing(node) {
|
|
2335
|
+
return node.parentElement.closest("turbo-frame[src][refresh=morph]");
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2290
2338
|
class DefaultIdiomorphCallbacks {
|
|
2291
2339
|
#beforeNodeMorphed;
|
|
2292
2340
|
constructor({beforeNodeMorphed: beforeNodeMorphed} = {}) {
|
|
@@ -2344,7 +2392,17 @@ class MorphingFrameRenderer extends FrameRenderer {
|
|
|
2344
2392
|
newElement: newElement
|
|
2345
2393
|
}
|
|
2346
2394
|
});
|
|
2347
|
-
morphChildren(currentElement, newElement
|
|
2395
|
+
morphChildren(currentElement, newElement, {
|
|
2396
|
+
callbacks: {
|
|
2397
|
+
beforeNodeMorphed: (node, newNode) => {
|
|
2398
|
+
if (shouldRefreshFrameWithMorphing(node, newNode) && closestFrameReloadableWithMorphing(node) === currentElement) {
|
|
2399
|
+
node.reload();
|
|
2400
|
+
return false;
|
|
2401
|
+
}
|
|
2402
|
+
return true;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
});
|
|
2348
2406
|
}
|
|
2349
2407
|
async preservingPermanentElements(callback) {
|
|
2350
2408
|
return await callback();
|
|
@@ -2596,7 +2654,8 @@ class PageSnapshot extends Snapshot {
|
|
|
2596
2654
|
return this.getSetting("visit-control") != "reload";
|
|
2597
2655
|
}
|
|
2598
2656
|
get prefersViewTransitions() {
|
|
2599
|
-
|
|
2657
|
+
const viewTransitionEnabled = this.getSetting("view-transition") === "true" || this.headSnapshot.getMetaValue("view-transition") === "same-origin";
|
|
2658
|
+
return viewTransitionEnabled && !window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2600
2659
|
}
|
|
2601
2660
|
get shouldMorphPage() {
|
|
2602
2661
|
return this.getSetting("refresh-method") === "morph";
|
|
@@ -3011,6 +3070,7 @@ class BrowserAdapter {
|
|
|
3011
3070
|
}
|
|
3012
3071
|
visitStarted(visit) {
|
|
3013
3072
|
this.location = visit.location;
|
|
3073
|
+
this.redirectedToLocation = null;
|
|
3014
3074
|
visit.loadCachedSnapshot();
|
|
3015
3075
|
visit.issueRequest();
|
|
3016
3076
|
visit.goToSamePageAnchor();
|
|
@@ -3025,6 +3085,9 @@ class BrowserAdapter {
|
|
|
3025
3085
|
}
|
|
3026
3086
|
visitRequestCompleted(visit) {
|
|
3027
3087
|
visit.loadResponse();
|
|
3088
|
+
if (visit.response.redirected) {
|
|
3089
|
+
this.redirectedToLocation = visit.redirectedToLocation;
|
|
3090
|
+
}
|
|
3028
3091
|
}
|
|
3029
3092
|
visitRequestFailedWithStatusCode(visit, statusCode) {
|
|
3030
3093
|
switch (statusCode) {
|
|
@@ -3095,7 +3158,7 @@ class BrowserAdapter {
|
|
|
3095
3158
|
dispatch("turbo:reload", {
|
|
3096
3159
|
detail: reason
|
|
3097
3160
|
});
|
|
3098
|
-
window.location.href = this.location?.toString() || window.location.href;
|
|
3161
|
+
window.location.href = (this.redirectedToLocation || this.location)?.toString() || window.location.href;
|
|
3099
3162
|
}
|
|
3100
3163
|
get navigator() {
|
|
3101
3164
|
return this.session.navigator;
|
|
@@ -3338,6 +3401,7 @@ class LinkPrefetchObserver {
|
|
|
3338
3401
|
if (this.delegate.canPrefetchRequestToLocation(link, location)) {
|
|
3339
3402
|
this.#prefetchedLink = link;
|
|
3340
3403
|
const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams, target);
|
|
3404
|
+
fetchRequest.fetchOptions.priority = "low";
|
|
3341
3405
|
prefetchCache.setLater(location.toString(), fetchRequest, this.#cacheTtl);
|
|
3342
3406
|
}
|
|
3343
3407
|
}
|
|
@@ -3988,12 +4052,15 @@ class MorphingPageRenderer extends PageRenderer {
|
|
|
3988
4052
|
static renderElement(currentElement, newElement) {
|
|
3989
4053
|
morphElements(currentElement, newElement, {
|
|
3990
4054
|
callbacks: {
|
|
3991
|
-
beforeNodeMorphed:
|
|
4055
|
+
beforeNodeMorphed: (node, newNode) => {
|
|
4056
|
+
if (shouldRefreshFrameWithMorphing(node, newNode) && !closestFrameReloadableWithMorphing(node)) {
|
|
4057
|
+
node.reload();
|
|
4058
|
+
return false;
|
|
4059
|
+
}
|
|
4060
|
+
return true;
|
|
4061
|
+
}
|
|
3992
4062
|
}
|
|
3993
4063
|
});
|
|
3994
|
-
for (const frame of currentElement.querySelectorAll("turbo-frame")) {
|
|
3995
|
-
if (canRefreshFrame(frame)) frame.reload();
|
|
3996
|
-
}
|
|
3997
4064
|
dispatch("turbo:morph", {
|
|
3998
4065
|
detail: {
|
|
3999
4066
|
currentElement: currentElement,
|
|
@@ -4012,10 +4079,6 @@ class MorphingPageRenderer extends PageRenderer {
|
|
|
4012
4079
|
}
|
|
4013
4080
|
}
|
|
4014
4081
|
|
|
4015
|
-
function canRefreshFrame(frame) {
|
|
4016
|
-
return frame instanceof FrameElement && frame.src && frame.refresh === "morph" && !frame.closest("[data-turbo-permanent]");
|
|
4017
|
-
}
|
|
4018
|
-
|
|
4019
4082
|
class SnapshotCache {
|
|
4020
4083
|
keys=[];
|
|
4021
4084
|
snapshots={};
|
|
@@ -4616,6 +4679,14 @@ function setFormMode(mode) {
|
|
|
4616
4679
|
config.forms.mode = mode;
|
|
4617
4680
|
}
|
|
4618
4681
|
|
|
4682
|
+
function morphBodyElements(currentBody, newBody) {
|
|
4683
|
+
MorphingPageRenderer.renderElement(currentBody, newBody);
|
|
4684
|
+
}
|
|
4685
|
+
|
|
4686
|
+
function morphTurboFrameElements(currentFrame, newFrame) {
|
|
4687
|
+
MorphingFrameRenderer.renderElement(currentFrame, newFrame);
|
|
4688
|
+
}
|
|
4689
|
+
|
|
4619
4690
|
var Turbo = Object.freeze({
|
|
4620
4691
|
__proto__: null,
|
|
4621
4692
|
navigator: navigator$1,
|
|
@@ -4635,7 +4706,11 @@ var Turbo = Object.freeze({
|
|
|
4635
4706
|
clearCache: clearCache,
|
|
4636
4707
|
setProgressBarDelay: setProgressBarDelay,
|
|
4637
4708
|
setConfirmMethod: setConfirmMethod,
|
|
4638
|
-
setFormMode: setFormMode
|
|
4709
|
+
setFormMode: setFormMode,
|
|
4710
|
+
morphBodyElements: morphBodyElements,
|
|
4711
|
+
morphTurboFrameElements: morphTurboFrameElements,
|
|
4712
|
+
morphChildren: morphChildren,
|
|
4713
|
+
morphElements: morphElements
|
|
4639
4714
|
});
|
|
4640
4715
|
|
|
4641
4716
|
class TurboFrameMissingError extends Error {}
|
|
@@ -5330,6 +5405,10 @@ var Turbo$1 = Object.freeze({
|
|
|
5330
5405
|
fetchEnctypeFromString: fetchEnctypeFromString,
|
|
5331
5406
|
fetchMethodFromString: fetchMethodFromString,
|
|
5332
5407
|
isSafe: isSafe,
|
|
5408
|
+
morphBodyElements: morphBodyElements,
|
|
5409
|
+
morphChildren: morphChildren,
|
|
5410
|
+
morphElements: morphElements,
|
|
5411
|
+
morphTurboFrameElements: morphTurboFrameElements,
|
|
5333
5412
|
navigator: navigator$1,
|
|
5334
5413
|
registerAdapter: registerAdapter,
|
|
5335
5414
|
renderStreamMessage: renderStreamMessage,
|