philomena/assets/js/utils/events.ts

61 lines
1.9 KiB
TypeScript
Raw Normal View History

2022-03-25 23:36:23 +01:00
// DOM events
2024-06-23 19:21:24 +02:00
import '../../types/ujs';
2023-05-18 14:40:24 +02:00
export interface PhilomenaAvailableEventsMap {
2024-07-04 02:27:59 +02:00
dragstart: DragEvent;
dragover: DragEvent;
dragenter: DragEvent;
dragleave: DragEvent;
dragend: DragEvent;
drop: DragEvent;
click: MouseEvent;
submit: Event;
reset: Event;
fetchcomplete: FetchcompleteEvent;
2023-05-18 14:40:24 +02:00
}
export interface PhilomenaEventElement {
addEventListener<K extends keyof PhilomenaAvailableEventsMap>(
type: K,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
listener: (this: Document | HTMLElement, ev: PhilomenaAvailableEventsMap[K]) => any,
2024-07-04 02:27:59 +02:00
options?: boolean | AddEventListenerOptions | undefined,
2023-05-18 14:40:24 +02:00
): void;
}
2022-03-25 23:36:23 +01:00
export function fire<El extends Element, D>(el: El, event: string, detail: D) {
el.dispatchEvent(new CustomEvent<D>(event, { detail, bubbles: true, cancelable: true }));
}
2023-05-18 14:40:24 +02:00
export function on<K extends keyof PhilomenaAvailableEventsMap>(
node: PhilomenaEventElement,
2024-07-04 02:27:59 +02:00
event: K,
selector: string,
func: (e: PhilomenaAvailableEventsMap[K], target: Element) => boolean,
2023-05-18 14:40:24 +02:00
) {
2022-03-25 23:36:23 +01:00
delegate(node, event, { [selector]: func });
}
export function leftClick<E extends MouseEvent, Target extends EventTarget>(func: (e: E, t: Target) => void) {
2024-07-04 02:27:59 +02:00
return (event: E, target: Target) => {
if (event.button === 0) return func(event, target);
};
2022-03-25 23:36:23 +01:00
}
2023-05-18 14:40:24 +02:00
export function delegate<K extends keyof PhilomenaAvailableEventsMap, Target extends Element>(
node: PhilomenaEventElement,
event: K,
2024-07-04 02:27:59 +02:00
selectors: Record<string, (e: PhilomenaAvailableEventsMap[K], target: Target) => void | boolean>,
2023-05-18 14:40:24 +02:00
) {
2022-03-25 23:36:23 +01:00
node.addEventListener(event, e => {
for (const selector in selectors) {
const evtTarget = e.target as EventTarget | Target | null;
2022-03-25 23:36:23 +01:00
if (evtTarget && 'closest' in evtTarget && typeof evtTarget.closest === 'function') {
const target = evtTarget.closest(selector) as Target;
2022-03-25 23:36:23 +01:00
if (target && selectors[selector](e, target) === false) break;
}
}
});
}