Skip to content

Commit

Permalink
extract morph action and add children-only option to stream-element
Browse files Browse the repository at this point in the history
  • Loading branch information
omarluq committed Mar 11, 2024
1 parent 268dfbc commit 276ee38
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 74 deletions.
68 changes: 68 additions & 0 deletions src/core/streams/actions/morph.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Idiomorph } from "idiomorph/dist/idiomorph.esm"
import { dispatch } from "../../../util"

export default function morph(streamElement) {
const morphStyle = streamElement.hasAttribute("children-only") ? "innerHTML" : "outerHTML"
streamElement.targetElements.forEach((element) => {
try {
Idiomorph.morph(element, streamElement.templateContent, {
morphStyle: morphStyle,
ignoreActiveValue: true,
callbacks: {
beforeNodeAdded,
beforeNodeMorphed,
beforeAttributeUpdated,
beforeNodeRemoved,
afterNodeMorphed,
},
})
} catch (e) {
console.error(e)
}
})
}

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

function beforeNodeRemoved(node) {
return beforeNodeAdded(node)
}

function 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
}

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

function afterNodeMorphed(target, newElement) {
if (newElement instanceof HTMLElement) {
dispatch("turbo:morph-element", {
target,
detail: {
newElement,
},
})
}
}
74 changes: 3 additions & 71 deletions src/core/streams/stream_actions.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { session } from "../"
import { Idiomorph } from "idiomorph/dist/idiomorph.esm.js"
import { dispatch } from "../../util"
import morph from "./actions/morph"

export const StreamActions = {
after() {
Expand Down Expand Up @@ -41,73 +40,6 @@ export const StreamActions = {
},

morph() {
this.targetElements.forEach((targetElement) => {
try {
const morphStyle = targetElement.getAttribute("data-turbo-morph-style") || "outerHTML"
Idiomorph.morph(targetElement, this.templateContent, {
morphStyle: morphStyle,
ignoreActiveValue: true,
callbacks: {
beforeNodeAdded,
beforeNodeMorphed,
beforeAttributeUpdated,
beforeNodeRemoved,
afterNodeMorphed
}
})

dispatch("turbo:morph", {
detail: {
currentElement: targetElement,
newElement: this.templateContent
}
})
} catch (error) {
console.error(error)
}
})
}
}

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
}
})
}
morph(this)
},
}
5 changes: 2 additions & 3 deletions src/tests/unit/stream_element_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ test("action=morph", async () => {
assert.equal(subject.find("h1#hello")?.textContent, "Hello Turbo Morphed")
})

test("action=morph with data-turbo-morph-style='innerHTML'", async () => {
test("action=morph children-only", 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")
element.setAttribute("children-only", true)

subject.append(element)

Expand All @@ -225,4 +225,3 @@ test("action=morph with data-turbo-morph-style='innerHTML'", async () => {
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 276ee38

Please sign in to comment.