packages/miew-cli/src/EventDispatcher.js

Summary

Maintainability
D
1 day
Test Coverage
/**
 * This class introduces the simplest event system.
 */

import { remove, find, forEach, omitBy } from 'lodash'

function isUndefOrEqual(param, value) {
  return !param || param === value
}

/**
 * Creates empty dispatcher.
 *
 * @exports EventDispatcher
 * @constructor
 */
function EventDispatcher() {
  this._handlers = {}
}

/**
 * Binds callback on specific event type. Optional `context` parameter
 * could be used as 'this' for the `callback`.
 * @param {string}   type       Event name.
 * @param {function} callback   Callback function.
 * @param {Object}   [context] 'This' object for the callback.
 */
EventDispatcher.prototype.addEventListener = function (
  type,
  callback,
  context
) {
  let handlers = this._handlers[type]

  if (!handlers) {
    this._handlers[type] = []
    handlers = this._handlers[type]
  }

  const params = [callback, context]
  function _checkPar(par) {
    return par[0] === params[0] && par[1] === params[1]
  }

  if (find(handlers, _checkPar) === undefined) {
    handlers.push(params)
  }
}

/**
 * Removes a previously-bound callback function from an object.
 * If no `context` is specified, all versions of the `callback` with different
 * contexts will be removed.
 * If no `callback` is specified, all callbacks of the `type` will be removed.
 * If no `type` is specified, callbacks for all events will be removed.
 * @param {?string}  [type]      Event type.
 * @param {function} [callback]  Callback function.
 * @param {Object}   [context]  'This' object for the callback.
 */
EventDispatcher.prototype.removeEventListener = function (
  type,
  callback,
  context
) {
  const self = this
  forEach(self._handlers, (handler, ev) => {
    remove(
      handler,
      (values) =>
        isUndefOrEqual(type, ev) &&
        isUndefOrEqual(callback, values[0]) &&
        isUndefOrEqual(context, values[1] || self)
    )
  })

  this._handlers = omitBy(self._handlers, (handler) => handler.length === 0)
}

/**
 * Makes all the callbacks for the specific `event` to trigger.
 * @param {Object} event      Event.
 * @param {string} event.type Type of the event.
 */
EventDispatcher.prototype.dispatchEvent = function (event) {
  const self = this

  forEach(this._handlers[event.type], (callback) => {
    const context = callback[1] || self
    callback[0].apply(context, [event])
  })
}

export default EventDispatcher