@@ -76,6 +76,14 @@ export function CDK_DRAG_CONFIG_FACTORY(): CdkDragConfig {
76
76
return { dragStartThreshold : 5 , pointerDirectionChangeThreshold : 5 } ;
77
77
}
78
78
79
+ /**
80
+ * Time in milliseconds for which to ignore mouse events, after
81
+ * receiving a touch event. Used to avoid doing double work for
82
+ * touch devices where the browser fires fake mouse events, in
83
+ * addition to touch events.
84
+ */
85
+ const MOUSE_EVENT_IGNORE_TIME = 800 ;
86
+
79
87
/** Element that can be moved inside a CdkDrop container. */
80
88
@Directive ( {
81
89
selector : '[cdkDrag]' ,
@@ -161,6 +169,12 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
161
169
162
170
/** Subscription to the event that is dispatched when the user lifts their pointer. */
163
171
private _pointerUpSubscription = Subscription . EMPTY ;
172
+ /**
173
+ * Time at which the last touch event occurred. Used to avoid firing the same
174
+ * events multiple times on touch devices where the browser will fire a fake
175
+ * mouse event for each touch event, after a certain time.
176
+ */
177
+ private _lastTouchEventTime : number ;
164
178
165
179
/** Elements that can be used to drag the draggable item. */
166
180
@ContentChildren ( CdkDragHandle ) _handles : QueryList < CdkDragHandle > ;
@@ -308,9 +322,13 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
308
322
*/
309
323
private _initializeDragSequence ( referenceElement : HTMLElement , event : MouseEvent | TouchEvent ) {
310
324
const isDragging = this . _isDragging ( ) ;
325
+ const isTouchEvent = this . _isTouchEvent ( event ) ;
326
+ const isAuxiliaryMouseButton = ! isTouchEvent && ( event as MouseEvent ) . button !== 0 ;
327
+ const isSyntheticEvent = ! isTouchEvent && this . _lastTouchEventTime &&
328
+ this . _lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date . now ( ) ;
311
329
312
330
// Abort if the user is already dragging or is using a mouse button other than the primary one.
313
- if ( isDragging || ( ! this . _isTouchEvent ( event ) && event . button !== 0 ) ) {
331
+ if ( isDragging || isAuxiliaryMouseButton || isSyntheticEvent ) {
314
332
return ;
315
333
}
316
334
@@ -331,10 +349,14 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
331
349
}
332
350
333
351
/** Starts the dragging sequence. */
334
- private _startDragSequence ( ) {
352
+ private _startDragSequence ( event : MouseEvent | TouchEvent ) {
335
353
// Emit the event on the item before the one on the container.
336
354
this . started . emit ( { source : this } ) ;
337
355
356
+ if ( this . _isTouchEvent ( event ) ) {
357
+ this . _lastTouchEventTime = Date . now ( ) ;
358
+ }
359
+
338
360
if ( this . dropContainer ) {
339
361
const element = this . _rootElement ;
340
362
@@ -370,7 +392,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
370
392
// per pixel of movement (e.g. if the user moves their pointer quickly).
371
393
if ( distanceX + distanceY >= minimumDistance ) {
372
394
this . _hasStartedDragging = true ;
373
- this . _ngZone . run ( ( ) => this . _startDragSequence ( ) ) ;
395
+ this . _ngZone . run ( ( ) => this . _startDragSequence ( event ) ) ;
374
396
}
375
397
376
398
return ;
@@ -426,10 +448,14 @@ export class CdkDrag<T = any> implements AfterViewInit, OnDestroy {
426
448
this . _passiveTransform . x = this . _activeTransform . x ;
427
449
this . _passiveTransform . y = this . _activeTransform . y ;
428
450
this . _ngZone . run ( ( ) => this . ended . emit ( { source : this } ) ) ;
451
+ this . _dragDropRegistry . stopDragging ( this ) ;
429
452
return ;
430
453
}
431
454
432
- this . _animatePreviewToPlaceholder ( ) . then ( ( ) => this . _cleanupDragArtifacts ( ) ) ;
455
+ this . _animatePreviewToPlaceholder ( ) . then ( ( ) => {
456
+ this . _cleanupDragArtifacts ( ) ;
457
+ this . _dragDropRegistry . stopDragging ( this ) ;
458
+ } ) ;
433
459
}
434
460
435
461
/** Cleans up the DOM artifacts that were added to facilitate the element being dragged. */
0 commit comments