123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*!
- * Unipointer v2.3.0
- * base class for doing one thing with pointer event
- * MIT license
- */
- /*jshint browser: true, undef: true, unused: true, strict: true */
- ( function( window, factory ) {
- // universal module definition
- /* jshint strict: false */ /*global define, module, require */
- if ( typeof define == 'function' && define.amd ) {
- // AMD
- define( [
- 'ev-emitter/ev-emitter'
- ], function( EvEmitter ) {
- return factory( window, EvEmitter );
- });
- } else if ( typeof module == 'object' && module.exports ) {
- // CommonJS
- module.exports = factory(
- window,
- require('ev-emitter')
- );
- } else {
- // browser global
- window.Unipointer = factory(
- window,
- window.EvEmitter
- );
- }
- }( window, function factory( window, EvEmitter ) {
- 'use strict';
- function noop() {}
- 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 );
- };
- /**
- * Add or remove start event
- * @param {Boolean} isAdd - remove if falsey
- */
- proto._bindStartEvent = function( elem, isAdd ) {
- // munge isAdd, default to true
- isAdd = isAdd === undefined ? true : isAdd;
- var bindMethod = isAdd ? 'addEventListener' : 'removeEventListener';
- // default to mouse events
- var startEvent = 'mousedown';
- if ( window.PointerEvent ) {
- // Pointer Events
- startEvent = 'pointerdown';
- } else if ( 'ontouchstart' in window ) {
- // Touch Events. iOS Safari
- startEvent = 'touchstart';
- }
- elem[ bindMethod ]( startEvent, 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() {
- this._pointerReset();
- this._unbindPostStartEvents();
- this.pointerDone();
- };
- proto._pointerReset = function() {
- // reset properties
- this.isPointerDown = false;
- delete this.pointerIdentifier;
- };
- proto.pointerDone = noop;
- // ----- 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
- };
- };
- // ----- ----- //
- return Unipointer;
- }));
|