All files / packages/core/src/utilities/eventListener MultiTargetEventListenerManager.ts

0% Statements 0/15
0% Branches 0/6
0% Functions 0/4
0% Lines 0/15

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                                                                                                                                                                                     
import TargetEventListeners from './TargetEventListeners';
 
/**
 * MultiTargetEventListenerManager allows you to add event listeners to multiple
 * HTML elements (targets) with support for event types with namespace,
 * allow removing events without having to pass a callback and makes it possible
 * to remove all event lsiteners from all HTML elements in a much simpler avoiding
 * leaving listeners behind which would result in memory leaks.
 *
 * @example
 * Adding and removing event listeners
 * ```javascript
 *   const eventListenerManager = new MultiTargetEventListenerManager()
 *   const element1 = document.getElementById('foo');
 *   const element2 = document.getElementById('bar');
 *   const mouseoverCallback = () => { };
 *   const mouseoutCallback = () => { };
 *   const dragCallback = () => { };
 *
 *   eventListenerManager.addEventListener(element1, 'mouseover', mouseoverCallback);
 *   eventListenerManager.addEventListener(element1, 'mouseout', mouseoutCallback);
 *
 *   eventListenerManager.addEventListener(element2, 'voi.mousemove', dragCallback);
 *   eventListenerManager.addEventListener(element2, 'voi.drag', dragCallback);
 *   eventListenerManager.addEventListener(element2, 'voi.mouseup', () => {
 *     // do not need to store a reference of this function
 *   }));
 *
 *   // Removes a specific event listener from element2
 *   eventListenerManager.removeEventListener(element2, 'voi.mousemove', dragCallback)
 *
 *   // Removes all "mouseup" event listeners added to "voi" namespace on element2
 *   eventListenerManager.removeEventListener(element2, 'voi.mouseup')
 *
 *   // Removes all event listeners added to element1 and element2
 *   eventListenerManager.reset();
 * ```
 */
class MultiTargetEventListenerManager {
  private _targetsEventListeners = new Map<EventTarget, TargetEventListeners>();
 
  public addEventListener(
    target: EventTarget,
    type: string,
    callback: EventListener,
    options?: AddEventListenerOptions
  ) {
    let eventListeners = this._targetsEventListeners.get(target);
 
    if (!eventListeners) {
      eventListeners = new TargetEventListeners(target);
      this._targetsEventListeners.set(target, eventListeners);
    }
 
    eventListeners.addEventListener(type, callback, options);
  }
 
  public removeEventListener(
    target: EventTarget,
    type: string,
    callback?: EventListener,
    options?: EventListenerOptions
  ) {
    const eventListeners = this._targetsEventListeners.get(target);
 
    if (!eventListeners) {
      return;
    }
 
    eventListeners.removeEventListener(type, callback, options);
 
    if (eventListeners.isEmpty) {
      this._targetsEventListeners.delete(target);
    }
  }
 
  public reset() {
    Array.from(this._targetsEventListeners.entries()).forEach(
      ([target, targetEventListeners]) => {
        targetEventListeners.reset();
        this._targetsEventListeners.delete(target);
      }
    );
  }
}
 
export {
  MultiTargetEventListenerManager as default,
  MultiTargetEventListenerManager,
};