@@ -85,6 +85,14 @@ const passiveEventListenerOptions = normalizePassiveListenerOptions({passive: tr
85
85
/** Options that can be used to bind an active event listener. */
86
86
const activeEventListenerOptions = normalizePassiveListenerOptions ( { passive : false } ) ;
87
87
88
+ /**
89
+ * Time in milliseconds for which to ignore mouse events, after
90
+ * receiving a touch event. Used to avoid doing double work for
91
+ * touch devices where the browser fires fake mouse events, in
92
+ * addition to touch events.
93
+ */
94
+ const MOUSE_EVENT_IGNORE_TIME = 800 ;
95
+
88
96
/** Element that can be moved inside a CdkDropList container. */
89
97
@Directive ( {
90
98
selector : '[cdkDrag]' ,
@@ -177,6 +185,12 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
177
185
178
186
/** Subscription to the event that is dispatched when the user lifts their pointer. */
179
187
private _pointerUpSubscription = Subscription . EMPTY ;
188
+ /**
189
+ * Time at which the last touch event occurred. Used to avoid firing the same
190
+ * events multiple times on touch devices where the browser will fire a fake
191
+ * mouse event for each touch event, after a certain time.
192
+ */
193
+ private _lastTouchEventTime : number ;
180
194
181
195
/** Subscription to the stream that initializes the root element. */
182
196
private _rootElementInitSubscription = Subscription . EMPTY ;
@@ -357,6 +371,12 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
357
371
// starting another sequence for a draggable parent somewhere up the DOM tree.
358
372
event . stopPropagation ( ) ;
359
373
374
+ const isDragging = this . _isDragging ( ) ;
375
+ const isTouchEvent = this . _isTouchEvent ( event ) ;
376
+ const isAuxiliaryMouseButton = ! isTouchEvent && ( event as MouseEvent ) . button !== 0 ;
377
+ const isSyntheticEvent = ! isTouchEvent && this . _lastTouchEventTime &&
378
+ this . _lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date . now ( ) ;
379
+
360
380
// If the event started from an element with the native HTML drag&drop, it'll interfere
361
381
// with our own dragging (e.g. `img` tags do it by default). Prevent the default action
362
382
// to stop it from happening. Note that preventing on `dragstart` also seems to work, but
@@ -368,7 +388,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
368
388
}
369
389
370
390
// Abort if the user is already dragging or is using a mouse button other than the primary one.
371
- if ( this . _isDragging ( ) || ( ! this . _isTouchEvent ( event ) && event . button !== 0 ) ) {
391
+ if ( isDragging || isAuxiliaryMouseButton || isSyntheticEvent ) {
372
392
return ;
373
393
}
374
394
@@ -395,10 +415,14 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
395
415
}
396
416
397
417
/** Starts the dragging sequence. */
398
- private _startDragSequence ( ) {
418
+ private _startDragSequence ( event : MouseEvent | TouchEvent ) {
399
419
// Emit the event on the item before the one on the container.
400
420
this . started . emit ( { source : this } ) ;
401
421
422
+ if ( this . _isTouchEvent ( event ) ) {
423
+ this . _lastTouchEventTime = Date . now ( ) ;
424
+ }
425
+
402
426
if ( this . dropContainer ) {
403
427
const element = this . _rootElement ;
404
428
@@ -433,7 +457,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
433
457
// per pixel of movement (e.g. if the user moves their pointer quickly).
434
458
if ( distanceX + distanceY >= this . _config . dragStartThreshold ) {
435
459
this . _hasStartedDragging = true ;
436
- this . _ngZone . run ( ( ) => this . _startDragSequence ( ) ) ;
460
+ this . _ngZone . run ( ( ) => this . _startDragSequence ( event ) ) ;
437
461
}
438
462
439
463
return ;
@@ -493,10 +517,14 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
493
517
this . _passiveTransform . x = this . _activeTransform . x ;
494
518
this . _passiveTransform . y = this . _activeTransform . y ;
495
519
this . _ngZone . run ( ( ) => this . ended . emit ( { source : this } ) ) ;
520
+ this . _dragDropRegistry . stopDragging ( this ) ;
496
521
return ;
497
522
}
498
523
499
- this . _animatePreviewToPlaceholder ( ) . then ( ( ) => this . _cleanupDragArtifacts ( ) ) ;
524
+ this . _animatePreviewToPlaceholder ( ) . then ( ( ) => {
525
+ this . _cleanupDragArtifacts ( ) ;
526
+ this . _dragDropRegistry . stopDragging ( this ) ;
527
+ } ) ;
500
528
}
501
529
502
530
/** Cleans up the DOM artifacts that were added to facilitate the element being dragged. */
0 commit comments