From f6f62e8d6769357792ffcc6683853f35b43f3091 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Mon, 23 Oct 2023 10:56:39 +0200 Subject: [PATCH] Don't morph frames flagged with "refresh=morph" as part of the full page refresh We will refresh those frames with morphing as part of the page refresh, so it does not make sense to morph them also as part of the full page refresh. If we do, we'll trigger a manual reload because the complete attribute will get removed. This aligns the upstreamed version with the private gem we've been using internally. This also fixes a couple of issues: - We don't want to manually reload all the remote turbo-frames, only those that are flagged with "refresh=morph". Regular remote frames will get reloaded automatically when removing their complete attribute during regular page refreshes. - Using idiomorph's "innerHTML" was resulting in a turbo-frame nested inside the target turbo-frame. I think its semantics is not morphing inner contents from both currentElement and newElement, but morphing newElement as the inner contents of currentElement. See https://github.com/hotwired/turbo/pull/1019#issuecomment-1754539355 --- src/core/drive/morph_renderer.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/drive/morph_renderer.js b/src/core/drive/morph_renderer.js index 8f8181464..541d6b346 100644 --- a/src/core/drive/morph_renderer.js +++ b/src/core/drive/morph_renderer.js @@ -26,6 +26,8 @@ export class MorphRenderer extends Renderer { } #morphElements(currentElement, newElement, morphStyle = "outerHTML") { + this.isMorphingTurboFrame = this.isFrameReloadedWithMorph(currentElement) + Idiomorph.morph(currentElement, newElement, { morphStyle: morphStyle, callbacks: { @@ -40,8 +42,8 @@ export class MorphRenderer extends Renderer { this.#remoteFrames().forEach((frame) => { if (this.#isFrameReloadedWithMorph(frame)) { this.#renderFrameWithMorph(frame) + frame.reload() } - frame.reload() }) } @@ -56,7 +58,7 @@ export class MorphRenderer extends Renderer { target: currentElement, detail: { currentElement, newElement } }) - this.#morphElements(currentElement, newElement, "innerHTML") + this.#morphElements(currentElement, newElement) } #shouldRemoveElement = (node) => { @@ -65,7 +67,7 @@ export class MorphRenderer extends Renderer { #shouldMorphElement = (node) => { if (node instanceof HTMLElement) { - return !node.hasAttribute("data-turbo-permanent") + return !node.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(node)) } else { return true }