/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* @license MPL 2.0
* @copyright Famous Industries, Inc. 2014
*/
/* Modified work copyright © 2015-2016 David Valdman */
//TODO: deprecate in favor of generic history stream
define(function(require, exports, module) {
var OptionsManager = require('../core/OptionsManager');
var EventHandler = require('../events/EventHandler');
var _now = Date.now;
/**
* Catalogues a history of touch events. Useful for creating more complex
* touch recognition for gestures. Currently only used by TouchInput to
* track previous touches to compute velocity.
*
* TouchTracker emits these events with the following payload data:
*
* `x` - Displacement in x-direction
* `y` - Displacement in y-direction
* `identifier` - DOM event touch identifier
* `timestamp` - Timestamp
* `count` - DOM event for number of simultaneous touches
* `history` - History of touches for the gesture
*
* @class TouchTracker
* @constructor
* @private
* @uses Core.OptionsManager
* @param [options] {Object} Options
* @param [options.limit] {Number} Number of touches to record
*/
function TouchTracker(options) {
this.options = OptionsManager.setOptions(this, options);
this.touchHistory = {};
this._isTouched = false;
this._eventInput = new EventHandler();
this._eventOutput = new EventHandler();
EventHandler.setInputHandler(this, this._eventInput);
EventHandler.setOutputHandler(this, this._eventOutput);
this._eventInput.on('touchstart', _handleStart.bind(this));
this._eventInput.on('touchmove', _handleMove.bind(this));
this._eventInput.on('touchend', _handleEnd.bind(this));
this._eventInput.on('touchcancel', _handleEnd.bind(this));
}
TouchTracker.DEFAULT_OPTIONS = {
limit : 1 // number of simultaneous touches
};
/**
* Record touch data, if selective is false.
* @private
* @method track
* @param {Object} data touch data
*/
TouchTracker.prototype.track = function track(data) {
this.touchHistory[data.identifier] = [data];
};
function _timestampTouch(touch, event, history) {
return {
x: touch.clientX,
y: touch.clientY,
identifier : touch.identifier,
timestamp: _now(),
count: event.touches.length,
history: history
};
}
function _handleStart(event) {
if (event.touches.length > this.options.limit) return;
this._isTouched = true;
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var data = _timestampTouch(touch, event, null);
this._eventOutput.emit('trackstart', data);
if (!this.touchHistory[touch.identifier]) this.track(data);
}
}
function _handleMove(event) {
event.preventDefault(); // prevents scrolling on mobile
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var history = this.touchHistory[touch.identifier];
if (history) {
var data = _timestampTouch(touch, event, history);
this.touchHistory[touch.identifier].push(data);
this._eventOutput.emit('trackmove', data);
}
}
}
function _handleEnd(event) {
if (!this._isTouched) return;
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches[i];
var history = this.touchHistory[touch.identifier];
if (history) {
var data = _timestampTouch(touch, event, history);
this._eventOutput.emit('trackend', data);
delete this.touchHistory[touch.identifier];
}
}
this._isTouched = false;
}
module.exports = TouchTracker;
});