diff --git a/src/core/streams/stream_actions.js b/src/core/streams/stream_actions.js index a343e4333..04e825676 100644 --- a/src/core/streams/stream_actions.js +++ b/src/core/streams/stream_actions.js @@ -2,7 +2,6 @@ import { session } from "../" import { morph } from "idiomorph" import { dispatch } from "../../util" - export const StreamActions = { after() { this.targetElements.forEach((e) => e.parentElement?.insertBefore(this.templateContent, e.nextSibling)) @@ -39,39 +38,85 @@ 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, { 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, + }, + }) + dispatchEvent("turbo:morph", { + currentElement: targetElement, + newElement: this.templateContent, }) } catch (error) { console.error(error) } }) + }, +} + +const dispatchEvent = (eventName, detail, cancelable = false) => { + const event = dispatch(eventName, { + cancelable, + detail, + }) + return !event.defaultPrevented +} + +const beforeNodeAdded = (node) => + !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id)) + +const beforeNodeMorphed = (oldNode, newNode) => { + if (oldNode instanceof HTMLElement && shouldMorphNode(oldNode, newNode)) { + return dispatchEvent( + "turbo:before-morph-element", + { + target: oldNode, + newElement: newNode, + }, + true, + ) + } else { + return false + } +} + +const beforeAttributeUpdated = (attributeName, target, mutationType) => + dispatchEvent( + "turbo:before-morph-attribute", + { + attributeName, + mutationType, + target, + }, + true, + ) + +const beforeNodeRemoved = beforeNodeMorphed + +const afterNodeMorphed = (oldNode, newNode) => { + if (newNode instanceof HTMLElement) { + dispatchEvent("turbo:morph-element", { + target: oldNode, + newElement: newNode, + }) } } + +const shouldMorphNode = (oldNode, newNode) => { + return ( + !oldNode.hasAttribute("data-turbo-permanent") && + ((newNode.src && newNode.refresh === "morph") || !(oldNode.src && oldNode.refresh === "morph")) + ) +}