284 lines
6.8 KiB
JavaScript
284 lines
6.8 KiB
JavaScript
|
/*!
|
||
|
* Unidragger v2.3.1
|
||
|
* Draggable base class
|
||
|
* MIT license
|
||
|
*/
|
||
|
|
||
|
/*jshint browser: true, unused: true, undef: true, strict: true */
|
||
|
|
||
|
( function( window, factory ) {
|
||
|
// universal module definition
|
||
|
/*jshint strict: false */ /*globals define, module, require */
|
||
|
|
||
|
if ( typeof define == 'function' && define.amd ) {
|
||
|
// AMD
|
||
|
define( [
|
||
|
'unipointer/unipointer'
|
||
|
], function( Unipointer ) {
|
||
|
return factory( window, Unipointer );
|
||
|
});
|
||
|
} else if ( typeof module == 'object' && module.exports ) {
|
||
|
// CommonJS
|
||
|
module.exports = factory(
|
||
|
window,
|
||
|
require('unipointer')
|
||
|
);
|
||
|
} else {
|
||
|
// browser global
|
||
|
window.Unidragger = factory(
|
||
|
window,
|
||
|
window.Unipointer
|
||
|
);
|
||
|
}
|
||
|
|
||
|
}( window, function factory( window, Unipointer ) {
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
// -------------------------- Unidragger -------------------------- //
|
||
|
|
||
|
function Unidragger() {}
|
||
|
|
||
|
// inherit Unipointer & EvEmitter
|
||
|
var proto = Unidragger.prototype = Object.create( Unipointer.prototype );
|
||
|
|
||
|
// ----- bind start ----- //
|
||
|
|
||
|
proto.bindHandles = function() {
|
||
|
this._bindHandles( true );
|
||
|
};
|
||
|
|
||
|
proto.unbindHandles = function() {
|
||
|
this._bindHandles( false );
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Add or remove start event
|
||
|
* @param {Boolean} isAdd
|
||
|
*/
|
||
|
proto._bindHandles = function( isAdd ) {
|
||
|
// munge isAdd, default to true
|
||
|
isAdd = isAdd === undefined ? true : isAdd;
|
||
|
// bind each handle
|
||
|
var bindMethod = isAdd ? 'addEventListener' : 'removeEventListener';
|
||
|
var touchAction = isAdd ? this._touchActionValue : '';
|
||
|
for ( var i=0; i < this.handles.length; i++ ) {
|
||
|
var handle = this.handles[i];
|
||
|
this._bindStartEvent( handle, isAdd );
|
||
|
handle[ bindMethod ]( 'click', this );
|
||
|
// touch-action: none to override browser touch gestures. metafizzy/flickity#540
|
||
|
if ( window.PointerEvent ) {
|
||
|
handle.style.touchAction = touchAction;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// prototype so it can be overwriteable by Flickity
|
||
|
proto._touchActionValue = 'none';
|
||
|
|
||
|
// ----- start event ----- //
|
||
|
|
||
|
/**
|
||
|
* pointer start
|
||
|
* @param {Event} event
|
||
|
* @param {Event or Touch} pointer
|
||
|
*/
|
||
|
proto.pointerDown = function( event, pointer ) {
|
||
|
var isOkay = this.okayPointerDown( event );
|
||
|
if ( !isOkay ) {
|
||
|
return;
|
||
|
}
|
||
|
// track start event position
|
||
|
// Safari 9 overrides pageX and pageY. These values needs to be copied. flickity#842
|
||
|
this.pointerDownPointer = {
|
||
|
pageX: pointer.pageX,
|
||
|
pageY: pointer.pageY,
|
||
|
};
|
||
|
|
||
|
event.preventDefault();
|
||
|
this.pointerDownBlur();
|
||
|
// bind move and end events
|
||
|
this._bindPostStartEvents( event );
|
||
|
this.emitEvent( 'pointerDown', [ event, pointer ] );
|
||
|
};
|
||
|
|
||
|
// nodes that have text fields
|
||
|
var cursorNodes = {
|
||
|
TEXTAREA: true,
|
||
|
INPUT: true,
|
||
|
SELECT: true,
|
||
|
OPTION: true,
|
||
|
};
|
||
|
|
||
|
// input types that do not have text fields
|
||
|
var clickTypes = {
|
||
|
radio: true,
|
||
|
checkbox: true,
|
||
|
button: true,
|
||
|
submit: true,
|
||
|
image: true,
|
||
|
file: true,
|
||
|
};
|
||
|
|
||
|
// dismiss inputs with text fields. flickity#403, flickity#404
|
||
|
proto.okayPointerDown = function( event ) {
|
||
|
var isCursorNode = cursorNodes[ event.target.nodeName ];
|
||
|
var isClickType = clickTypes[ event.target.type ];
|
||
|
var isOkay = !isCursorNode || isClickType;
|
||
|
if ( !isOkay ) {
|
||
|
this._pointerReset();
|
||
|
}
|
||
|
return isOkay;
|
||
|
};
|
||
|
|
||
|
// kludge to blur previously focused input
|
||
|
proto.pointerDownBlur = function() {
|
||
|
var focused = document.activeElement;
|
||
|
// do not blur body for IE10, metafizzy/flickity#117
|
||
|
var canBlur = focused && focused.blur && focused != document.body;
|
||
|
if ( canBlur ) {
|
||
|
focused.blur();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ----- move event ----- //
|
||
|
|
||
|
/**
|
||
|
* drag move
|
||
|
* @param {Event} event
|
||
|
* @param {Event or Touch} pointer
|
||
|
*/
|
||
|
proto.pointerMove = function( event, pointer ) {
|
||
|
var moveVector = this._dragPointerMove( event, pointer );
|
||
|
this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );
|
||
|
this._dragMove( event, pointer, moveVector );
|
||
|
};
|
||
|
|
||
|
// base pointer move logic
|
||
|
proto._dragPointerMove = function( event, pointer ) {
|
||
|
var moveVector = {
|
||
|
x: pointer.pageX - this.pointerDownPointer.pageX,
|
||
|
y: pointer.pageY - this.pointerDownPointer.pageY
|
||
|
};
|
||
|
// start drag if pointer has moved far enough to start drag
|
||
|
if ( !this.isDragging && this.hasDragStarted( moveVector ) ) {
|
||
|
this._dragStart( event, pointer );
|
||
|
}
|
||
|
return moveVector;
|
||
|
};
|
||
|
|
||
|
// condition if pointer has moved far enough to start drag
|
||
|
proto.hasDragStarted = function( moveVector ) {
|
||
|
return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;
|
||
|
};
|
||
|
|
||
|
// ----- end event ----- //
|
||
|
|
||
|
/**
|
||
|
* pointer up
|
||
|
* @param {Event} event
|
||
|
* @param {Event or Touch} pointer
|
||
|
*/
|
||
|
proto.pointerUp = function( event, pointer ) {
|
||
|
this.emitEvent( 'pointerUp', [ event, pointer ] );
|
||
|
this._dragPointerUp( event, pointer );
|
||
|
};
|
||
|
|
||
|
proto._dragPointerUp = function( event, pointer ) {
|
||
|
if ( this.isDragging ) {
|
||
|
this._dragEnd( event, pointer );
|
||
|
} else {
|
||
|
// pointer didn't move enough for drag to start
|
||
|
this._staticClick( event, pointer );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// -------------------------- drag -------------------------- //
|
||
|
|
||
|
// dragStart
|
||
|
proto._dragStart = function( event, pointer ) {
|
||
|
this.isDragging = true;
|
||
|
// prevent clicks
|
||
|
this.isPreventingClicks = true;
|
||
|
this.dragStart( event, pointer );
|
||
|
};
|
||
|
|
||
|
proto.dragStart = function( event, pointer ) {
|
||
|
this.emitEvent( 'dragStart', [ event, pointer ] );
|
||
|
};
|
||
|
|
||
|
// dragMove
|
||
|
proto._dragMove = function( event, pointer, moveVector ) {
|
||
|
// do not drag if not dragging yet
|
||
|
if ( !this.isDragging ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.dragMove( event, pointer, moveVector );
|
||
|
};
|
||
|
|
||
|
proto.dragMove = function( event, pointer, moveVector ) {
|
||
|
event.preventDefault();
|
||
|
this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
|
||
|
};
|
||
|
|
||
|
// dragEnd
|
||
|
proto._dragEnd = function( event, pointer ) {
|
||
|
// set flags
|
||
|
this.isDragging = false;
|
||
|
// re-enable clicking async
|
||
|
setTimeout( function() {
|
||
|
delete this.isPreventingClicks;
|
||
|
}.bind( this ) );
|
||
|
|
||
|
this.dragEnd( event, pointer );
|
||
|
};
|
||
|
|
||
|
proto.dragEnd = function( event, pointer ) {
|
||
|
this.emitEvent( 'dragEnd', [ event, pointer ] );
|
||
|
};
|
||
|
|
||
|
// ----- onclick ----- //
|
||
|
|
||
|
// handle all clicks and prevent clicks when dragging
|
||
|
proto.onclick = function( event ) {
|
||
|
if ( this.isPreventingClicks ) {
|
||
|
event.preventDefault();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// ----- staticClick ----- //
|
||
|
|
||
|
// triggered after pointer down & up with no/tiny movement
|
||
|
proto._staticClick = function( event, pointer ) {
|
||
|
// ignore emulated mouse up clicks
|
||
|
if ( this.isIgnoringMouseUp && event.type == 'mouseup' ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.staticClick( event, pointer );
|
||
|
|
||
|
// set flag for emulated clicks 300ms after touchend
|
||
|
if ( event.type != 'mouseup' ) {
|
||
|
this.isIgnoringMouseUp = true;
|
||
|
// reset flag after 300ms
|
||
|
setTimeout( function() {
|
||
|
delete this.isIgnoringMouseUp;
|
||
|
}.bind( this ), 400 );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
proto.staticClick = function( event, pointer ) {
|
||
|
this.emitEvent( 'staticClick', [ event, pointer ] );
|
||
|
};
|
||
|
|
||
|
// ----- utils ----- //
|
||
|
|
||
|
Unidragger.getPointerPoint = Unipointer.getPointerPoint;
|
||
|
|
||
|
// ----- ----- //
|
||
|
|
||
|
return Unidragger;
|
||
|
|
||
|
}));
|