Skip to content

Commit

Permalink
feat(drag-drop): allow drag start delay to be configured based… (#17301)
Browse files Browse the repository at this point in the history
Allows the consumer to configure the drag start delay based on whether it's a touch event or mouse event.

Fixes #17260.
  • Loading branch information
crisbeto authored and mmalerba committed Oct 14, 2019
1 parent 7a748fc commit 43c7a7d
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 7 deletions.
23 changes: 22 additions & 1 deletion src/cdk/drag-drop/directives/drag.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,27 @@ describe('CdkDrag', () => {
'Expected element to be dragged after all the time has passed.');
}));

it('should be able to configure the drag start delay based on the event type', fakeAsync(() => {
// We can't use Jasmine's `clock` because Zone.js interferes with it.
spyOn(Date, 'now').and.callFake(() => currentTime);
let currentTime = 0;

const fixture = createComponent(StandaloneDraggable);
fixture.componentInstance.dragStartDelay = {touch: 500, mouse: 0};
fixture.detectChanges();
const dragElement = fixture.componentInstance.dragElement.nativeElement;

expect(dragElement.style.transform).toBeFalsy('Expected element not to be moved by default.');

dragElementViaTouch(fixture, dragElement, 50, 100);
expect(dragElement.style.transform)
.toBeFalsy('Expected element not to be moved via touch because it has a delay.');

dragElementViaMouse(fixture, dragElement, 50, 100);
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)',
'Expected element to be moved via mouse because it has no delay.');
}));

it('should be able to get the current position', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.detectChanges();
Expand Down Expand Up @@ -4293,7 +4314,7 @@ class StandaloneDraggable {
endedSpy = jasmine.createSpy('ended spy');
releasedSpy = jasmine.createSpy('released spy');
boundary: string | HTMLElement;
dragStartDelay: number | string;
dragStartDelay: number | string | {touch: number, mouse: number};
constrainPosition: (point: Point) => Point;
freeDragPosition?: {x: number, y: number};
}
Expand Down
6 changes: 4 additions & 2 deletions src/cdk/drag-drop/directives/drag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
* Amount of milliseconds to wait after the user has put their
* pointer down before starting to drag the element.
*/
@Input('cdkDragStartDelay') dragStartDelay: number = 0;
@Input('cdkDragStartDelay') dragStartDelay: number | {touch: number, mouse: number} = 0;

/**
* Sets the position of a `CdkDrag` that is outside of a drop container.
Expand Down Expand Up @@ -326,6 +326,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
ref.beforeStarted.subscribe(() => {
if (!ref.isDragging()) {
const dir = this._dir;
const dragStartDelay = this.dragStartDelay;
const placeholder = this._placeholderTemplate ? {
template: this._placeholderTemplate.templateRef,
context: this._placeholderTemplate.data,
Expand All @@ -339,7 +340,8 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {

ref.disabled = this.disabled;
ref.lockAxis = this.lockAxis;
ref.dragStartDelay = coerceNumberProperty(this.dragStartDelay);
ref.dragStartDelay = (typeof dragStartDelay === 'object' && dragStartDelay) ?
dragStartDelay : coerceNumberProperty(dragStartDelay);
ref.constrainPosition = this.constrainPosition;
ref
.withBoundaryElement(this._getBoundaryElement())
Expand Down
17 changes: 15 additions & 2 deletions src/cdk/drag-drop/drag-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export class DragRef<T = any> {
* Amount of milliseconds to wait after the user has put their
* pointer down before starting to drag the element.
*/
dragStartDelay: number = 0;
dragStartDelay: number | {touch: number, mouse: number} = 0;

/** Whether starting to drag this element is disabled. */
get disabled(): boolean {
Expand Down Expand Up @@ -533,7 +533,7 @@ export class DragRef<T = any> {
// in the `pointerMove` subscription, because we're not guaranteed to have one move event
// per pixel of movement (e.g. if the user moves their pointer quickly).
if (isOverThreshold) {
const isDelayElapsed = Date.now() >= this._dragStartTime + (this.dragStartDelay || 0);
const isDelayElapsed = Date.now() >= this._dragStartTime + this._getDragStartDelay(event);
if (!isDelayElapsed) {
this._endDragSequence(event);
return;
Expand Down Expand Up @@ -1149,6 +1149,19 @@ export class DragRef<T = any> {
this.setFreeDragPosition({y, x});
}
}

/** Gets the drag start delay, based on the event type. */
private _getDragStartDelay(event: MouseEvent | TouchEvent): number {
const value = this.dragStartDelay;

if (typeof value === 'number') {
return value;
} else if (isTouchEvent(event)) {
return value.touch;
}

return value ? value.mouse : 0;
}
}

/** Point on the page or within an element. */
Expand Down
10 changes: 8 additions & 2 deletions tools/public_api_guard/cdk/drag-drop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDes
constrainPosition?: (point: Point, dragRef: DragRef) => Point;
data: T;
disabled: boolean;
dragStartDelay: number;
dragStartDelay: number | {
touch: number;
mouse: number;
};
dropContainer: CdkDropList;
dropped: EventEmitter<CdkDragDrop<any>>;
element: ElementRef<HTMLElement>;
Expand Down Expand Up @@ -194,7 +197,10 @@ export declare class DragRef<T = any> {
constrainPosition?: (point: Point, dragRef: DragRef) => Point;
data: T;
disabled: boolean;
dragStartDelay: number;
dragStartDelay: number | {
touch: number;
mouse: number;
};
dropped: Subject<{
previousIndex: number;
currentIndex: number;
Expand Down

0 comments on commit 43c7a7d

Please sign in to comment.