Skip to content

feat(drag-drop): allow drag start delay to be configured based on event type #17301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -4266,7 +4287,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