summaryrefslogtreecommitdiffstats
path: root/js/drag.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/drag.js')
-rw-r--r--js/drag.js185
1 files changed, 111 insertions, 74 deletions
diff --git a/js/drag.js b/js/drag.js
index 55cd3d9..246dbe6 100644
--- a/js/drag.js
+++ b/js/drag.js
@@ -1,24 +1,20 @@
+// drag
( function( window, factory ) {
- 'use strict';
// universal module definition
-
+ /* jshint strict: false */
if ( typeof define == 'function' && define.amd ) {
// AMD
define( [
- 'classie/classie',
- 'eventie/eventie',
'./flickity',
'unidragger/unidragger',
'fizzy-ui-utils/utils'
- ], function( classie, eventie, Flickity, Unidragger, utils ) {
- return factory( window, classie, eventie, Flickity, Unidragger, utils );
+ ], function( Flickity, Unidragger, utils ) {
+ return factory( window, Flickity, Unidragger, utils );
});
- } else if ( typeof exports == 'object' ) {
+ } else if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory(
window,
- require('desandro-classie'),
- require('eventie'),
require('./flickity'),
require('unidragger'),
require('fizzy-ui-utils')
@@ -27,31 +23,21 @@
// browser global
window.Flickity = factory(
window,
- window.classie,
- window.eventie,
window.Flickity,
window.Unidragger,
window.fizzyUIUtils
);
}
-}( window, function factory( window, classie, eventie, Flickity, Unidragger, utils ) {
+}( window, function factory( window, Flickity, Unidragger, utils ) {
'use strict';
-// handle IE8 prevent default
-function preventDefaultEvent( event ) {
- if ( event.preventDefault ) {
- event.preventDefault();
- } else {
- event.returnValue = false;
- }
-}
-
// ----- defaults ----- //
utils.extend( Flickity.defaults, {
- draggable: true
+ draggable: true,
+ dragThreshold: 3,
});
// ----- create ----- //
@@ -60,50 +46,69 @@ Flickity.createMethods.push('_createDrag');
// -------------------------- drag prototype -------------------------- //
-utils.extend( Flickity.prototype, Unidragger.prototype );
+var proto = Flickity.prototype;
+utils.extend( proto, Unidragger.prototype );
// -------------------------- -------------------------- //
-Flickity.prototype._createDrag = function() {
+proto._createDrag = function() {
this.on( 'activate', this.bindDrag );
this.on( 'uiChange', this._uiChangeDrag );
this.on( 'childUIPointerDown', this._childUIPointerDownDrag );
this.on( 'deactivate', this.unbindDrag );
};
-Flickity.prototype.bindDrag = function() {
+proto.bindDrag = function() {
if ( !this.options.draggable || this.isDragBound ) {
return;
}
- classie.add( this.element, 'is-draggable' );
+ this.element.classList.add('is-draggable');
this.handles = [ this.viewport ];
this.bindHandles();
this.isDragBound = true;
};
-Flickity.prototype.unbindDrag = function() {
+proto.unbindDrag = function() {
if ( !this.isDragBound ) {
return;
}
- classie.remove( this.element, 'is-draggable' );
+ this.element.classList.remove('is-draggable');
this.unbindHandles();
delete this.isDragBound;
};
-Flickity.prototype._uiChangeDrag = function() {
+proto._uiChangeDrag = function() {
delete this.isFreeScrolling;
};
-Flickity.prototype._childUIPointerDownDrag = function( event ) {
- preventDefaultEvent( event );
+proto._childUIPointerDownDrag = function( event ) {
+ event.preventDefault();
this.pointerDownFocus( event );
};
// -------------------------- pointer events -------------------------- //
-Flickity.prototype.pointerDown = function( event, pointer ) {
- // dismiss range sliders
- if ( event.target.nodeName == 'INPUT' && event.target.type == 'range' ) {
+// nodes that have text fields
+var cursorNodes = {
+ TEXTAREA: true,
+ INPUT: true,
+};
+
+// input types that do not have text fields
+var clickTypes = {
+ radio: true,
+ checkbox: true,
+ button: true,
+ submit: true,
+ image: true,
+ file: true,
+};
+
+proto.pointerDown = function( event, pointer ) {
+ // dismiss inputs with text fields. #404
+ var isCursorInput = cursorNodes[ event.target.nodeName ] &&
+ !clickTypes[ event.target.type ];
+ if ( isCursorInput ) {
// reset pointerDown logic
this.isPointerDown = false;
delete this.pointerIdentifier;
@@ -122,12 +127,12 @@ Flickity.prototype.pointerDown = function( event, pointer ) {
this.pointerDownFocus( event );
// stop if it was moving
this.dragX = this.x;
- classie.add( this.viewport, 'is-pointer-down' );
+ this.viewport.classList.add('is-pointer-down');
// bind move and end events
this._bindPostStartEvents( event );
// track scrolling
- this.pointerDownScroll = Unidragger.getScrollPosition();
- eventie.bind( window, 'scroll', this );
+ this.pointerDownScroll = getScrollPosition();
+ window.addEventListener( 'scroll', this );
this.dispatchEvent( 'pointerDown', event, [ pointer ] );
};
@@ -142,7 +147,7 @@ var focusNodes = {
SELECT: true
};
-Flickity.prototype.pointerDownFocus = function( event ) {
+proto.pointerDownFocus = function( event ) {
// focus element, if not touch, and its not an input or select
if ( !this.options.accessibility || touchStartEvents[ event.type ] ||
focusNodes[ event.target.nodeName ] ) {
@@ -156,46 +161,54 @@ Flickity.prototype.pointerDownFocus = function( event ) {
}
};
+proto.canPreventDefaultOnPointerDown = function( event ) {
+ // prevent default, unless touchstart or <select>
+ var isTouchstart = event.type == 'touchstart';
+ var targetNodeName = event.target.nodeName;
+ return !isTouchstart && targetNodeName != 'SELECT';
+};
+
// ----- move ----- //
-Flickity.prototype.hasDragStarted = function( moveVector ) {
- return Math.abs( moveVector.x ) > 3;
+proto.hasDragStarted = function( moveVector ) {
+ return Math.abs( moveVector.x ) > this.options.dragThreshold;
};
// ----- up ----- //
-Flickity.prototype.pointerUp = function( event, pointer ) {
- classie.remove( this.viewport, 'is-pointer-down' );
+proto.pointerUp = function( event, pointer ) {
+ delete this.isTouchScrolling;
+ this.viewport.classList.remove('is-pointer-down');
this.dispatchEvent( 'pointerUp', event, [ pointer ] );
this._dragPointerUp( event, pointer );
};
-Flickity.prototype.pointerDone = function() {
- eventie.unbind( window, 'scroll', this );
+proto.pointerDone = function() {
+ window.removeEventListener( 'scroll', this );
delete this.pointerDownScroll;
};
// -------------------------- dragging -------------------------- //
-Flickity.prototype.dragStart = function( event, pointer ) {
+proto.dragStart = function( event, pointer ) {
this.dragStartPosition = this.x;
this.startAnimation();
this.dispatchEvent( 'dragStart', event, [ pointer ] );
};
-Flickity.prototype.dragMove = function( event, pointer, moveVector ) {
- preventDefaultEvent( event );
+proto.dragMove = function( event, pointer, moveVector ) {
+ event.preventDefault();
this.previousDragX = this.dragX;
// reverse if right-to-left
var direction = this.options.rightToLeft ? -1 : 1;
var dragX = this.dragStartPosition + moveVector.x * direction;
- if ( !this.options.wrapAround && this.cells.length ) {
+ if ( !this.options.wrapAround && this.slides.length ) {
// slow drag
- var originBound = Math.max( -this.cells[0].target, this.dragStartPosition );
+ var originBound = Math.max( -this.slides[0].target, this.dragStartPosition );
dragX = dragX > originBound ? ( dragX + originBound ) * 0.5 : dragX;
- var endBound = Math.min( -this.getLastCell().target, this.dragStartPosition );
+ var endBound = Math.min( -this.getLastSlide().target, this.dragStartPosition );
dragX = dragX < endBound ? ( dragX + endBound ) * 0.5 : dragX;
}
@@ -205,7 +218,7 @@ Flickity.prototype.dragMove = function( event, pointer, moveVector ) {
this.dispatchEvent( 'dragMove', event, [ pointer, moveVector ] );
};
-Flickity.prototype.dragEnd = function( event, pointer ) {
+proto.dragEnd = function( event, pointer ) {
if ( this.options.freeScroll ) {
this.isFreeScrolling = true;
}
@@ -214,11 +227,11 @@ Flickity.prototype.dragEnd = function( event, pointer ) {
if ( this.options.freeScroll && !this.options.wrapAround ) {
// if free-scroll & not wrap around
- // do not free-scroll if going outside of bounding cells
- // so bounding cells can attract slider, and keep it in bounds
+ // do not free-scroll if going outside of bounding slides
+ // so bounding slides can attract slider, and keep it in bounds
var restingX = this.getRestingPosition();
- this.isFreeScrolling = -restingX > this.cells[0].target &&
- -restingX < this.getLastCell().target;
+ this.isFreeScrolling = -restingX > this.slides[0].target &&
+ -restingX < this.getLastSlide().target;
} else if ( !this.options.freeScroll && index == this.selectedIndex ) {
// boost selection if selected index has not changed
index += this.dragEndBoostSelect();
@@ -226,14 +239,17 @@ Flickity.prototype.dragEnd = function( event, pointer ) {
delete this.previousDragX;
// apply selection
// TODO refactor this, selecting here feels weird
+ // HACK, set flag so dragging stays in correct direction
+ this.isDragSelect = this.options.wrapAround;
this.select( index );
+ delete this.isDragSelect;
this.dispatchEvent( 'dragEnd', event, [ pointer ] );
};
-Flickity.prototype.dragEndRestingSelect = function() {
+proto.dragEndRestingSelect = function() {
var restingX = this.getRestingPosition();
- // how far away from selected cell
- var distance = Math.abs( this.getCellDistance( -restingX, this.selectedIndex ) );
+ // how far away from selected slide
+ var distance = Math.abs( this.getSlideDistance( -restingX, this.selectedIndex ) );
// get closet resting going up and going down
var positiveResting = this._getClosestResting( restingX, distance, 1 );
var negativeResting = this._getClosestResting( restingX, distance, -1 );
@@ -251,7 +267,7 @@ Flickity.prototype.dragEndRestingSelect = function() {
* @param {Integer} increment - +1 or -1, going up or down
* @returns {Object} - { distance: {Number}, index: {Integer} }
*/
-Flickity.prototype._getClosestResting = function( restingX, distance, increment ) {
+proto._getClosestResting = function( restingX, distance, increment ) {
var index = this.selectedIndex;
var minDistance = Infinity;
var condition = this.options.contain && !this.options.wrapAround ?
@@ -261,7 +277,7 @@ Flickity.prototype._getClosestResting = function( restingX, distance, increment
// measure distance to next cell
index += increment;
minDistance = distance;
- distance = this.getCellDistance( -restingX, index );
+ distance = this.getSlideDistance( -restingX, index );
if ( distance === null ) {
break;
}
@@ -275,25 +291,25 @@ Flickity.prototype._getClosestResting = function( restingX, distance, increment
};
/**
- * measure distance between x and a cell target
+ * measure distance between x and a slide target
* @param {Number} x
- * @param {Integer} index - cell index
+ * @param {Integer} index - slide index
*/
-Flickity.prototype.getCellDistance = function( x, index ) {
- var len = this.cells.length;
- // wrap around if at least 2 cells
+proto.getSlideDistance = function( x, index ) {
+ var len = this.slides.length;
+ // wrap around if at least 2 slides
var isWrapAround = this.options.wrapAround && len > 1;
- var cellIndex = isWrapAround ? utils.modulo( index, len ) : index;
- var cell = this.cells[ cellIndex ];
- if ( !cell ) {
+ var slideIndex = isWrapAround ? utils.modulo( index, len ) : index;
+ var slide = this.slides[ slideIndex ];
+ if ( !slide ) {
return null;
}
- // add distance for wrap-around cells
+ // add distance for wrap-around slides
var wrap = isWrapAround ? this.slideableWidth * Math.floor( index / len ) : 0;
- return x - ( cell.target + wrap );
+ return x - ( slide.target + wrap );
};
-Flickity.prototype.dragEndBoostSelect = function() {
+proto.dragEndBoostSelect = function() {
// do not boost if no previousDragX or dragMoveTime
if ( this.previousDragX === undefined || !this.dragMoveTime ||
// or if drag was held for 100 ms
@@ -301,7 +317,7 @@ Flickity.prototype.dragEndBoostSelect = function() {
return 0;
}
- var distance = this.getCellDistance( -this.dragX, this.selectedIndex );
+ var distance = this.getSlideDistance( -this.dragX, this.selectedIndex );
var delta = this.previousDragX - this.dragX;
if ( distance > 0 && delta > 0 ) {
// boost to next if moving towards the right, and positive velocity
@@ -315,14 +331,35 @@ Flickity.prototype.dragEndBoostSelect = function() {
// ----- staticClick ----- //
-Flickity.prototype.staticClick = function( event, pointer ) {
+proto.staticClick = function( event, pointer ) {
// get clickedCell, if cell was clicked
var clickedCell = this.getParentCell( event.target );
var cellElem = clickedCell && clickedCell.element;
- var cellIndex = clickedCell && utils.indexOf( this.cells, clickedCell );
+ var cellIndex = clickedCell && this.cells.indexOf( clickedCell );
this.dispatchEvent( 'staticClick', event, [ pointer, cellElem, cellIndex ] );
};
+// ----- scroll ----- //
+
+proto.onscroll = function() {
+ var scroll = getScrollPosition();
+ var scrollMoveX = this.pointerDownScroll.x - scroll.x;
+ var scrollMoveY = this.pointerDownScroll.y - scroll.y;
+ // cancel click/tap if scroll is too much
+ if ( Math.abs( scrollMoveX ) > 3 || Math.abs( scrollMoveY ) > 3 ) {
+ this._pointerDone();
+ }
+};
+
+// ----- utils ----- //
+
+function getScrollPosition() {
+ return {
+ x: window.pageXOffset,
+ y: window.pageYOffset
+ };
+}
+
// ----- ----- //
return Flickity;