Skip to content

Commit f02a70b

Browse files
committed
fix(delay_distance): cleanup and evaluate pre-drag conditions without flags
Fail fast - do not add mouseup and mousemove listeners if there is no container Store time and location of event for later evaluation of delay and distance Prefer single code path to startDrag avoiding flags and secondary constraint evaluation Add tests for all three configruations - only delay, only distance, both distance and delay
1 parent 4ab09de commit f02a70b

File tree

2 files changed

+255
-119
lines changed

2 files changed

+255
-119
lines changed

src/Draggable/Sensors/MouseSensor/MouseSensor.js

Lines changed: 31 additions & 21 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} from 'shared/utils';
22
import Sensor from '../Sensor';
33
import {DragStartSensorEvent, DragMoveSensorEvent, DragStopSensorEvent} from '../SensorEvent';
44

@@ -63,28 +63,27 @@ export default class MouseSensor extends Sensor {
6363
if (event.button !== 0 || event.ctrlKey || event.metaKey) {
6464
return;
6565
}
66-
67-
this.startEvent = event;
68-
69-
document.addEventListener('mouseup', this[onMouseUp]);
70-
document.addEventListener('mousemove', this[onDistanceChange]);
71-
7266
const container = closest(event.target, this.containers);
7367

7468
if (!container) {
7569
return;
7670
}
7771

78-
document.addEventListener('dragstart', preventNativeDragStart);
72+
const {delay = 0} = this.options;
73+
const {pageX, pageY} = event;
74+
75+
Object.assign(this, {pageX, pageY});
76+
this.onMouseDownAt = Date.now();
77+
this.startEvent = event;
7978

8079
this.currentContainer = container;
81-
this.mouseDownTimeout = setTimeout(() => {
82-
this.delayOver = true;
83-
if (this.distance < this.options.distance) {
84-
return;
85-
}
86-
this[startDrag]();
87-
}, this.options.delay);
80+
document.addEventListener('mouseup', this[onMouseUp]);
81+
document.addEventListener('dragstart', preventNativeDragStart);
82+
document.addEventListener('mousemove', this[onDistanceChange]);
83+
84+
this.mouseDownTimeout = window.setTimeout(() => {
85+
this[onDistanceChange]({pageX: this.pageX, pageY: this.pageY});
86+
}, delay);
8887
}
8988

9089
/**
@@ -114,15 +113,28 @@ export default class MouseSensor extends Sensor {
114113
}
115114

116115
/**
117-
* Detect change in distance
116+
* Detect change in distance, starting drag when both
117+
* delay and distance requirements are met
118118
* @private
119119
* @param {Event} event - Mouse move event
120120
*/
121121
[onDistanceChange](event) {
122-
if (this.dragging) return;
123-
this.distance = distance(this.startEvent.pageX, this.startEvent.pageY, event.pageX, event.pageY);
122+
const {pageX, pageY} = event;
123+
const {delay, distance} = this.options;
124+
const {startEvent} = this;
125+
126+
Object.assign(this, {pageX, pageY});
127+
128+
if (!this.currentContainer) {
129+
return;
130+
}
131+
132+
const timeElapsed = Date.now() - this.onMouseDownAt;
133+
const distanceTravelled = euclideanDistance(startEvent.pageX, startEvent.pageY, pageX, pageY) || 0;
124134

125-
if (this.delayOver && this.distance >= this.options.distance) {
135+
if (timeElapsed >= delay && distanceTravelled >= distance) {
136+
window.clearTimeout(this.mouseDownTimeout);
137+
document.removeEventListener('mousemove', this[onDistanceChange]);
126138
this[startDrag]();
127139
}
128140
}
@@ -187,8 +199,6 @@ export default class MouseSensor extends Sensor {
187199

188200
this.currentContainer = null;
189201
this.dragging = false;
190-
this.distance = 0;
191-
this.delayOver = false;
192202
this.startEvent = null;
193203
}
194204

0 commit comments

Comments
 (0)