Skip to content

Commit

Permalink
limit morph action data atrributes to morphStyle only and add morph l…
Browse files Browse the repository at this point in the history
…ifecycle events
  • Loading branch information
omarluq committed Mar 4, 2024
1 parent 8b2228e commit 268dfbc
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 29 deletions.
84 changes: 60 additions & 24 deletions src/core/streams/stream_actions.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { session } from "../"
import { morph } from "idiomorph"
import { Idiomorph } from "idiomorph/dist/idiomorph.esm.js"
import { dispatch } from "../../util"


export const StreamActions = {
after() {
this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e.nextSibling))
Expand Down Expand Up @@ -39,34 +38,28 @@ export const StreamActions = {

refresh() {
session.refresh(this.baseURI, this.requestId)
}
},

morph() {
this.targetElements.forEach((targetElement) => {
try {
const morphStyle = this.getAttribute("data-turbo-morph-style") || "outerHTML"
const ignoreActive = this.getAttribute("data-turbo-morph-ignore-active") || true
const ignoreActiveValue = this.getAttribute("data-turbo-morph-ignore-active-value") || true
const head = this.getAttribute("data-turbo-morph-head") || 'merge'
morph(targetElement, this.templateContent, {
const morphStyle = targetElement.getAttribute("data-turbo-morph-style") || "outerHTML"
Idiomorph.morph(targetElement, this.templateContent, {
morphStyle: morphStyle,
ignoreActive: ignoreActive,
ignoreActiveValue: ignoreActiveValue,
head: head,
ignoreActiveValue: true,
callbacks: {
beforeNodeAdded: (node) => {
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
},
afterNodeMorphed: (oldNode, newNode) => {
if (newNode instanceof HTMLElement) {
dispatch("turbo:morph-element", {
target: oldNode,
detail: {
newElement: newNode
}
})
}
}
beforeNodeAdded,
beforeNodeMorphed,
beforeAttributeUpdated,
beforeNodeRemoved,
afterNodeMorphed
}
})

dispatch("turbo:morph", {
detail: {
currentElement: targetElement,
newElement: this.templateContent
}
})
} catch (error) {
Expand All @@ -75,3 +68,46 @@ export const StreamActions = {
})
}
}

const beforeNodeAdded = (node) => {
return !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id))
}

const beforeNodeMorphed = (target, newElement) => {
if (target instanceof HTMLElement && !target.hasAttribute("data-turbo-permanent")) {
const event = dispatch("turbo:before-morph-element", {
cancelable: true,
detail: {
target,
newElement
}
})
return !event.defaultPrevented
}
return false
}

const beforeAttributeUpdated = (attributeName, target, mutationType) => {
const event = dispatch("turbo:before-morph-attribute", {
cancelable: true,
target,
detail: {
attributeName,
mutationType
}
})
return !event.defaultPrevented
}

const beforeNodeRemoved = beforeNodeMorphed

const afterNodeMorphed = (target, newElement) => {
if (newElement instanceof HTMLElement) {
dispatch("turbo:morph-element", {
target,
detail: {
newElement
}
})
}
}
27 changes: 22 additions & 5 deletions src/tests/unit/stream_element_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,31 @@ test("test action=refresh discarded when matching request id", async () => {
})

test("action=morph", async () => {
const templateElement = createTemplateElement(`<div id="hello">Hello Turbo Morphed</div>`)
const templateElement = createTemplateElement(`<h1 id="hello">Hello Turbo Morphed</h1>`)
const element = createStreamElement("morph", "hello", templateElement)
assert.equal(subject.find("#hello")?.textContent, "Hello Turbo")

assert.equal(subject.find("div#hello")?.textContent, "Hello Turbo")

subject.append(element)
await nextAnimationFrame()

assert.notOk(subject.find("#hello")?.textContent, "Hello Turbo")
assert.equal(subject.find("#hello")?.textContent, "Hello Turbo Morphed")
assert.notOk(subject.find("div#hello"))
assert.equal(subject.find("h1#hello")?.textContent, "Hello Turbo Morphed")
})

test("action=morph with data-turbo-morph-style='innerHTML'", async () => {
const templateElement = createTemplateElement(`<h1 id="hello-child-element">Hello Turbo Morphed</h1>`)
const element = createStreamElement("morph", "hello", templateElement)
const target = subject.find("div#hello")
assert.equal(target?.textContent, "Hello Turbo")
target.setAttribute("data-turbo-morph-style", "innerHTML")

subject.append(element)

await nextAnimationFrame()

assert.ok(subject.find("div#hello"))
assert.ok(subject.find("div#hello > h1#hello-child-element"))
assert.equal(subject.find("div#hello > h1#hello-child-element").textContent, "Hello Turbo Morphed")
})

0 comments on commit 268dfbc

Please sign in to comment.