Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
react-fluckity / fluckity / Unipointer.js
Size: Mime:
// #onenoop
const { NO_OP } = require('exotic')
const EvEmitter = require('./EvEmitter')

module.exports = Unipointer

function Unipointer() {}

// inherit EvEmitter
var proto = (Unipointer.prototype = Object.create(EvEmitter.prototype))

proto.bindStartEvent = function(elem) {
  this._bindStartEvent(elem, true)
}

proto.unbindStartEvent = function(elem) {
  this._bindStartEvent(elem, false)
}

/**
 * works as unbinder, as you can ._bindStart( false ) to unbind
 * @param {Boolean} isBind - will unbind if falsey
 */
proto._bindStartEvent = function(elem, isBind) {
  // munge isBind, default to true
  isBind = isBind === undefined ? true : !!isBind
  var bindMethod = isBind ? 'addEventListener' : 'removeEventListener'

  if (window.PointerEvent) {
    // Pointer Events. Chrome 55, IE11, Edge 14
    elem[bindMethod]('pointerdown', this)
  } else {
    // listen for both, for devices like Chrome Pixel
    elem[bindMethod]('mousedown', this)
    elem[bindMethod]('touchstart', this)
  }
}

// trigger handler methods for events
proto.handleEvent = function(event) {
  var method = 'on' + event.type
  if (this[method]) {
    this[method](event)
  }
}

// returns the touch that we're keeping track of
proto.getTouch = function(touches) {
  for (var i = 0; i < touches.length; i++) {
    var touch = touches[i]
    if (touch.identifier == this.pointerIdentifier) {
      return touch
    }
  }
}

// ----- start event ----- //

proto.onmousedown = function(event) {
  // dismiss clicks from right or middle buttons
  var button = event.button
  if (button && (button !== 0 && button !== 1)) {
    return
  }
  this._pointerDown(event, event)
}

proto.ontouchstart = function(event) {
  this._pointerDown(event, event.changedTouches[0])
}

proto.onpointerdown = function(event) {
  this._pointerDown(event, event)
}

/**
 * pointer start
 * @param {Event} event
 * @param {Event or Touch} pointer
 */
proto._pointerDown = function(event, pointer) {
  // dismiss right click and other pointers
  // button = 0 is okay, 1-4 not
  if (event.button || this.isPointerDown) {
    return
  }

  this.isPointerDown = true
  // save pointer identifier to match up touch events
  this.pointerIdentifier =
    pointer.pointerId !== undefined
      ? // pointerId for pointer events, touch.indentifier for touch events
        pointer.pointerId
      : pointer.identifier

  this.pointerDown(event, pointer)
}

proto.pointerDown = function(event, pointer) {
  this._bindPostStartEvents(event)
  this.emitEvent('pointerDown', [event, pointer])
}

// hash of events to be bound after start event
var postStartEvents = {
  mousedown: ['mousemove', 'mouseup'],
  touchstart: ['touchmove', 'touchend', 'touchcancel'],
  pointerdown: ['pointermove', 'pointerup', 'pointercancel']
}

proto._bindPostStartEvents = function(event) {
  if (!event) {
    return
  }
  // get proper events to match start event
  var events = postStartEvents[event.type]
  // bind events to node
  events.forEach(function(eventName) {
    window.addEventListener(eventName, this)
  }, this)
  // save these arguments
  this._boundPointerEvents = events
}

proto._unbindPostStartEvents = function() {
  // check for _boundEvents, in case dragEnd triggered twice (old IE8 bug)
  if (!this._boundPointerEvents) {
    return
  }
  this._boundPointerEvents.forEach(function(eventName) {
    window.removeEventListener(eventName, this)
  }, this)

  delete this._boundPointerEvents
}

// ----- move event ----- //

proto.onmousemove = function(event) {
  this._pointerMove(event, event)
}

proto.onpointermove = function(event) {
  if (event.pointerId == this.pointerIdentifier) {
    this._pointerMove(event, event)
  }
}

proto.ontouchmove = function(event) {
  var touch = this.getTouch(event.changedTouches)
  if (touch) {
    this._pointerMove(event, touch)
  }
}

/**
 * pointer move
 * @param {Event} event
 * @param {Event or Touch} pointer
 * @private
 */
proto._pointerMove = function(event, pointer) {
  this.pointerMove(event, pointer)
}

// public
proto.pointerMove = function(event, pointer) {
  this.emitEvent('pointerMove', [event, pointer])
}

// ----- end event ----- //

proto.onmouseup = function(event) {
  this._pointerUp(event, event)
}

proto.onpointerup = function(event) {
  if (event.pointerId == this.pointerIdentifier) {
    this._pointerUp(event, event)
  }
}

proto.ontouchend = function(event) {
  var touch = this.getTouch(event.changedTouches)
  if (touch) {
    this._pointerUp(event, touch)
  }
}

/**
 * pointer up
 * @param {Event} event
 * @param {Event or Touch} pointer
 * @private
 */
proto._pointerUp = function(event, pointer) {
  this._pointerDone()
  this.pointerUp(event, pointer)
}

// public
proto.pointerUp = function(event, pointer) {
  this.emitEvent('pointerUp', [event, pointer])
}

// ----- pointer done ----- //

// triggered on pointer up & pointer cancel
proto._pointerDone = function() {
  // reset properties
  this.isPointerDown = false
  delete this.pointerIdentifier
  // remove events
  this._unbindPostStartEvents()
  this.pointerDone()
}

proto.pointerDone = NO_OP

// ----- pointer cancel ----- //

proto.onpointercancel = function(event) {
  if (event.pointerId == this.pointerIdentifier) {
    this._pointerCancel(event, event)
  }
}

proto.ontouchcancel = function(event) {
  var touch = this.getTouch(event.changedTouches)
  if (touch) {
    this._pointerCancel(event, touch)
  }
}

/**
 * pointer cancel
 * @param {Event} event
 * @param {Event or Touch} pointer
 * @private
 */
proto._pointerCancel = function(event, pointer) {
  this._pointerDone()
  this.pointerCancel(event, pointer)
}

// public
proto.pointerCancel = function(event, pointer) {
  this.emitEvent('pointerCancel', [event, pointer])
}

// -----  ----- //

// utility function for getting x/y coords from event
Unipointer.getPointerPoint = function(pointer) {
  return {
    x: pointer.pageX,
    y: pointer.pageY
  }
}

// -----  ----- //