snappymail/vendors/jquery-finger/jquery.finger.js

148 lines
4.1 KiB
JavaScript
Raw Normal View History

/*! jquery.finger - v0.1.0-alpha - 2013-07-01
* https://github.com/ngryman/jquery.finger
* Copyright (c) 2013 Nicolas Gryman; Licensed MIT */
(function($) {
var hasTouch = 'ontouchstart' in window,
startEvent = hasTouch ? 'touchstart' : 'mousedown',
stopEvent = hasTouch ? 'touchend touchcancel' : 'mouseup mouseleave',
moveEvent = hasTouch ? 'touchmove' : 'mousemove',
namespace = 'finger',
safeguard,
Finger = $.Finger = {
pressDuration: 300,
doubleTapInterval: 300,
flickDuration: 150,
motionThreshold: 5
};
function page(coord, e) {
return (hasTouch ? e.originalEvent.touches[0] : e)['page' + coord.toUpperCase()];
}
function startHandler(event) {
var data = {},
timeStamp = event.timeStamp || +new Date(),
f = $.data(this, namespace);
if (safeguard == timeStamp) return;
safeguard = timeStamp;
data.move = { x: page('x', event), y: page('y', event) };
data.start = $.extend({ time: timeStamp, target: event.target }, data.move);
data.timeout = setTimeout($.proxy(function() {
$.event.trigger($.Event('press', data.move), null, event.target);
$.event.remove(this, moveEvent + '.' + namespace, moveHandler);
$.event.remove(this, stopEvent + '.' + namespace, stopHandler);
}, this), $.Finger.pressDuration);
$.event.add(this, moveEvent + '.' + namespace, moveHandler, data);
$.event.add(this, stopEvent + '.' + namespace, stopHandler, data);
if (Finger.preventDefault || f.options.preventDefault) event.preventDefault();
}
function moveHandler(event) {
var data = event.data,
start = data.start,
move = data.move;
// motion data
move.x = page('x', event);
move.y = page('y', event);
move.dx = move.x - start.x;
move.dy = move.y - start.y;
move.adx = Math.abs(move.dx);
move.ady = Math.abs(move.dy);
// security
data.motion = move.adx > Finger.motionThreshold || move.ady > Finger.motionThreshold;
if (!data.motion) return;
// moves cancel press events
clearTimeout(data.timeout);
// orientation
if (!move.orientation) {
if (move.adx > data.move.ady) {
move.orientation = 'horizontal';
move.direction = move.dx > 0 ? +1 : -1;
}
else {
move.orientation = 'vertical';
move.direction = move.dy > 0 ? +1 : -1;
}
}
// for delegated events, the target may change over time
// this ensures we notify the right target and simulates the mouseleave behavior
if (event.target !== start.target) {
event.target = start.target;
stopHandler.call(this, $.Event(stopEvent + '.' + namespace, event));
return;
}
// fire drag event
$.event.trigger($.Event('drag', move), null, event.target);
}
function stopHandler(event) {
var data = event.data,
timeStamp = event.timeStamp || +new Date(),
f = $.data(this, namespace),
dt = timeStamp - data.start.time,
evtName;
// always clears press timeout
clearTimeout(data.timeout);
// ensures start target and end target are the same
if (event.target !== data.start.target) return;
// tap-like events
if (!data.motion) {
evtName = dt < Finger.pressDuration &&
!f.prev || f.prev && timeStamp - f.prev > Finger.doubleTapInterval ? 'tap' : 'doubletap';
f.prev = timeStamp;
}
// motion events
else {
evtName = dt < Finger.flickDuration ? 'flick' : 'drag';
data.move.end = true;
}
$.event.trigger($.Event(evtName, data.move), null, event.target);
$.event.remove(this, moveEvent + '.' + namespace, moveHandler);
$.event.remove(this, stopEvent + '.' + namespace, stopHandler);
}
var fingerCustom = {
add: function(handleObj) {
if (!$.data(this, namespace)) {
$.event.add(this, startEvent + '.' + namespace, startHandler);
$.data(this, namespace, { options: handleObj.data || {} });
}
},
teardown: function() {
if ($.data(this, namespace)) {
$.event.remove(this, startEvent + '.' + namespace, startHandler);
$.data(this, namespace, null);
}
}
};
// registers custom events
$.event.special.tap = fingerCustom;
$.event.special.press = fingerCustom;
$.event.special.doubletap = fingerCustom;
$.event.special.drag = fingerCustom;
$.event.special.flick = fingerCustom;
})(jQuery);