Home Reference Source

src/Draggable/Sensors/Sensor/Sensor.js

const defaultDealy = {
  mouse: 0,
  drag: 0,
  touch: 100,
};

/**
 * Base sensor class. Extend from this class to create a new or custom sensor
 * @class Sensor
 * @module Sensor
 */
export default class Sensor {
  /**
   * Sensor constructor.
   * @constructs Sensor
   * @param {HTMLElement[]|NodeList|HTMLElement} containers - Containers
   * @param {Object} options - Options
   */
  constructor(containers = [], options = {}) {
    /**
     * Current containers
     * @property containers
     * @type {HTMLElement[]}
     */
    this.containers = [...containers];

    /**
     * Current options
     * @property options
     * @type {Object}
     */
    this.options = {...options};

    /**
     * Current drag state
     * @property dragging
     * @type {Boolean}
     */
    this.dragging = false;

    /**
     * Current container
     * @property currentContainer
     * @type {HTMLElement}
     */
    this.currentContainer = null;

    /**
     * The event of the initial sensor down
     * @property startEvent
     * @type {Event}
     */
    this.startEvent = null;

    /**
     * The delay of each sensor
     * @property delay
     * @type {Object}
     */
    this.delay = calcDelay(options.delay);
  }

  /**
   * Attaches sensors event listeners to the DOM
   * @return {Sensor}
   */
  attach() {
    return this;
  }

  /**
   * Detaches sensors event listeners to the DOM
   * @return {Sensor}
   */
  detach() {
    return this;
  }

  /**
   * Adds container to this sensor instance
   * @param {...HTMLElement} containers - Containers you want to add to this sensor
   * @example draggable.addContainer(document.body)
   */
  addContainer(...containers) {
    this.containers = [...this.containers, ...containers];
  }

  /**
   * Removes container from this sensor instance
   * @param {...HTMLElement} containers - Containers you want to remove from this sensor
   * @example draggable.removeContainer(document.body)
   */
  removeContainer(...containers) {
    this.containers = this.containers.filter((container) => !containers.includes(container));
  }

  /**
   * Triggers event on target element
   * @param {HTMLElement} element - Element to trigger event on
   * @param {SensorEvent} sensorEvent - Sensor event to trigger
   */
  trigger(element, sensorEvent) {
    const event = document.createEvent('Event');
    event.detail = sensorEvent;
    event.initEvent(sensorEvent.type, true, true);
    element.dispatchEvent(event);
    this.lastEvent = sensorEvent;

    return sensorEvent;
  }
}

/**
 * Calculate the delay of each sensor through the delay in the options
 * @param {undefined|Number|Object} optionsDelay - the delay in the options
 * @return {Object}
 */
function calcDelay(optionsDelay) {
  const delay = {};

  if (optionsDelay === undefined) {
    return {...defaultDealy};
  }

  if (typeof optionsDelay === 'number') {
    for (const key in defaultDealy) {
      if (defaultDealy.hasOwnProperty(key)) {
        delay[key] = optionsDelay;
      }
    }
    return delay;
  }

  for (const key in defaultDealy) {
    if (defaultDealy.hasOwnProperty(key)) {
      if (optionsDelay[key] === undefined) {
        delay[key] = defaultDealy[key];
      } else {
        delay[key] = optionsDelay[key];
      }
    }
  }

  return delay;
}