/ src / helpers / prependJqListener.ts
prependJqListener.ts
 1  import type { Logger } from '@/utils/logger';
 2  
 3  interface EventHandler {
 4  	(eventObject: JQueryEventObject, ...args: unknown[]): unknown;
 5  	wrappedJSObject?: Omit<EventHandler, 'wrappedJSObject'>;
 6  }
 7  
 8  interface JQueryEvent {
 9  	handler: EventHandler;
10  }
11  
12  export const prependJqListener = (
13  	logger: Logger,
14  	node: JQuery,
15  	event: string,
16  	eventKey: string,
17  	handler: EventHandler,
18  ) => {
19  	node.on(event, handler);
20  
21  	const newEvents = tryGetEventListeners(logger, node, eventKey);
22  
23  	if (!newEvents) {
24  		return;
25  	}
26  
27  	const addedEvents: JQueryEvent[] = [];
28  	const addedEventsIndexes: number[] = [];
29  	const waivedHandler = handler.wrappedJSObject || handler;
30  
31  	for (const [i, e] of newEvents.entries()) {
32  		if (e.handler === waivedHandler) {
33  			addedEvents.push(e);
34  			addedEventsIndexes.push(i);
35  		}
36  	}
37  
38  	if (!addedEvents.length || addedEvents.length === newEvents.length) {
39  		return;
40  	}
41  
42  	{
43  		let i = addedEvents.length;
44  		while (i--) {
45  			newEvents.splice(addedEventsIndexes[i], 1);
46  		}
47  	}
48  
49  	newEvents.unshift(...addedEvents);
50  };
51  
52  const tryGetEventListeners = (
53  	logger: Logger,
54  	node: JQuery,
55  	eventKey: string,
56  ): JQueryEvent[] | undefined => {
57  	try {
58  		const maybeEvents = node.data('events')?.[eventKey];
59  		return Array.isArray(maybeEvents) ? maybeEvents : undefined;
60  	} catch (err) {
61  		logger
62  			.getChildLogger('prependJqListener')
63  			.error('failed to get', eventKey, 'jQuery events:', err);
64  	}
65  };