Source: EventDispatcher.js

/**
 * @class EventDispatcher
 *
 * Implements the interface EventTarget.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
 */
class EventDispatcher
{
  /**
   * @param p_initial_events {Object}
   *          An object containing default events that
   *          are to be dispatched whenever a corresponding
   *          event listener is added.
   */
  constructor(p_initial_events = null)
  {
    this.v_initial_events = p_initial_events;
    this.v_listeners = {};
  }

  /**
   * @param p_type     {String}
   * @param p_callback {Function}
   */
  addEventListener(p_type, p_callback)
  {
    let l_initial_event = this.v_initial_events[p_type];

    if (!(p_type in this.v_listeners))
      this.v_listeners[p_type] = [];
    this.v_listeners[p_type].push(p_callback);

    if (l_initial_event != null)
      this.dispatchEvent(l_initial_event);
  }

  /**
   * @param p_type     {String}
   * @param p_callback {Function}
   */
  removeEventListener(p_type, p_callback)
  {
    if (!(p_type in this.v_listeners))
      return;

    let l_callbacks = this.v_listeners[p_type];

    for (let i = 0, n = l_callbacks.length; i < n; i++)
      if (l_callbacks[i] === p_callback)
      {
        l_callbacks.splice(i, 1);
        return;
      }
  }

  /**
   * @param p_event {CustomEvent}
   * @return {Boolean}
   */
  dispatchEvent(p_event)
  {
    if (!(p_event.type in this.v_listeners))
      return true;

    let l_callbacks = this.v_listeners[p_event.type];

    for (let i = 0, n = l_callbacks.length; i < n; i++)
      l_callbacks[i].call(this, p_event);

    return !p_event.defaultPrevented;
  }
}

export default EventDispatcher;