htmgo/framework/assets/js/htmxextensions/trigger-children.ts

65 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

2024-10-06 16:21:37 +00:00
import htmx from "htmx.org";
function kebabEventName(str: string) {
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()
}
2024-10-10 22:00:20 +00:00
const ignoredEvents = ['htmx:beforeProcessNode', 'htmx:afterProcessNode', 'htmx:configRequest', 'htmx:configResponse', 'htmx:responseError'];
2024-10-01 17:09:22 +00:00
function makeEvent(eventName: string, detail: any) {
let evt
if (window.CustomEvent && typeof window.CustomEvent === 'function') {
// TODO: `composed: true` here is a hack to make global event handlers work with events in shadow DOM
evt = new CustomEvent(eventName, { bubbles: false, cancelable: true, composed: true, detail })
} else {
evt = document.createEvent('CustomEvent')
evt.initCustomEvent(eventName, true, true, detail)
}
return evt
}
function triggerChildren(target: HTMLElement, name: string, event: CustomEvent, triggered: Set<HTMLElement>) {
2024-10-01 17:09:22 +00:00
if(ignoredEvents.includes(name)) {
return
}
if (target && target.children) {
Array.from(target.children).forEach((e) => {
const kehab = kebabEventName(name);
const eventName = kehab.replace("htmx:", "hx-on::")
if (!triggered.has(e as HTMLElement)) {
if(e.hasAttribute(eventName)) {
2024-10-10 22:00:20 +00:00
setTimeout(() => {
const newEvent = makeEvent(eventName.replace("hx-on::", "htmx:"), {
...event.detail,
target: e,
})
newEvent.detail.meta = 'trigger-children'
e.dispatchEvent(newEvent)
triggered.add(e as HTMLElement);
}, 1)
}
if (e.children) {
triggerChildren(e as HTMLElement, name, event, triggered);
}
}
});
}
}
2024-10-06 16:21:37 +00:00
// @ts-ignore
htmx.defineExtension("trigger-children", {
onEvent: (name, evt: Event | CustomEvent) => {
if (!(evt instanceof CustomEvent)) {
return false;
}
if(evt.detail.meta === 'trigger-children') {
return false;
}
const triggered = new Set<HTMLElement>();
const target = evt.target as HTMLElement || evt.detail.target as HTMLElement;
triggerChildren(target, name, evt, triggered);
return true;
},
});