Show:
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * @license MPL 2.0
  6. * @copyright Famous Industries, Inc. 2014
  7. */
  8.  
  9. /* Modified work copyright © 2015-2016 David Valdman */
  10.  
  11. //TODO: deprecate in favor of generic history stream
  12.  
  13. define(function(require, exports, module) {
  14. var OptionsManager = require('../core/OptionsManager');
  15. var EventHandler = require('../events/EventHandler');
  16.  
  17. var _now = Date.now;
  18.  
  19. /**
  20. * Catalogues a history of touch events. Useful for creating more complex
  21. * touch recognition for gestures. Currently only used by TouchInput to
  22. * track previous touches to compute velocity.
  23. *
  24. * TouchTracker emits these events with the following payload data:
  25. *
  26. * `x` - Displacement in x-direction
  27. * `y` - Displacement in y-direction
  28. * `identifier` - DOM event touch identifier
  29. * `timestamp` - Timestamp
  30. * `count` - DOM event for number of simultaneous touches
  31. * `history` - History of touches for the gesture
  32. *
  33. * @class TouchTracker
  34. * @constructor
  35. * @private
  36. * @uses Core.OptionsManager
  37. * @param [options] {Object} Options
  38. * @param [options.limit] {Number} Number of touches to record
  39. */
  40.  
  41. function TouchTracker(options) {
  42. this.options = OptionsManager.setOptions(this, options);
  43.  
  44. this.touchHistory = {};
  45. this._isTouched = false;
  46.  
  47. this._eventInput = new EventHandler();
  48. this._eventOutput = new EventHandler();
  49.  
  50. EventHandler.setInputHandler(this, this._eventInput);
  51. EventHandler.setOutputHandler(this, this._eventOutput);
  52.  
  53. this._eventInput.on('touchstart', _handleStart.bind(this));
  54. this._eventInput.on('touchmove', _handleMove.bind(this));
  55. this._eventInput.on('touchend', _handleEnd.bind(this));
  56. this._eventInput.on('touchcancel', _handleEnd.bind(this));
  57. }
  58.  
  59. TouchTracker.DEFAULT_OPTIONS = {
  60. limit : 1 // number of simultaneous touches
  61. };
  62.  
  63. /**
  64. * Record touch data, if selective is false.
  65. * @private
  66. * @method track
  67. * @param {Object} data touch data
  68. */
  69. TouchTracker.prototype.track = function track(data) {
  70. this.touchHistory[data.identifier] = [data];
  71. };
  72.  
  73. function _timestampTouch(touch, event, history) {
  74. return {
  75. x: touch.clientX,
  76. y: touch.clientY,
  77. identifier : touch.identifier,
  78. timestamp: _now(),
  79. count: event.touches.length,
  80. history: history
  81. };
  82. }
  83.  
  84. function _handleStart(event) {
  85. if (event.touches.length > this.options.limit) return;
  86. this._isTouched = true;
  87.  
  88. for (var i = 0; i < event.changedTouches.length; i++) {
  89. var touch = event.changedTouches[i];
  90. var data = _timestampTouch(touch, event, null);
  91. this._eventOutput.emit('trackstart', data);
  92. if (!this.touchHistory[touch.identifier]) this.track(data);
  93. }
  94. }
  95.  
  96. function _handleMove(event) {
  97. event.preventDefault(); // prevents scrolling on mobile
  98. for (var i = 0; i < event.changedTouches.length; i++) {
  99. var touch = event.changedTouches[i];
  100. var history = this.touchHistory[touch.identifier];
  101. if (history) {
  102. var data = _timestampTouch(touch, event, history);
  103. this.touchHistory[touch.identifier].push(data);
  104. this._eventOutput.emit('trackmove', data);
  105. }
  106. }
  107. }
  108.  
  109. function _handleEnd(event) {
  110. if (!this._isTouched) return;
  111.  
  112. for (var i = 0; i < event.changedTouches.length; i++) {
  113. var touch = event.changedTouches[i];
  114. var history = this.touchHistory[touch.identifier];
  115. if (history) {
  116. var data = _timestampTouch(touch, event, history);
  117. this._eventOutput.emit('trackend', data);
  118. delete this.touchHistory[touch.identifier];
  119. }
  120. }
  121.  
  122. this._isTouched = false;
  123. }
  124.  
  125. module.exports = TouchTracker;
  126. });
  127.