Skip to content

Commit

Permalink
allow customizing the element that Drive replaces
Browse files Browse the repository at this point in the history
While most of the time, replacing `<body>` makes perfect sense, when working with 3rd party integrations (i.e. Stripe), there are elements injected just before the closing `</body>` tag that should not be
removed between page visits. There is more detail on this issue, particularly with injected `<iframe>` elements in hotwired#305 (comment).

Now, if someone wants to customize the element that is replaced by Drive, they can add `data-turbo-drive-body` to an element, and only that element will be replaced between visits.
  • Loading branch information
agrobbin committed Jul 14, 2022
1 parent 98cdc40 commit 05f3aa1
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/core/drive/page_renderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Renderer } from "../renderer"
import { PageSnapshot } from "./page_snapshot"
import { ReloadReason } from "../native/browser_adapter"
import { nextEventLoopTick } from "../../util"

export class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot> {
get shouldRender() {
Expand Down Expand Up @@ -104,9 +105,14 @@ export class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot> {
}
}

assignNewBody() {
async assignNewBody() {
await nextEventLoopTick()

if (document.body && this.newElement instanceof HTMLBodyElement) {
document.body.replaceWith(this.newElement)
const currentBody = this.findBodyElement(document.body)
const newBody = this.findBodyElement(this.newElement)

currentBody.replaceWith(newBody)
} else {
document.documentElement.appendChild(this.newElement)
}
Expand All @@ -131,4 +137,12 @@ export class PageRenderer extends Renderer<HTMLBodyElement, PageSnapshot> {
get newBodyScriptElements() {
return this.newElement.querySelectorAll("script")
}

// Private

findBodyElement(body: HTMLBodyElement | Element) {
if (!this.currentSnapshot.bodyElementId) return body

return body.querySelector(`#${this.currentSnapshot.bodyElementId}`) || body
}
}
4 changes: 4 additions & 0 deletions src/core/drive/page_snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export class PageSnapshot extends Snapshot<HTMLBodyElement> {
return this.getSetting("visit-control") != "reload"
}

get bodyElementId() {
return this.getSetting("body")
}

// Private

getSetting(name: string) {
Expand Down

0 comments on commit 05f3aa1

Please sign in to comment.