All files / src/support/dom events.ts

100% Statements 32/32
100% Branches 20/20
100% Functions 11/11
100% Lines 29/29

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        10x 40x 5x 5x     5x         3x             40x   116x                             10x           76x 80x                     10x           40x 40x 40x 40x 40x 40x             40x 76x   8x 8x       76x 76x     40x             10x           10x           10x 1x  
import { isUndefined } from 'support/utils/types';
import { each, push, runEach } from 'support/utils/array';
 
let passiveEventsSupport: boolean;
const supportPassiveEvents = (): boolean => {
  if (isUndefined(passiveEventsSupport)) {
    passiveEventsSupport = false;
    try {
      /* eslint-disable */
      // @ts-ignore
      window.addEventListener(
        'test',
        null,
        Object.defineProperty({}, 'passive', {
          get: function () {
            passiveEventsSupport = true;
          },
        })
      );
      /* eslint-enable */
    } catch (e) {}
  }
  return passiveEventsSupport;
};
const splitEventNames = (eventNames: string) => eventNames.split(' ');
 
export interface OnOptions {
  _capture?: boolean;
  _passive?: boolean;
  _once?: boolean;
}
 
/**
 * Removes the passed event listener for the passed events with the passed options.
 * @param target The element from which the listener shall be removed.
 * @param eventNames The eventsnames for which the listener shall be removed.
 * @param listener The listener which shall be removed.
 * @param capture The options of the removed listener.
 */
export const off = <T extends Event = Event>(
  target: EventTarget,
  eventNames: string,
  listener: (event: T) => any,
  capture?: boolean
): void => {
  each(splitEventNames(eventNames), (eventName) => {
    target.removeEventListener(eventName, listener as EventListener, capture);
  });
};
 
/**
 * Adds the passed event listener for the passed eventnames with the passed options.
 * @param target The element to which the listener shall be added.
 * @param eventNames The eventsnames for which the listener shall be called.
 * @param listener The listener which is called on the eventnames.
 * @param options The options of the added listener.
 */
export const on = <T extends Event = Event>(
  target: EventTarget,
  eventNames: string,
  listener: (event: T) => any,
  options?: OnOptions
): (() => void) => {
  const doSupportPassiveEvents = supportPassiveEvents();
  const passive = (doSupportPassiveEvents && options && options._passive) || false;
  const capture = (options && options._capture) || false;
  const once = (options && options._once) || false;
  const offListeners: (() => void)[] = [];
  const nativeOptions: AddEventListenerOptions | boolean = doSupportPassiveEvents
    ? {
        passive,
        capture,
      }
    : capture;
 
  each(splitEventNames(eventNames), (eventName) => {
    const finalListener = (once
      ? (evt: T) => {
          target.removeEventListener(eventName, finalListener, capture);
          listener && listener(evt);
        }
      : listener) as EventListener;
 
    push(offListeners, off.bind(null, target, eventName, finalListener, capture));
    target.addEventListener(eventName, finalListener, nativeOptions);
  });
 
  return runEach.bind(0, offListeners);
};
 
/**
 * Shorthand for the stopPropagation event Method.
 * @param evt The event of which the stopPropagation method shall be called.
 */
export const stopPropagation = (evt: Event): void => evt.stopPropagation();
 
/**
 * Shorthand for the preventDefault event Method.
 * @param evt The event of which the preventDefault method shall be called.
 */
export const preventDefault = (evt: Event): void => evt.preventDefault();
 
/**
 * Shorthand for the stopPropagation and preventDefault event Method.
 * @param evt The event of which the stopPropagation and preventDefault methods shall be called.
 */
export const stopAndPrevent = (evt: Event): void =>
  (stopPropagation(evt) as undefined) || (preventDefault(evt) as undefined);