Skip to content

Commit

Permalink
feat(drag-drop): allow drag start delay to be configured based on eve…
Browse files Browse the repository at this point in the history
…nt type

Allows the consumer to configure the drag start delay based on whether it's a touch event or mouse event.

Fixes angular#17260.
  • Loading branch information
crisbeto committed Oct 5, 2019
1 parent 473d4c6 commit 4c4e708
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 @@ -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

0 comments on commit 4c4e708

Please sign in to comment.