Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 3x 3x 3x 3x 3x 2x 1x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x | interface EventHandler {
(event: Event, target: HTMLElement): void;
}
interface SelectChangeHandler {
(event: Event, target: HTMLSelectElement): void;
}
type ValidEventTypes = "change" | "click" | "keyup" | "resize";
type EventHandlerMap = {
change: SelectChangeHandler;
click: EventHandler;
keyup: EventHandler;
resize: EventHandler;
};
interface EventRegistration<T extends ValidEventTypes> {
selector: HTMLElement | string;
func: EventHandlerMap[T];
}
class Events {
events: Partial<{
[T in ValidEventTypes]: EventRegistration<T>[];
}> = {};
availableHandles: ValidEventTypes[];
defaultBindTarget: ParentNode;
constructor(defaultBindTarget: ParentNode | null | undefined) {
this.defaultBindTarget = defaultBindTarget || document.body;
this.events = {};
this.availableHandles = [];
return this;
}
_addListener(
type: ValidEventTypes,
selector: HTMLElement | HTMLSelectElement | string | Window,
): void {
const bindTarget =
typeof selector === "string" ? this.defaultBindTarget : selector;
bindTarget.addEventListener(type, (e) => {
this._handleEvent(type, e);
});
}
_handleEvent(type: ValidEventTypes, event: Event): void {
const eventTarget = event.target as HTMLElement | HTMLSelectElement;
const eventRegistrations = this.events[type];
Iif (!eventRegistrations) return;
eventRegistrations.forEach((ev) => {
const target =
typeof ev.selector === "string"
? eventTarget.closest(ev.selector)
: ev.selector;
Eif (target) {
Iif (type === "change" && target instanceof HTMLSelectElement) {
(ev.func as SelectChangeHandler)(event, target);
E} else if (target instanceof HTMLElement) {
(ev.func as EventHandler)(event, target);
}
}
});
}
addEvent<T extends ValidEventTypes>(
type: T,
selector: HTMLElement | HTMLSelectElement | string,
func: EventHandlerMap[T],
): void {
if (!this.events[type]) {
this.events[type] = [];
}
const eventArray = this.events[type];
Eif (eventArray) {
eventArray.push({
selector: selector as HTMLElement | string,
func,
});
}
if (!this.availableHandles.includes(type)) {
this._addListener(type, selector);
this.availableHandles.push(type);
}
}
addWindowEvent(type: ValidEventTypes, func: EventHandler): void {
window.addEventListener(type, (event) => {
func(event, window as unknown as HTMLElement);
});
}
addEvents(
eventTypes: Partial<{
[T in ValidEventTypes]: Record<string, EventHandlerMap[T]>;
}>,
): void {
(Object.keys(eventTypes) as ValidEventTypes[]).forEach((type) => {
const handlers = eventTypes[type];
Eif (handlers) {
Object.keys(handlers).forEach((selector) => {
const handler = handlers[selector];
this.addEvent(type, selector, handler);
});
}
});
}
}
export default Events;
|