You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
11KB

  1. /*
  2. * TouchController.js
  3. * Keynote HTML Player
  4. *
  5. * Responsibility: Tungwei Cheng
  6. * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
  7. */
  8. // iPhone Event Name Constants:
  9. // -----------------------------
  10. var kTouchStartEventName = "touchstart";
  11. var kTouchMoveEventName = "touchmove";
  12. var kTouchEndEventName = "touchend";
  13. var kTouchCancelEventName = "touchcancel";
  14. var kGestureStartEventName = "gesturestart";
  15. var kGestureEndEventName = "gestureend";
  16. // Class: TouchController
  17. // ===============================================================
  18. var kSwipeEvent = "TouchController:SwipeEvent";
  19. var kTapEvent = "TouchController:TapeEvent";
  20. var TouchController = Class.create({
  21. initialize: function() {
  22. // observe touch events
  23. document.observe(kTouchStartEventName, this.handleTouchStartEvent.bind(this));
  24. document.observe(kTouchMoveEventName, this.handleTouchMoveEvent.bind(this));
  25. document.observe(kTouchEndEventName, this.handleTouchEndEvent.bind(this));
  26. document.observe(kTouchCancelEventName, this.handleTouchCancelEvent.bind(this));
  27. // observe gesture events
  28. document.observe(kGestureStartEventName, this.handleGestureStartEvent.bind(this));
  29. document.observe(kGestureEndEventName, this.handleGestureEndEvent.bind(this));
  30. this.swipeInProgress = false;
  31. this.swipeFingerCount = 0;
  32. this.swipeStartTime = 0;
  33. this.swipeStartX = 0;
  34. this.swipeStartY = 0;
  35. this.preventDefault = true;
  36. this.tapEventCallback = null;
  37. this.setTrackArea(0, 0, 0, 0);
  38. this.enableTouchTracking = true;
  39. },
  40. setTouchTrackingEnabled: function(isEnabled) {
  41. this.enableTouchTracking = isEnabled;
  42. },
  43. setTrackArea: function(left, top, width, height) {
  44. debugMessage(kDebugTouchController_SetTrackArea, "left: " + left + " top: " + top + " width: " + width + " height: " + height);
  45. this.trackAreaLeft = left;
  46. this.trackAreaTop = top;
  47. this.trackAreaRight = left + width;
  48. this.trackAreaBottom = top + height;
  49. },
  50. registerTapEventCallback: function(tapEventCallback) {
  51. this.tapEventCallback = tapEventCallback;
  52. },
  53. isTouchWithinTrackArea: function(touch) {
  54. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "checking...");
  55. if (this.enableTouchTracking === false) {
  56. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, tracking is disabled");
  57. return false;
  58. }
  59. if (touch.clientX < this.trackAreaLeft) {
  60. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, x < left");
  61. return false;
  62. }
  63. if (touch.clientX > this.trackAreaRight) {
  64. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, x > right");
  65. return false;
  66. }
  67. if (touch.clientY < this.trackAreaTop) {
  68. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, y < top");
  69. return false;
  70. }
  71. if (touch.clientY > this.trackAreaBottom) {
  72. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, y > bottom");
  73. return false;
  74. }
  75. debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- yes it is!");
  76. return true;
  77. },
  78. handleTouchStartEvent: function(event) {
  79. debugMessage(kDebugTouchController_HandleTouchStartEvent, "touch event has " + event.touches.length + " fingers...");
  80. if (this.swipeInProgress === false) {
  81. debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this is the first finger down event...");
  82. var startTouch = event.touches[0];
  83. if (this.isTouchWithinTrackArea(startTouch)) {
  84. debugMessage(kDebugTouchController_HandleTouchStartEvent, "- start tracking a swipt event...");
  85. if (this.preventDefault) {
  86. event.preventDefault();
  87. }
  88. this.swipeInProgress = true;
  89. this.swipeFingerCount = event.touches.length;
  90. this.swipeStartTime = new Date();
  91. this.swipeStartX = startTouch.clientX;
  92. this.swipeStartY = startTouch.clientY;
  93. } else {
  94. debugMessage(kDebugTouchController_HandleTouchStartEvent, "- but it is outside of the track area");
  95. }
  96. } else {
  97. debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this is a subsequent finger down event. update finger count...");
  98. if (event.touches.length > this.swipeFingerCount) {
  99. this.swipeFingerCount = event.touches.length;
  100. debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this.swipeFingerCount:" + this.swipeFingerCount);
  101. }
  102. }
  103. },
  104. handleTouchMoveEvent: function(event) {
  105. if (this.preventDefault) {
  106. event.preventDefault();
  107. }
  108. debugMessage(kDebugTouchController_HandleTouchCancelEvent, "");
  109. },
  110. handleTouchEndEvent: function(event) {
  111. debugMessage(kDebugTouchController_HandleTouchEndEvent, "touch event has " + event.touches.length + " fingers...");
  112. if (this.swipeInProgress) {
  113. if (this.preventDefault) {
  114. event.preventDefault();
  115. }
  116. if (event.touches.length === 0) {
  117. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- " + this.swipeFingerCount + " finger swipe is complete.");
  118. var endTouch = event.changedTouches[0];
  119. var viewport = document.viewport.getDimensions();
  120. var minSwipeDistance = viewport.width / 3.0;
  121. var maxVerticalMagnitude = viewport.height / 3.0;
  122. var maxHorizontalMagnitude = viewport.width / 3.0;
  123. var deltaX = endTouch.clientX - this.swipeStartX;
  124. var deltaY = endTouch.clientY - this.swipeStartY;
  125. var magnitudeX = Math.abs(deltaX);
  126. var magnitudeY = Math.abs(deltaY);
  127. var touchEndTime = new Date();
  128. var elapsedTime = touchEndTime - this.swipeStartTime;
  129. var tapIsGood = false;
  130. var swipeIsGood = false;
  131. // First Check for a "tap"
  132. var kMaxTapTime = 400;
  133. var kMaxTapMagnitude = 20;
  134. if (elapsedTime < kMaxTapTime) {
  135. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time was short enough to be a tap, check its magnitude...");
  136. if ((magnitudeX < kMaxTapMagnitude) && (magnitudeY < kMaxTapMagnitude)) {
  137. tapIsGood = true;
  138. } else {
  139. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- magnitude time too big to be a tap, check if it's a swipe...");
  140. }
  141. } else {
  142. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time too long to be a tap, check if it's a swipe...");
  143. }
  144. if (elapsedTime > 800) {
  145. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time too long to be a swipe, ignoring...");
  146. } else {
  147. if (magnitudeX > magnitudeY) {
  148. if (magnitudeY > maxVerticalMagnitude) {
  149. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- vertical magnitude too high, ignoring...");
  150. } else {
  151. swipeIsGood = true;
  152. }
  153. } else {
  154. if (magnitudeX > maxHorizontalMagnitude) {
  155. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- horizontal magnitude too high, ignoring...");
  156. } else {
  157. swipeIsGood = true;
  158. }
  159. }
  160. }
  161. if (tapIsGood) {
  162. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- it's a " + this.swipeFingerCount + " finger tap");
  163. if (this.tapEventCallback) {
  164. var tapEvent = {};
  165. tapEvent.memo = {};
  166. tapEvent.memo.fingers = this.swipeFingerCount;
  167. tapEvent.memo.pointX = endTouch.clientX;
  168. tapEvent.memo.pointY = endTouch.clientY;
  169. tapEvent.memo.target = event.target;
  170. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- invoking callback with pointX: " + endTouch.clientX + " pointY: " + endTouch.clientY + "...");
  171. this.tapEventCallback(tapEvent);
  172. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- back from callback");
  173. } else {
  174. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- firing TapEvent...");
  175. document.fire(kTapEvent, {
  176. fingers: this.swipeFingerCount,
  177. pointX: endTouch.clientX,
  178. pointY: endTouch.clientY
  179. });
  180. }
  181. } else if (swipeIsGood) {
  182. var direction;
  183. if (magnitudeX > magnitudeY) {
  184. direction = (deltaX < 0 ? "left" : "right");
  185. } else {
  186. direction = (deltaY < 0 ? "up" : "down");
  187. }
  188. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- it's a " + this.swipeFingerCount + " finger swipe in the " + direction + " direction");
  189. document.fire(kSwipeEvent, {
  190. direction: direction,
  191. fingers: this.swipeFingerCount,
  192. swipeStartX: this.swipeStartX
  193. });
  194. }
  195. this.swipeInProgress = false;
  196. this.swipeFingerCount = 0;
  197. }
  198. } else {
  199. debugMessage(kDebugTouchController_HandleTouchEndEvent, "- false alarm. swipe has already ended.");
  200. }
  201. },
  202. handleTouchCancelEvent: function(event) {
  203. debugMessage(kDebugTouchController_HandleTouchCancelEvent, "");
  204. this.swipeInProgress = false;
  205. },
  206. handleGestureStartEvent: function(event) {
  207. debugMessage(kDebugTouchController_HandleGestureStartEvent, "");
  208. if (this.preventDefault) {
  209. event.preventDefault();
  210. }
  211. },
  212. handleGestureEndEvent: function(event) {
  213. debugMessage(kDebugTouchController_HandleGestureEndEvent, "");
  214. if (this.preventDefault) {
  215. event.preventDefault();
  216. }
  217. }
  218. });