This repository has been archived on 2018-10-12. You can view files and clone it, but cannot push or open issues or pull requests.
node-task/public/js/ink.swipe.js

209 lines
7.9 KiB
JavaScript

/**
* Swipe gestures
* @module Ink.UI.Swipe_1
* @version 1
*/
Ink.createModule('Ink.UI.Swipe', '1', ['Ink.Dom.Event_1', 'Ink.Dom.Element_1', 'Ink.UI.Common_1'], function(InkEvent, InkElement, Common) {
'use strict';
/**
* Subscribe swipe gestures.
*
* Supports filtering swipes be any combination of the criteria supported in the options.
*
* -----
*
* Arguments received by the callbacks
* -----------------------------------
*
* The `onStart`, `onMove`, and `onEnd` options receive as argument an object containing:
*
* - `event`: the DOMEvent object
* - `element`: the target element
* - `Instance`: the `Ink.UI.Swipe_1` instance
* - `position`: `Array` with `[x, y]` coordinates of current position
* - `dt`: Time passed between now and the first event (onMove only)
* - `gesture`: an Array containing [x,y] coordinates of every touchmove event received (only if options.storeGesture is enabled) (onEnd only)
* - `time`: an Array containing all the `dt` values for every touchmove event (onEnd only)
* - `overallMovement`: X and Y distance traveled by the touch movement (`[x, y]`) (onEnd only)
* - `overallTime`: total time passed (onEnd only)
*
* @class Ink.UI.Swipe
* @constructor
* @param {String|DOMElement} el Element or Selector
* @param {Object} options Options Object
* @param {Function} [options.onEnd] Callback function for the `touchend` event. Gets all the gesture information, and is filtered by min/max Dist and Duration options (see below)
* @param {Function} [options.onStart] Callback function for `touchstart` event.
* @param {Function} [options.onMove] Callback function for every `touchmove` event. Gets current gesture information.
* @param {Number} [options.minDist] Minimum allowed distance, in pixels.
* @param {Number} [options.maxDist] Maximum allowed distance, in pixels.
* @param {Number} [options.minDuration] Minimum allowed duration, in seconds.
* @param {Number} [options.maxDuration] Maximum allowed duration, in seconds.
* @param {String} [options.axis] If either 'x' or 'y' is passed, only swipes where the dominant axis is the given one trigger the callback
* @param {String} [options.storeGesture] If to store gesture information and provide it to the callback. Defaults to true.
* @param {String} [options.stopEvents] Flag to stop (default and propagation) of the received events. Defaults to true.
*
*
* @sample Ink_UI_Swipe_1.html
*/
function Swipe() {
if (typeof arguments[1] === 'function') {
arguments[1] = { onEnd: arguments[1] };
}
Common.BaseUIComponent.apply(this, arguments);
}
Swipe._name = 'Swipe_1';
Swipe._optionDefinition = {
onEnd: ['Function', undefined],
onStart: ['Function', undefined],
onMove: ['Function', undefined],
minDist: ['Number', undefined], // in pixels
maxDist: ['Number', undefined],
minDuration: ['Number', undefined], // in seconds
maxDuration: ['Number', undefined],
axis: ['String', undefined], // x | y
storeGesture: ['Boolean', false],
stopEvents: ['Boolean', true]
};
Swipe.prototype = {
_supported: ('ontouchstart' in document.documentElement),
_init: function() {
this._handlers = {
down: Ink.bindEvent(this._onDown, this),
move: Ink.bindEvent(this._onMove, this),
up: Ink.bindEvent(this._onUp, this)
};
var db = document.body;
InkEvent.observe(db, 'touchstart', this._handlers.down);
if (this._options.storeGesture || this._options.onMove) {
InkEvent.observe(db, 'touchmove', this._handlers.move);
}
InkEvent.observe(db, 'touchend', this._handlers.up);
this._isOn = false;
},
_isMeOrParent: function(el, parentEl) {
if (!el) {return;}
do {
if (el === parentEl) { return true; }
el = el.parentNode;
} while (el);
return false;
},
_pushGesture: function (coords, dt) {
if (this._options.storeGesture) {
this._gesture.push(coords);
this._time.push(dt);
}
},
_onDown: function(event) {
if (event.changedTouches.length !== 1) { return; }
if (!this._isMeOrParent(event.target, this._element)) { return; }
if( this._options.stopEvents === true ){
InkEvent.stop(event);
}
event = event.changedTouches[0];
this._isOn = true;
this._target = event.target;
this._t0 = +new Date();
this._p0 = [event.pageX, event.pageY];
if (this._options.storeGesture) {
this._gesture = [];
this._time = [];
}
this._pushGesture(this._p0, 0);
if (this._options.onStart) {
this._options.onStart({
event: event,
element: this._element,
instance: this,
position: this._p0,
dt: 0
});
}
},
_onMove: function(event) {
if (!this._isOn || event.changedTouches.length !== 1) { return; }
if( this._options.stopEvents === true ) {
InkEvent.stop(event);
}
event = event.changedTouches[0];
var t1 = +new Date();
var dt = (t1 - this._t0);
var gesture = [event.pageX, event.pageY];
this._pushGesture(gesture, dt);
if (this._options.onMove) {
this._options.onMove({
event: event,
element: this._element,
instance: this,
position: gesture,
dt: dt
});
}
},
_onUp: function(event) {
if (!this._isOn || event.changedTouches.length !== 1) { return; }
if( this._options.stopEvents === true ){
InkEvent.stop(event);
}
event = event.changedTouches[0]; // TODO SHOULD CHECK IT IS THE SAME TOUCH
this._isOn = false;
var t1 = +new Date();
var p1 = [event.pageX, event.pageY];
var dt = (t1 - this._t0);
var dr = [
p1[0] - this._p0[0],
p1[1] - this._p0[1]
];
var dist = Math.sqrt(dr[0]*dr[0] + dr[1]*dr[1]);
var axis = Math.abs(dr[0]) > Math.abs(dr[1]) ? 'x' : 'y';
var o = this._options;
if (o.minDist && dist < o.minDist) { return; }
if (o.maxDist && dist > o.maxDist) { return; }
if (o.minDuration && dt < o.minDuration) { return; }
if (o.maxDuration && dt > o.maxDuration) { return; }
if (o.axis && axis !== o.axis) { return; }
if (this._options.onEnd) {
this._options.onEnd({
event: event,
element: this._element,
instance: this,
gesture: this._gesture,
time: this._time,
axis: axis,
overallMovement: dr,
overallTime: dt
});
}
}
};
Common.createUIComponent(Swipe);
return Swipe;
});