export function createListenHandler()

in src/lib/api/event.recorder.ts [198:296]


export function createListenHandler(
  _document: Document,
  prebootData: PrebootData,
  eventSelector: EventSelector,
  appData: PrebootAppData
): EventListener {
  const CARET_EVENTS = ['keyup', 'keydown', 'focusin', 'mouseup', 'mousedown'];
  const CARET_NODES = ['INPUT', 'TEXTAREA'];

  // Support: IE 9-11 only
  // IE uses a prefixed `matches` version
  const matches = _document.documentElement.matches ||
    (_document.documentElement as any).msMatchesSelector;
  const opts = prebootData.opts;

  return function(event: DomEvent) {
    const node: Element = event.target;

    // a delegated handlers on document is used so we need to check if
    // event target matches a desired selector
    if (!matches.call(node, eventSelector.selector)) {
      return;
    }

    const root = appData.root;
    const eventName = event.type;

    // if no node or no event name, just return
    if (!node || !eventName) {
      return;
    }

    // if key codes set for eventSelector, then don't do anything if event
    // doesn't include key
    const keyCodes = eventSelector.keyCodes;
    if (keyCodes && keyCodes.length) {
      const matchingKeyCodes = keyCodes.filter(keyCode => event.which === keyCode);

      // if there are not matches (i.e. key entered NOT one of the key codes)
      // then don't do anything
      if (!matchingKeyCodes.length) {
        return;
      }
    }

    // if for a given set of events we are preventing default, do that
    if (eventSelector.preventDefault) {
      event.preventDefault();
    }

    // if an action handler passed in, use that
    if (eventSelector.action) {
      eventSelector.action(node, event);
    }

    // get the node key for a given node
    const nodeKey = getNodeKeyForPreboot({ root: root, node: node });

    // record active node
    if (CARET_EVENTS.indexOf(eventName) >= 0) {
      // if it's an caret node, get the selection for the active node
      const isCaretNode = CARET_NODES.indexOf(node.tagName ? node.tagName : '') >= 0;

      prebootData.activeNode = {
        root: root,
        node: node,
        nodeKey: nodeKey,
        selection: isCaretNode ? getSelection(node as HTMLInputElement) : undefined
      };
    } else if (eventName !== 'change' && eventName !== 'focusout') {
      prebootData.activeNode = undefined;
    }

    // if overlay is not disabled and we are freezing the UI
    if (opts && !opts.disableOverlay && eventSelector.freeze) {
      const overlay = root.overlay as HTMLElement;

      // show the overlay
      overlay.style.display = 'block';

      // hide the overlay after 10 seconds just in case preboot.complete() never
      // called
      setTimeout(() => {
        overlay.style.display = 'none';
      }, 10000);
    }

    // we will record events for later replay unless explicitly marked as
    // doNotReplay
    if (eventSelector.replay) {
      appData.events.push({
        node,
        nodeKey,
        event,
        name: eventName
      });
    }
  };
}