|
/*! |
|
* addTap v1.0.00 - helper function for adding click-ish events for touch devices |
|
* by David DeSandro |
|
* https://gist.github.com/1901569 |
|
*/ |
|
|
|
/*jshint undef: true, forin: false, browser: true */ |
|
|
|
(function( window, undefined ){ |
|
|
|
var isTouch = 'ontouchstart' in window; |
|
var cursorStartEvent = isTouch ? 'touchstart' : 'mousedown'; |
|
var cursorMoveEvent = isTouch ? 'touchmove' : 'mousemove'; |
|
var cursorEndEvent = isTouch ? 'touchend' : 'mouseup'; |
|
|
|
// -------------------------- addTap -------------------------- // |
|
|
|
function addTap( elem, onTap, options ) { |
|
|
|
var handler = new addTap.Handler( onTap, options ); |
|
|
|
elem.addEventListener( cursorStartEvent, handler, false ); |
|
|
|
} |
|
|
|
// -------------------------- TapHandler -------------------------- // |
|
|
|
addTap.Handler = function( onTap, options ) { |
|
// bail out if onTap callback is not set |
|
if ( !onTap ) { |
|
return; |
|
} |
|
|
|
// set onTap callback |
|
this.onTap = onTap; |
|
|
|
// set options |
|
this.options = {}; |
|
// set defaults |
|
for ( var prop in addTap.Handler.defaults ) { |
|
this.options[ prop ] = addTap.Handler.defaults[ prop ]; |
|
} |
|
// overwrite with passed-in options |
|
for ( prop in options ) { |
|
this.options[ prop ] = options[ prop ]; |
|
} |
|
|
|
}; |
|
|
|
addTap.Handler.defaults = { |
|
moveableBuffer: 3 |
|
}; |
|
|
|
addTap.Handler.prototype = { |
|
|
|
handleEvent: function( event ) { |
|
if ( this[ event.type ] ) { |
|
this[ event.type ]( event ); |
|
} |
|
}, |
|
|
|
// ----- start ----- // |
|
|
|
mousedown: function( event ) { |
|
this.cursorStart( event ); |
|
}, |
|
|
|
touchstart: function( event ) { |
|
// bail out if we already have a touch |
|
if ( this.touch ) { |
|
return; |
|
} |
|
// get first changedTouch |
|
this.touch = event.changedTouches[0]; |
|
this.cursorStart( this.touch ); |
|
}, |
|
|
|
cursorStart: function( cursor ) { |
|
// set start point |
|
this.startPoint = { |
|
x: cursor.pageX, |
|
y: cursor.pageY |
|
}; |
|
|
|
// listen for move and end events |
|
window.addEventListener( cursorMoveEvent, this, false ); |
|
window.addEventListener( cursorEndEvent, this, false ); |
|
}, |
|
|
|
// ----- move ----- // |
|
|
|
mousemove: function( event ) { |
|
this.cursorMove( event ); |
|
}, |
|
|
|
touchmove: function( event ) { |
|
var matchedTouch = this.getMatchedTouch( event ); |
|
if ( matchedTouch ) { |
|
this.cursorMove( matchedTouch ); |
|
} |
|
}, |
|
|
|
getMatchedTouch: function( event ) { |
|
var touch, matchedTouch; |
|
// iterate through touches |
|
for ( var i=0, len = event.changedTouches.length; i < len; i++ ) { |
|
touch = event.changedTouches[i]; |
|
// get matched touch |
|
if ( touch.identifier === this.touch.identifier ) { |
|
matchedTouch = touch; |
|
break; |
|
} |
|
} |
|
return matchedTouch; |
|
}, |
|
|
|
cursorMove: function( cursor ) { |
|
var moveX = cursor.pageX - this.startPoint.x; |
|
var moveY = cursor.pageY - this.startPoint.y; |
|
|
|
// check if touch has moved outside buffer zone |
|
if ( Math.abs( moveX ) > this.options.moveableBuffer || |
|
Math.abs( moveY ) > this.options.moveableBuffer |
|
) { |
|
// if outside, then remove listeners, so onTap won't be triggered |
|
this.reset(); |
|
} |
|
|
|
}, |
|
|
|
// ----- end ----- // |
|
|
|
mouseup: function( event ) { |
|
this.cursorEnd( event, event ); |
|
}, |
|
|
|
touchend: function( event ) { |
|
var matchedTouch = this.getMatchedTouch( event ); |
|
if ( matchedTouch ) { |
|
this.cursorEnd( event, matchedTouch ); |
|
} |
|
}, |
|
|
|
cursorEnd: function( event, cursor ) { |
|
// trigger onTap callback |
|
this.onTap( event, cursor ); |
|
this.reset(); |
|
}, |
|
|
|
reset: function() { |
|
window.removeEventListener( cursorMoveEvent, this, false ); |
|
window.removeEventListener( cursorEndEvent, this, false ); |
|
delete this.touch; |
|
} |
|
|
|
}; |
|
|
|
// publicize |
|
window.addTap = addTap; |
|
|
|
})( window ); |