Skip to content

Commit 21c49da

Browse files
author
Sebastien Pereira
committed
refactor TouchTracker
1 parent 0780165 commit 21c49da

File tree

2 files changed

+169
-133
lines changed

2 files changed

+169
-133
lines changed

handlers/touch.js

Lines changed: 55 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
* todo: pointerenter/pointerleave: generate on capture when target is the originated element.
66
*/
77
define([
8+
"./touchTracker",
89
"./utils"
9-
], function (utils) {
10+
], function (tracker, utils) {
1011
"use strict";
1112

1213
var TouchEvents = {
@@ -42,16 +43,16 @@ define([
4243
// handled by the user agent. The current event is related to a new pointer which contributes to a
4344
// multi touch gesture: we must absorb this event and cancel the primary pointer to let the user agent
4445
// handle the default action.
45-
if (TouchTracker.hasPrimary() && (touchAction === utils.TouchAction.AUTO)) {
46+
if (tracker.hasPrimary() && (touchAction === utils.TouchAction.AUTO)) {
4647
// fire pointerout > pointercancel for current primary pointer
47-
var lastNativeEvent = TouchTracker.getPrimaryTouchEvent();
48-
var lastTouch = TouchTracker.getPrimaryTouch();
49-
touchTarget = TouchTracker.identifyPrimaryTouchTarget(lastTouch.target);
48+
var lastNativeEvent = tracker.getPrimaryTouchEvent();
49+
var lastTouch = tracker.getPrimaryTouch();
50+
touchTarget = tracker.identifyPrimaryTouchTarget(lastTouch.target);
5051
utils.dispatchEvent(touchTarget, createPointer(utils.events.OUT, lastNativeEvent, lastTouch, {}));
5152
utils.dispatchEvent(touchTarget, createPointer(utils.events.CANCEL, lastNativeEvent, lastTouch, {}));
52-
TouchTracker.implicitReleaseCapture(lastTouch.identifier);
53+
releaseCapture(lastTouch.identifier); //implicit release
5354
// cancel the primary pointer to avoid duplicate generation of PointerOut > PointerCancel
54-
TouchTracker.unregister(lastTouch.identifier);
55+
tracker.unregister(lastTouch.identifier);
5556
} else {
5657
if (touchAction !== utils.TouchAction.AUTO) {
5758
if (DoubleTap.isEligible(touch.target)) {
@@ -62,8 +63,8 @@ define([
6263
// to set a pointer capture on the element, so we must:
6364
// - register the pointer *before* firing the events.
6465
// - update the tracker *before* firing the events.
65-
TouchTracker.register(touch.identifier, touchAction);
66-
TouchTracker.update(touch, e, touch.target);
66+
tracker.register(touch.identifier, touchAction);
67+
tracker.update(touch, e, touch.target);
6768
// fire pointerover > pointerdown
6869
utils.dispatchEvent(touch.target, createPointer(utils.events.OVER, e, touch, {}));
6970
utils.dispatchEvent(touch.target, createPointer(utils.events.DOWN, e, touch, {}));
@@ -80,12 +81,12 @@ define([
8081
var touch;
8182
for (var l = e.changedTouches.length, i = 0; i < l; i++) {
8283
touch = e.changedTouches.item(i);
83-
if (!TouchTracker.isActive(touch.identifier)) {
84+
if (!tracker.isActive(touch.identifier)) {
8485
return;
8586
}
8687
// browser default actions
87-
if (TouchTracker.getTouchAction(touch.identifier) === utils.TouchAction.AUTO) {
88-
var lastNativeEventType = TouchTracker.getTouchEvent(touch.identifier).type;
88+
if (tracker.getTouchAction(touch.identifier) === utils.TouchAction.AUTO) {
89+
var lastNativeEventType = tracker.getTouchEvent(touch.identifier).type;
8990
switch (lastNativeEventType) {
9091
case TouchEvents.touchstart:
9192
// (1) fire PointerOut > PointerCancel
@@ -99,11 +100,11 @@ define([
99100
// events flow already ended (previous touchmove already removed pointer from tracker to
100101
// prevent PointerEvent to be fired)
101102
}
102-
TouchTracker.implicitReleaseCapture(touch.identifier);
103-
TouchTracker.unregister(touch.identifier);
103+
releaseCapture(touch.identifier); //implicit release
104+
tracker.unregister(touch.identifier);
104105
} else { // always map PointerMove when touch action is set (none/pan-x/pan-y)
105-
var touchTarget = TouchTracker.identifyTouchTarget(touch.identifier, elementFromTouch(touch));
106-
var lastElementFromPoint = TouchTracker.getTargetElement(touch.identifier);
106+
var touchTarget = tracker.identifyTouchTarget(touch.identifier, elementFromTouch(touch));
107+
var lastElementFromPoint = tracker.getTargetElement(touch.identifier);
107108
// check if the pointer is moving out from the current target element
108109
if (touchTarget !== lastElementFromPoint) {
109110
// expected sequence of events:
@@ -125,7 +126,7 @@ define([
125126
} else {
126127
utils.dispatchEvent(touchTarget, createPointer(utils.events.MOVE, e, touch, {}));
127128
}
128-
TouchTracker.update(touch, e, touchTarget);
129+
tracker.update(touch, e, touchTarget);
129130
// default actions must be prevented
130131
e.preventDefault();
131132
}
@@ -141,15 +142,15 @@ define([
141142
var touch;
142143
for (var l = e.changedTouches.length, i = 0; i < l; i++) {
143144
touch = e.changedTouches.item(i);
144-
if (!TouchTracker.isActive(touch.identifier)) {
145+
if (!tracker.isActive(touch.identifier)) {
145146
return;
146147
}
147-
var lastNativeEventType = TouchTracker.getTouchEvent(touch.identifier).type;
148+
var lastNativeEventType = tracker.getTouchEvent(touch.identifier).type;
148149
// elementFromPoint may return null on android when user makes a pinch 2 zoom gesture
149150
// in that case we use the current touch.target.
150151
var elementFromPoint = elementFromTouch(touch) || touch.target;
151-
var touchTarget = TouchTracker.identifyTouchTarget(touch.identifier, elementFromPoint);
152-
if (TouchTracker.getTouchAction(touch.identifier) === utils.TouchAction.AUTO) {
152+
var touchTarget = tracker.identifyTouchTarget(touch.identifier, elementFromPoint);
153+
if (tracker.getTouchAction(touch.identifier) === utils.TouchAction.AUTO) {
153154
// default action handled by user agent
154155
switch (lastNativeEventType) {
155156
case TouchEvents.touchmove:
@@ -189,8 +190,8 @@ define([
189190
// "touchend event with touch action!=auto and lastNativeEventType=[" + lastNativeEventType + "]"
190191
}
191192
}
192-
TouchTracker.implicitReleaseCapture(touch.identifier);
193-
TouchTracker.unregister(touch.identifier);
193+
releaseCapture(touch.identifier); // implicit release
194+
tracker.unregister(touch.identifier);
194195
}
195196
}
196197

@@ -203,13 +204,13 @@ define([
203204
var touch;
204205
for (var l = e.changedTouches.length, i = 0; i < l; i++) {
205206
touch = e.changedTouches.item(i);
206-
if (!TouchTracker.isActive(touch.identifier)) {
207+
if (!tracker.isActive(touch.identifier)) {
207208
return;
208209
}
209-
utils.dispatchEvent(TouchTracker.identifyTouchTarget(touch.identifier, elementFromTouch(touch)),
210+
utils.dispatchEvent(tracker.identifyTouchTarget(touch.identifier, elementFromTouch(touch)),
210211
createPointer(utils.events.CANCEL, e, touch, {}));
211-
TouchTracker.implicitReleaseCapture(touch.identifier);
212-
TouchTracker.unregister(touch.identifier);
212+
releaseCapture(touch.identifier); // implicit release
213+
tracker.unregister(touch.identifier);
213214
}
214215
}
215216

@@ -235,7 +236,7 @@ define([
235236
props.metaKey = touchEvent.metaKey;
236237
props.pageX = touch.pageX;
237238
props.pageY = touch.pageY;
238-
if (TouchTracker.hasCapture(touch.identifier)) { // W3C spec §10.1
239+
if (tracker.hasCapture(touch.identifier)) { // W3C spec §10.1
239240
props.relatedTarget = null;
240241
}
241242
// normalize button/buttons values
@@ -246,7 +247,7 @@ define([
246247
// Pointer Events properties
247248
props.pointerId = touch.identifier + 2; // avoid id collision: 1 is reserved for mouse events mapping
248249
props.pointerType = "touch";
249-
props.isPrimary = TouchTracker.isPrimary(touch.identifier);
250+
props.isPrimary = tracker.isPrimary(touch.identifier);
250251
return new utils.Pointer(pointerType, touchEvent, props);
251252
}
252253

@@ -259,7 +260,7 @@ define([
259260
function fireSyntheticClick(target, touch) {
260261
// IE10 always generates a click for every pointer when there is multiple touches
261262
// todo: investigate how IE11 handles clicks when there is multiple touches
262-
if (TouchTracker.isPrimary(touch.identifier)) {
263+
if (tracker.isPrimary(touch.identifier)) {
263264
// here we choose to fire click/dblclick only for primary pointer
264265
utils.dispatchEvent(target, utils.createSyntheticClick(touch));
265266
// dispatch double tap if eligible
@@ -285,109 +286,20 @@ define([
285286
return touch.target.ownerDocument.elementFromPoint(touch.clientX, touch.clientY);
286287
}
287288

288-
// todo:refactor + document TouchTracker/TouchInfo
289-
/* function TouchInfo(touchId, touchAction) {
290-
this.touchId = touchId;
291-
this.touchAction = 0;
292-
this.lastNativeEvent = null;
293-
this.lastTargetElement = null;
294-
this.captureTarget = null;
295-
}*/
296-
var TouchTracker = {
297-
// touchId of the primary pointer, or -1 if no primary pointer set.
298-
primaryTouchId: -1,
299-
register: function (touchId, touchAction) {
300-
// the first touch to register becomes the primary pointer
301-
if (this.primaryTouchId === -1) {
302-
this.primaryTouchId = touchId;
303-
}
304-
this[touchId] = {};
305-
this[touchId]._touchAction = touchAction;
306-
},
307-
update: function (touch, touchEvent, targetElement) {
308-
this[touch.identifier]._lastTouch = touch;
309-
this[touch.identifier]._lastNativeEvent = touchEvent;
310-
this[touch.identifier]._lastTargetElement = targetElement;
311-
},
312-
getTouchAction: function (touchId) {
313-
return this[touchId]._touchAction;
314-
},
315-
getTouch: function (touchId) {
316-
return this[touchId]._lastTouch;
317-
},
318-
getTouchEvent: function (touchId) {
319-
return this[touchId]._lastNativeEvent;
320-
},
321-
getTargetElement: function (touchId) {
322-
return this[touchId]._lastTargetElement;
323-
},
324-
unregister: function (touchId) {
325-
if (this.primaryTouchId === touchId) {
326-
this.primaryTouchId = -1;
327-
}
328-
return (delete this[touchId]);
329-
},
330-
isActive: function (touchId) {
331-
return (touchId in this);
332-
},
333-
// touch target depends whether capture has been set on the pointer
334-
identifyTouchTarget: function (touchId, nonCapturedElement) {
335-
return (this[touchId] && this[touchId]._captureTarget) || nonCapturedElement;
336-
},
337-
hasPrimary: function () {
338-
return (this.primaryTouchId !== -1);
339-
},
340-
isPrimary: function (touchId) {
341-
return (this.primaryTouchId === touchId);
342-
},
343-
getPrimaryTouchEvent: function () {
344-
return this[this.primaryTouchId]._lastNativeEvent;
345-
},
346-
getPrimaryTouch: function () {
347-
return this[this.primaryTouchId]._lastTouch;
348-
},
349-
identifyPrimaryTouchTarget: function (nonCapturedElement) {
350-
return this.identifyTouchTarget(this.primaryTouchId, nonCapturedElement);
351-
},
352-
setCapture: function (touchId, targetElement) {
353-
// 1. check if pointer is active, otw throw DOMException with the name InvalidPointerId.
354-
if (!this.isActive(touchId)) {
355-
throw "InvalidPointerId";
356-
}
357-
// 2. pointer must have active buttons, otherwise return
358-
// 3. register capture on this element.
359-
this[touchId]._captureTarget = targetElement;
360-
// 4. Fire a gotpointercapture event at the targetElement
361-
utils.dispatchEvent(this.getTouch(touchId).target,
362-
createPointer(utils.events.GOTCAPTURE, this.getTouchEvent(touchId), this.getTouch(touchId), {}));
363-
return true;
364-
},
365-
hasCapture: function (touchId) {
366-
return !!(this[touchId]._captureTarget);
367-
},
368-
releaseCapture: function (touchId, targetElement, implicit) {
369-
// 1. check if pointerId is active, otw throw DOMException with the name InvalidPointerId.
370-
if (!this.isActive(touchId)) {
371-
throw "InvalidPointerId";
372-
}
373-
// 2. if pointer capture not set at targetElement, return
374-
if (!implicit && (this[touchId]._captureTarget !== targetElement)) {
375-
return false;
376-
}
377-
// 3. release capture
378-
if (this[touchId]._captureTarget) {
379-
this[touchId]._captureTarget = null;
380-
// 4. Fire a lostpointercapture event at the targetElement
381-
utils.dispatchEvent(TouchTracker.getTouch(touchId).target,
382-
createPointer(utils.events.LOSTCAPTURE, TouchTracker.getTouchEvent(touchId),
383-
TouchTracker.getTouch(touchId), {}));
384-
}
289+
function releaseCapture(touchId, targetElement) {
290+
if (tracker.releaseCapture(touchId, targetElement)) {
291+
// 4. Fire a lostpointercapture event at the targetElement
292+
utils.dispatchEvent(
293+
tracker.getLastTouch(touchId).target,
294+
createPointer(utils.events.LOSTCAPTURE,
295+
tracker.getTouchEvent(touchId),
296+
tracker.getLastTouch(touchId), {}
297+
)
298+
);
385299
return true;
386-
},
387-
implicitReleaseCapture: function (touchId) {
388-
return this.releaseCapture(touchId, null, true);
389300
}
390-
};
301+
return false;
302+
}
391303

392304
return {
393305
/**
@@ -422,7 +334,17 @@ define([
422334
* @param pointerId Id of the capturing Pointer
423335
*/
424336
setPointerCapture: function (targetElement, pointerId) {
425-
return TouchTracker.setCapture(pointerId - 2, targetElement);
337+
var touchId = pointerId - 2;
338+
tracker.setCapture(touchId, targetElement);
339+
// 4. Fire a gotpointercapture event at the targetElement
340+
utils.dispatchEvent(
341+
tracker.getLastTouch(touchId).target,
342+
createPointer(utils.events.GOTCAPTURE,
343+
tracker.getTouchEvent(touchId),
344+
tracker.getLastTouch(touchId), {}
345+
)
346+
);
347+
return true;
426348
},
427349

428350
/**
@@ -432,7 +354,7 @@ define([
432354
* @param pointerId Id of the capturing Pointer
433355
*/
434356
releasePointerCapture: function (targetElement, pointerId) {
435-
return TouchTracker.releaseCapture(pointerId - 2, targetElement, false);
357+
return releaseCapture(pointerId - 2, targetElement);
436358
}
437359
};
438360
});

0 commit comments

Comments
 (0)