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 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: string | HTMLElement; 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: string | HTMLElement | HTMLSelectElement | Window, ) { const bindTarget = typeof selector === "string" ? this.defaultBindTarget : selector; bindTarget.addEventListener(type, (e) => this._handleEvent(type, e)); } _handleEvent(type: ValidEventTypes, event: Event) { 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); } else Eif (target instanceof HTMLElement) { (ev.func as EventHandler)(event, target); } } }); } addEvent<T extends ValidEventTypes>( type: T, selector: string | HTMLElement | HTMLSelectElement, func: EventHandlerMap[T], ): void { if (!this.events[type]) { this.events[type] = []; } const eventArray = this.events[type]; Eif (eventArray) { eventArray.push({ selector: selector as string | HTMLElement, func, }); } if (!this.availableHandles.includes(type)) { this._addListener(type, selector); this.availableHandles.push(type); } } addWindowEvent(type: ValidEventTypes, func: EventHandler) { window.addEventListener(type, (event) => { func(event, window as unknown as HTMLElement); }); } addEvents( eventTypes: Partial<{ [T in ValidEventTypes]: { [selector: string]: EventHandlerMap[T]; }; }>, ) { (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; |