@@ -105,11 +105,18 @@ type ElementWithValue =
105105 | HTMLTextAreaElement
106106 | HTMLSelectElement ;
107107
108- export type DomUtilsEvent < T extends Event = Event > = Omit < T , "currentTarget" > ;
108+ //TODO: after the migration from jQuery to dom-utils we might want to add currentTarget back to the event object, if we have a use-case for it.
109+ // For now we remove it because currentTarget is not the same element when using dom-utils intead of jQuery to get compile errors.
110+ export type OnChildEvent < T extends Event = Event > = Omit < T , "currentTarget" > & {
111+ /**
112+ * target element matching the selector. This emulates the behavior of `currentTarget` in jQuery events registered with `.on(events, selector, handler)`
113+ */
114+ childTarget : EventTarget | null ;
115+ } ;
109116
110- type DomUtilsEventListenerOrEventListenerObject =
111- | { ( evt : DomUtilsEvent ) : void }
112- | { handleEvent ( object : DomUtilsEvent ) : void } ;
117+ type OnChildEventListenerOrEventListenerObject =
118+ | { ( evt : OnChildEvent ) : void }
119+ | { handleEvent ( object : OnChildEvent ) : void } ;
113120
114121export class ElementWithUtils < T extends HTMLElement = HTMLElement > {
115122 /**
@@ -244,56 +251,80 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
244251 */
245252 on < K extends keyof HTMLElementEventMap > (
246253 event : K ,
247- handler : ( this : T , ev : DomUtilsEvent < HTMLElementEventMap [ K ] > ) => void ,
254+ handler : ( this : T , ev : HTMLElementEventMap [ K ] ) => void ,
248255 ) : this;
249- on ( event : string , handler : DomUtilsEventListenerOrEventListenerObject ) : this;
256+ on ( event : string , handler : EventListenerOrEventListenerObject ) : this;
250257 on (
251258 event : keyof HTMLElementEventMap | string ,
252259 handler :
253- | DomUtilsEventListenerOrEventListenerObject
254- | ( ( this : T , ev : DomUtilsEvent ) => void ) ,
260+ | EventListenerOrEventListenerObject
261+ | ( ( this : T , ev : Event ) => void ) ,
255262 ) : this {
256263 // this type was some AI magic but if it works it works
257264 this . native . addEventListener (
258265 event ,
259- handler as DomUtilsEventListenerOrEventListenerObject ,
266+ handler as EventListenerOrEventListenerObject ,
260267 ) ;
261268 return this ;
262269 }
263270
264271 /**
265- * Attach an event listener to child elements matching the query .
272+ * Attach an event listener to child elements matching the selector .
266273 * Useful for dynamically added elements.
274+ *
275+ * The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements)
276+ * that match the selector. Bubbles the event from the event target up to the element where the handler is attached
277+ * (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
267278 */
268279 onChild < K extends keyof HTMLElementEventMap > (
269280 event : K ,
270- query : string ,
281+ /**
282+ * A selector string to filter the descendants of the selected elements that will call the handler.
283+ */
284+ selector : string ,
271285 handler : (
272286 this : HTMLElement ,
273- ev : DomUtilsEvent < HTMLElementEventMap [ K ] > ,
287+ ev : OnChildEvent < HTMLElementEventMap [ K ] > ,
274288 ) => void ,
275289 ) : this;
276290 onChild (
277291 event : string ,
278- query : string ,
279- handler : DomUtilsEventListenerOrEventListenerObject ,
292+ /**
293+ * A selector string to filter the descendants of the selected elements that will call the handler.
294+ */
295+ selector : string ,
296+ handler : OnChildEventListenerOrEventListenerObject ,
280297 ) : this;
281298 onChild (
282299 event : keyof HTMLElementEventMap | string ,
283- query : string ,
300+ /**
301+ * A selector string to filter the descendants of the selected elements that will call the handler.
302+ */
303+ selector : string ,
284304 handler :
285- | DomUtilsEventListenerOrEventListenerObject
286- | ( ( this : HTMLElement , ev : DomUtilsEvent ) => void ) ,
305+ | OnChildEventListenerOrEventListenerObject
306+ | ( ( this : HTMLElement , ev : OnChildEvent ) => void ) ,
287307 ) : this {
288- // this type was some AI magic but if it works it works
289308 this . native . addEventListener ( event , ( e ) => {
290309 const target = e . target as HTMLElement ;
291- if ( target !== null && target . matches ( query ) ) {
310+ if ( target === null ) return ; //ignore event
311+
312+ let childTarget = target . closest ( selector ) ;
313+ //bubble up until no match found or the parent element is reached
314+ while ( childTarget !== null && childTarget !== this . native ) {
292315 if ( typeof handler === "function" ) {
293- handler . call ( target , e ) ;
316+ handler . call (
317+ childTarget as HTMLElement ,
318+ Object . assign ( e , { childTarget } ) ,
319+ ) ;
294320 } else {
295- handler . handleEvent ( e ) ;
321+ handler . handleEvent ( Object . assign ( e , { childTarget } ) ) ;
296322 }
323+
324+ childTarget =
325+ childTarget . parentElement !== null
326+ ? childTarget . parentElement . closest ( selector )
327+ : null ;
297328 }
298329 } ) ;
299330 return this ;
@@ -680,21 +711,20 @@ export class ElementsWithUtils<
680711 */
681712 on < K extends keyof HTMLElementEventMap > (
682713 event : K ,
683- handler : ( this : T , ev : DomUtilsEvent < HTMLElementEventMap [ K ] > ) => void ,
714+ handler : ( this : T , ev : HTMLElementEventMap [ K ] ) => void ,
684715 ) : this;
685- on ( event : string , handler : DomUtilsEventListenerOrEventListenerObject ) : this;
716+ on ( event : string , handler : EventListenerOrEventListenerObject ) : this;
686717 on (
687718 event : keyof HTMLElementEventMap | string ,
688719 handler :
689- | DomUtilsEventListenerOrEventListenerObject
690- | ( ( this : T , ev : DomUtilsEvent ) => void ) ,
720+ | EventListenerOrEventListenerObject
721+ | ( ( this : T , ev : Event ) => void ) ,
691722 ) : this {
692723 for ( const item of this ) {
693724 item . on ( event , handler ) ;
694725 }
695726 return this ;
696727 }
697-
698728 /**
699729 * Set attribute value on all elements in the array
700730 */
0 commit comments