1+ import utils from "./utils" ;
2+
13// Event related methods and event factories
24
35// Event listener registration for easy-to-remove event listeners.
46// once Safari supports the ``signal`` option for addEventListener we can abort
57// event handlers by calling AbortController.abort().
6- export const event_listener_map = { } ;
8+ export const event_listener_map = new Map ( ) ;
79
810/**
911 * Add an event listener to a DOM element under a unique id.
@@ -23,48 +25,72 @@ const add_event_listener = (el, event_type, id, cb, opts = {}) => {
2325 remove_event_listener ( el , id ) ; // do not register one listener twice.
2426
2527 // Create event_listener_map entry if not existent.
26- if ( ! event_listener_map [ el ] ) {
27- event_listener_map [ el ] = { } ;
28+ if ( ! event_listener_map . has ( el ) ) {
29+ event_listener_map . set ( el , new Map ( ) ) ;
2830 }
2931 let _cb = cb ;
3032 if ( opts ?. once === true ) {
3133 // For `once` events, also remove the entry from the event_listener_map.
3234 _cb = ( e ) => {
33- delete event_listener_map [ el ] [ id ] ;
35+ event_listener_map . get ( el ) ?. delete ( id ) ;
3436 cb ( e ) ;
3537 } ;
3638 }
3739 // Only `capture` option is necessary for `removeEventListener`.
38- event_listener_map [ el ] [ id ] = [ event_type , _cb , opts . capture ? opts : undefined ] ;
40+ event_listener_map
41+ . get ( el )
42+ . set ( id , [ event_type , _cb , opts . capture ? opts : undefined ] ) ;
3943 el . addEventListener ( event_type , _cb , opts ) ;
4044} ;
4145
4246/**
4347 * Remove an event listener from a DOM element under a unique id.
4448 *
45- * @param {DOM Node } el - The element to register the event for.
46- * @param {string } id - A unique id under which the event is registered.
49+ * If an element and id are given, the event listeners for the given element matching the id are removed.
50+ * If an element but no id is given, all event listeners for that element are removed.
51+ * If an id but no element is given, all event listeners for any element matching the id are removed.
52+ * If no element and no id are given, all event listeners are removed.
53+ *
54+ * The id can be a wildcard string, e.g. `test-*-event`, which would match any
55+ * event which starts with "test-" and ends with "-event". The wildcard "*" can
56+ * be anywhere in the string and also be used multiple times. If no wildcard is
57+ * present the search string is used for an exact match.
58+ *
59+ * @param {DOM Node } [el] - The element to register the event for.
60+ * @param {string } [id] - A unique id under which the event is registered.
61+ * Can be a wildcard string.
4762 *
4863 */
4964const remove_event_listener = ( el , id ) => {
50- if ( ! el ?. removeEventListener ) {
51- return ; // nothing to do.
52- }
53- const el_events = event_listener_map [ el ] ;
54- if ( ! el_events ) {
55- return ;
56- }
57- let entries ;
58- if ( id ) {
59- // remove event listener with specific id
60- const entry = el_events [ id ] ;
61- entries = entry ? [ entry ] : [ ] ;
62- } else {
63- // remove all event listeners of element
64- entries = Object . entries ( el_events ) ;
65- }
66- for ( const entry of entries || [ ] ) {
67- el . removeEventListener ( entry [ 0 ] , entry [ 1 ] , entry [ 2 ] ) ;
65+ const els = el ? [ el ] : event_listener_map . keys ( ) ;
66+ for ( const el of els ) {
67+ if ( ! el ?. removeEventListener ) {
68+ return ; // nothing to do.
69+ }
70+ const el_events = event_listener_map . get ( el ) ;
71+ if ( ! el_events ) {
72+ return ;
73+ }
74+ let entries ;
75+ if ( id ) {
76+ // remove event listener with matching id
77+ entries = [ ...el_events . entries ( ) ] . filter ( ( entry ) =>
78+ utils . regexp_from_wildcard ( id ) . test ( entry [ 0 ] )
79+ ) ;
80+ } else {
81+ // remove all event listeners of element
82+ entries = el_events . entries ( ) ;
83+ }
84+ for ( const entry of entries || [ ] ) {
85+ // Remove event listener
86+ el . removeEventListener ( entry [ 1 ] [ 0 ] , entry [ 1 ] [ 1 ] , entry [ 1 ] [ 2 ] ) ;
87+ // Delete entry from event_listener_map
88+ event_listener_map . get ( el ) . delete ( entry [ 0 ] ) ;
89+ // Delete element from event_listener_map if no more events are registered.
90+ if ( ! event_listener_map . get ( el ) . size ) {
91+ event_listener_map . delete ( el ) ;
92+ }
93+ }
6894 }
6995} ;
7096
0 commit comments