Last active
December 23, 2015 11:49
-
-
Save aubricus/6630877 to your computer and use it in GitHub Desktop.
Swipe Detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SwipeEvent = { | |
'START' : 'start', | |
'DRAG' : 'drag', | |
'COMPLETE': 'complete', | |
'FAIL' : 'fail' | |
}; | |
/** | |
* @namespace Swipe | |
* @description Simple interface to detect a touch based "Swipe" | |
* @param {object} spec Configuration object {} | |
* @param {object} my This is used to share secrets between objects; optional. | |
* | |
* @returns {object} The public interface for the Swipe object | |
*/ | |
Swipe = function(spec, my){ | |
var self = {}; | |
var dispatcher = Dispatcher(); | |
my = my || {}; | |
var DIRECTION_UNKNOWN = 'unknown'; | |
var DIRECTION_RIGHT = 'right'; | |
var DIRECTION_LEFT = 'left'; | |
var error_target = '[Swipe] error no target specified'; | |
var target = spec.target || false; | |
var start = false; | |
var move = false; | |
var delta = false; | |
var direction = DIRECTION_UNKNOWN; | |
var _isScroll; | |
function __new__(){ | |
self.on = dispatcher.on; | |
self.off = dispatcher.off; | |
} | |
/* initialization */ | |
function __init__(){ | |
self.name = 'Swipe'; | |
if(target !== false){ | |
initializeTouch(target); | |
}else{ | |
throw error_target; | |
} | |
} | |
/* private methods */ | |
function initializeTouch(target){ | |
try{ | |
target.addEventListener('touchstart', handleTouchStart, false); | |
target.addEventListener('touchmove', handleTouchMove, false); | |
target.addEventListener('touchend', handleTouchEnd, false); | |
}catch(e){ | |
throw e; | |
} | |
} | |
function isScroll(){ | |
if(typeof _isScroll === 'undefined'){ | |
set_isScroll(); | |
} | |
return _isScroll; | |
} | |
function set_isScroll(){ | |
var delta = getDelta(start, move); | |
if(delta !== false){ | |
_isScroll = (delta.x < delta.y); | |
} | |
} | |
/* event delegates */ | |
function handleTouchStart(e){ | |
if(isSingleTouch(e)){ | |
// !important - disables native scrolling (fixes bug on android specifically) | |
e.preventDefault(); | |
start = { | |
'x':e.touches[0].pageX, | |
'y':e.touches[0].pageY | |
}; | |
dispatchStart(); | |
} | |
} | |
function handleTouchMove(e){ | |
// if touch is single touch (not pinch) and user is not attempting a vertical scroll | |
if(isSingleTouch(e) && !isScroll()){ | |
// !important - disables native scrolling (fixes bug on android specifically) | |
e.preventDefault(); | |
move = { | |
'x': e.touches[0].pageX, | |
'y': e.touches[0].pageY | |
}; | |
delta = getDelta(start, move); | |
dispatchDrag(); | |
} | |
} | |
function handleTouchEnd(e){ | |
e.preventDefault(); | |
direction = (move.x - start.x) > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT; | |
if(isPastTollerance(delta)){ | |
dispatchComplete(); | |
}else{ | |
dispatchFail(); | |
} | |
// once gesture has reset ended data. | |
_isScroll = undefined; | |
start = false; | |
move = false; | |
delta = false; | |
} | |
/* helpers */ | |
function getDelta(start, move){ | |
if(start === false || move === false) return false; | |
var x = Math.abs(start.x - move.x); | |
var y = Math.abs(start.y - move.y); | |
return {'x': x, 'y': y}; | |
} | |
function isSingleTouch(e){ | |
return e.touches.length === 1 || e.scale && e.scale === 1; | |
} | |
function isPastTollerance(delta){ | |
var result = false; | |
var dx = delta.x; | |
var width = target.getBoundingClientRect().width; | |
var threshold = 0.3; | |
if(dx > width*threshold){ | |
result = true; | |
} | |
return result; | |
} | |
/* event dispatcher helpers */ | |
function dispatchStart(){ | |
log('dispatchStart'); | |
dispatcher.dispatch( | |
SwipeEvent.START, | |
{ | |
'start': start | |
} | |
); | |
} | |
function dispatchDrag(){ | |
dispatcher.dispatch( | |
SwipeEvent.DRAG, | |
{ | |
'start': start, | |
'move' : move, | |
'delta': delta, | |
'isScroll' : _isScroll | |
} | |
); | |
} | |
function dispatchComplete(){ | |
log('dispatchComplete'); | |
dispatcher.dispatch( | |
SwipeEvent.COMPLETE, | |
{ | |
'start': start, | |
'move': move, | |
'delta': delta, | |
'direction': direction | |
} | |
); | |
} | |
function dispatchFail(){ | |
log('dispatchFail'); | |
dispatcher.dispatch( | |
SwipeEvent.FAIL, | |
{ | |
'start': start, | |
'move': move, | |
'delta': delta, | |
'direction': direction | |
} | |
); | |
} | |
// do not delete // | |
__new__(); | |
__init__(); | |
return self; | |
// #eo do not delete // | |
}; | |
/* #eo Swipe */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment