2020-11-26 16:45:25 +01:00
|
|
|
import { config } from "./config";
|
|
|
|
|
|
2021-10-26 11:01:57 +02:00
|
|
|
type EventHandlerSetter = (this: HTMLElement, data: any) => void;
|
|
|
|
|
|
|
|
|
|
interface EventHandlerCreator {
|
|
|
|
|
setup: EventHandlerSetter;
|
|
|
|
|
update: EventHandlerSetter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function createEventHandler(rawEvent: string): EventHandlerCreator {
|
|
|
|
|
const eventName = rawEvent.split(".")[0];
|
2021-10-27 14:45:29 +02:00
|
|
|
const capture = rawEvent.includes(".capture");
|
2021-10-26 11:01:57 +02:00
|
|
|
if (rawEvent.includes(".synthetic")) {
|
2021-10-27 14:45:29 +02:00
|
|
|
return createSyntheticHandler(eventName, capture);
|
2021-10-26 11:01:57 +02:00
|
|
|
} else {
|
2021-10-27 14:45:29 +02:00
|
|
|
return createElementHandler(eventName, capture);
|
2021-10-26 11:01:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Native listener
|
2021-11-02 11:29:23 +01:00
|
|
|
let nextNativeEventId = 1;
|
2021-10-27 14:45:29 +02:00
|
|
|
function createElementHandler(evName: string, capture: boolean = false): EventHandlerCreator {
|
2021-11-02 11:29:23 +01:00
|
|
|
let eventKey = `__event__${evName}_${nextNativeEventId++}`;
|
2021-10-27 14:45:29 +02:00
|
|
|
if (capture) {
|
|
|
|
|
eventKey = `${eventKey}_capture`;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-26 11:01:57 +02:00
|
|
|
function listener(ev: Event) {
|
|
|
|
|
const currentTarget = ev.currentTarget;
|
|
|
|
|
if (!currentTarget || !document.contains(currentTarget as HTMLElement)) return;
|
|
|
|
|
const data = (currentTarget as any)[eventKey];
|
|
|
|
|
if (!data) return;
|
2021-10-27 14:45:29 +02:00
|
|
|
config.mainEventHandler(data, ev, currentTarget);
|
2021-10-26 11:01:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setup(this: HTMLElement, data: any) {
|
|
|
|
|
(this as any)[eventKey] = data;
|
2021-10-27 14:45:29 +02:00
|
|
|
this.addEventListener(evName, listener, { capture });
|
2021-10-26 11:01:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function update(this: HTMLElement, data: any) {
|
|
|
|
|
(this as any)[eventKey] = data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { setup, update };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Synthetic handler: a form of event delegation that allows placing only one
|
|
|
|
|
// listener per event type.
|
2021-11-08 12:12:44 +01:00
|
|
|
let nextSyntheticEventId = 1;
|
2021-10-27 14:45:29 +02:00
|
|
|
function createSyntheticHandler(evName: string, capture: boolean = false): EventHandlerCreator {
|
2021-10-26 11:01:57 +02:00
|
|
|
let eventKey = `__event__synthetic_${evName}`;
|
2021-10-27 14:45:29 +02:00
|
|
|
if (capture) {
|
|
|
|
|
eventKey = `${eventKey}_capture`;
|
|
|
|
|
}
|
|
|
|
|
setupSyntheticEvent(evName, eventKey, capture);
|
2021-11-08 12:12:44 +01:00
|
|
|
const currentId = nextSyntheticEventId++;
|
2021-10-26 11:01:57 +02:00
|
|
|
function setup(this: HTMLElement, data: any) {
|
2021-11-08 12:12:44 +01:00
|
|
|
const _data = (this as any)[eventKey] || {};
|
|
|
|
|
_data[currentId] = data;
|
|
|
|
|
(this as any)[eventKey] = _data;
|
2021-10-26 11:01:57 +02:00
|
|
|
}
|
|
|
|
|
return { setup, update: setup };
|
2020-11-26 16:45:25 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-26 11:01:57 +02:00
|
|
|
function nativeToSyntheticEvent(eventKey: string, event: Event) {
|
2020-11-26 16:45:25 +01:00
|
|
|
let dom = event.target;
|
|
|
|
|
while (dom !== null) {
|
2021-11-08 12:12:44 +01:00
|
|
|
const _data = (dom as any)[eventKey];
|
|
|
|
|
if (_data) {
|
|
|
|
|
for (const data of Object.values(_data)) {
|
|
|
|
|
const stopped = config.mainEventHandler(data, event, dom);
|
|
|
|
|
if (stopped) return;
|
|
|
|
|
}
|
2020-11-26 16:45:25 +01:00
|
|
|
}
|
|
|
|
|
dom = (dom as any).parentNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CONFIGURED_SYNTHETIC_EVENTS: { [event: string]: boolean } = {};
|
|
|
|
|
|
2021-10-27 14:45:29 +02:00
|
|
|
function setupSyntheticEvent(evName: string, eventKey: string, capture: boolean = false) {
|
2021-10-26 11:01:57 +02:00
|
|
|
if (CONFIGURED_SYNTHETIC_EVENTS[eventKey]) {
|
2020-11-26 16:45:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2021-10-28 17:47:16 +02:00
|
|
|
document.addEventListener(evName, (event) => nativeToSyntheticEvent(eventKey, event), {
|
|
|
|
|
capture,
|
|
|
|
|
});
|
2021-10-26 11:01:57 +02:00
|
|
|
CONFIGURED_SYNTHETIC_EVENTS[eventKey] = true;
|
2020-11-26 16:45:25 +01:00
|
|
|
}
|