Skip to content

Commit d3e5e23

Browse files
committed
fix(delay_distance): cleanup and evaluate pre-drag conditions without flags for TouchSensor
1 parent 492d22d commit d3e5e23

File tree

2 files changed

+249
-129
lines changed

2 files changed

+249
-129
lines changed

src/Draggable/Sensors/TouchSensor/TouchSensor.js

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {closest, distance} from 'shared/utils';
1+
import {closest, distance as euclideanDistance, touchCoords} from 'shared/utils';
22
import Sensor from '../Sensor';
33
import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent} from '../SensorEvent';
44

@@ -52,7 +52,7 @@ export default class TouchSensor extends Sensor {
5252
this.currentScrollableParent = null;
5353

5454
/**
55-
* TimeoutID for long touch
55+
* TimeoutID for managing delay
5656
* @property tapTimeout
5757
* @type {Number}
5858
*/
@@ -97,27 +97,26 @@ export default class TouchSensor extends Sensor {
9797
if (!container) {
9898
return;
9999
}
100+
const {distance = 0, delay = 0} = this.options;
101+
const {pageX, pageY} = touchCoords(event);
100102

103+
Object.assign(this, {pageX, pageY});
104+
this.onTouchStartAt = Date.now();
101105
this.startEvent = event;
106+
this.currentContainer = container;
102107

103-
document.addEventListener('touchmove', this[onTouchMove]);
104108
document.addEventListener('touchend', this[onTouchEnd]);
105109
document.addEventListener('touchcancel', this[onTouchEnd]);
106110
document.addEventListener('touchmove', this[onDistanceChange]);
107111
container.addEventListener('contextmenu', onContextMenu);
108112

109-
if (this.options.distance) {
113+
if (distance) {
110114
preventScrolling = true;
111115
}
112116

113-
this.currentContainer = container;
114-
this.tapTimeout = setTimeout(() => {
115-
this.delayOver = true;
116-
if (this.touchMoved || this.distance < this.options.distance) {
117-
return;
118-
}
119-
this[startDrag]();
120-
}, this.options.delay);
117+
this.tapTimeout = window.setTimeout(() => {
118+
this[onDistanceChange]({touches: [{pageX: this.pageX, pageY: this.pageY}]});
119+
}, delay);
121120
}
122121

123122
/**
@@ -127,7 +126,7 @@ export default class TouchSensor extends Sensor {
127126
[startDrag]() {
128127
const startEvent = this.startEvent;
129128
const container = this.currentContainer;
130-
const touch = startEvent.touches[0] || startEvent.changedTouches[0];
129+
const touch = touchCoords(startEvent);
131130

132131
const dragStartEvent = new DragStartSensorEvent({
133132
clientX: touch.pageX,
@@ -140,47 +139,49 @@ export default class TouchSensor extends Sensor {
140139
this.trigger(this.currentContainer, dragStartEvent);
141140

142141
this.dragging = !dragStartEvent.canceled();
142+
143+
if (this.dragging) {
144+
document.addEventListener('touchmove', this[onTouchMove]);
145+
}
143146
preventScrolling = this.dragging;
144147
}
145148

146149
/**
147-
* Detect change in distance
150+
* Touch move handler prior to drag start.
148151
* @private
149152
* @param {Event} event - Touch move event
150153
*/
151154
[onDistanceChange](event) {
152-
if (this.dragging || !this.options.distance) {
153-
return;
154-
}
155-
156-
const tap = this.startEvent.touches[0] || this.startEvent.changedTouches[0];
157-
const touch = event.touches[0] || event.changedTouches[0];
158-
159-
this.distance = distance(tap.pageX, tap.pageY, touch.pageX, touch.pageY);
160-
161-
if (this.delayOver && this.distance >= this.options.distance) {
155+
const {delay, distance} = this.options;
156+
const {startEvent} = this;
157+
const start = touchCoords(startEvent);
158+
const current = touchCoords(event);
159+
const timeElapsed = Date.now() - this.onTouchStartAt;
160+
const distanceTravelled = euclideanDistance(start.pageX, start.pageY, current.pageX, current.pageY);
161+
162+
Object.assign(this, current);
163+
if (timeElapsed >= delay && distanceTravelled >= distance) {
164+
window.clearTimeout(this.tapTimeout);
165+
document.removeEventListener('touchmove', this[onDistanceChange]);
162166
this[startDrag]();
163167
}
164168
}
165169

166170
/**
167-
* Touch move handler
171+
* Mouse move handler while dragging
168172
* @private
169173
* @param {Event} event - Touch move event
170174
*/
171175
[onTouchMove](event) {
172-
this.touchMoved = true;
173-
174176
if (!this.dragging) {
175177
return;
176178
}
177-
178-
const touch = event.touches[0] || event.changedTouches[0];
179-
const target = document.elementFromPoint(touch.pageX - window.scrollX, touch.pageY - window.scrollY);
179+
const {pageX, pageY} = touchCoords(event);
180+
const target = document.elementFromPoint(pageX - window.scrollX, pageY - window.scrollY);
180181

181182
const dragMoveEvent = new DragMoveSensorEvent({
182-
clientX: touch.pageX,
183-
clientY: touch.pageY,
183+
clientX: pageX,
184+
clientY: pageY,
184185
target,
185186
container: this.currentContainer,
186187
originalEvent: event,
@@ -195,32 +196,31 @@ export default class TouchSensor extends Sensor {
195196
* @param {Event} event - Touch end event
196197
*/
197198
[onTouchEnd](event) {
198-
this.touchMoved = false;
199+
clearTimeout(this.tapTimeout);
199200
preventScrolling = false;
200201

201202
document.removeEventListener('touchend', this[onTouchEnd]);
202203
document.removeEventListener('touchcancel', this[onTouchEnd]);
203-
document.removeEventListener('touchmove', this[onTouchMove]);
204204
document.removeEventListener('touchmove', this[onDistanceChange]);
205205

206206
if (this.currentContainer) {
207207
this.currentContainer.removeEventListener('contextmenu', onContextMenu);
208208
}
209209

210-
clearTimeout(this.tapTimeout);
211-
212210
if (!this.dragging) {
213211
return;
214212
}
215213

216-
const touch = event.touches[0] || event.changedTouches[0];
217-
const target = document.elementFromPoint(touch.pageX - window.scrollX, touch.pageY - window.scrollY);
214+
document.removeEventListener('touchmove', this[onTouchMove]);
215+
216+
const {pageX, pageY} = touchCoords(event);
217+
const target = document.elementFromPoint(pageX - window.scrollX, pageY - window.scrollY);
218218

219219
event.preventDefault();
220220

221221
const dragStopEvent = new DragStopSensorEvent({
222-
clientX: touch.pageX,
223-
clientY: touch.pageY,
222+
clientX: pageX,
223+
clientY: pageY,
224224
target,
225225
container: this.currentContainer,
226226
originalEvent: event,
@@ -230,8 +230,6 @@ export default class TouchSensor extends Sensor {
230230

231231
this.currentContainer = null;
232232
this.dragging = false;
233-
this.distance = 0;
234-
this.delayOver = false;
235233
this.startEvent = null;
236234
}
237235
}

0 commit comments

Comments
 (0)