Skip to content

Commit

Permalink
fix: allow dragging the element inside a scrollable container
Browse files Browse the repository at this point in the history
BREAKING CHANGE: A cloned element is now created when the element is being dragged, and the dragged
element is set to be positioned fixed. This may break some apps in some edge cases.

Fixes #25
  • Loading branch information
mattlewis92 committed Jun 5, 2018
1 parent d0093e8 commit 6e0a1a3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 4 deletions.
42 changes: 38 additions & 4 deletions src/draggable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
* @hidden
*/
constructor(
public element: ElementRef,
public element: ElementRef<HTMLElement>,
private renderer: Renderer2,
private draggableHelper: DraggableHelper,
private zone: NgZone
Expand Down Expand Up @@ -206,19 +206,47 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
.pipe(takeUntil(merge(this.pointerUp, this.pointerDown)))
.pipe(share());

pointerMove.pipe(take(1)).subscribe(() => {
const dragStart$ = pointerMove.pipe(take(1)).pipe(share());
const dragEnd$ = pointerMove.pipe(takeLast(1)).pipe(share());

dragStart$.subscribe(() => {
pointerDownEvent.event.preventDefault();

this.zone.run(() => {
this.dragStart.next({ x: 0, y: 0 });
});

if (this.ghostDragEnabled) {
const rect = this.element.nativeElement.getBoundingClientRect();
const clone = this.element.nativeElement.cloneNode(true);
this.renderer.setStyle(clone, 'visibility', 'hidden');
this.element.nativeElement.parentNode!.insertBefore(
clone,
this.element.nativeElement
);

this.setElementStyles({
position: 'fixed',
top: `${rect.top}px`,
left: `${rect.left}px`
});

dragEnd$.subscribe(() => {
clone.parentElement!.removeChild(clone);
this.setElementStyles({
position: '',
top: '',
left: ''
});
});
}

this.setCursor(this.dragCursor);

this.draggableHelper.currentDrag.next(currentDrag);
});

pointerMove.pipe(takeLast(1)).subscribe(({ x, y }) => {
dragEnd$.subscribe(({ x, y }) => {
this.zone.run(() => {
this.dragEnd.next({ x, y });
});
Expand Down Expand Up @@ -272,7 +300,7 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
}

ngOnChanges(changes: SimpleChanges): void {
if (changes['dragAxis']) {
if (changes.dragAxis) {
this.checkEventListeners();
}
}
Expand Down Expand Up @@ -459,4 +487,10 @@ export class DraggableDirective implements OnInit, OnChanges, OnDestroy {
delete (this as any).eventListenerSubscriptions[type];
});
}

private setElementStyles(styles: { [key: string]: string }) {
Object.keys(styles).forEach(key => {
this.renderer.setStyle(this.element.nativeElement, key, styles[key]);
});
}
}
33 changes: 33 additions & 0 deletions test/draggable.directive.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,4 +564,37 @@ describe('draggable directive', () => {
fixture.componentInstance.dragEnd
);
});

it('should create a clone of the element and make the host static', () => {
const draggableElement: HTMLElement =
fixture.componentInstance.draggable.element.nativeElement;
expect(
(draggableElement.previousElementSibling as HTMLElement).hasAttribute(
'mwldraggable'
)
).to.be.false;
triggerDomEvent('mousedown', draggableElement, { clientX: 5, clientY: 10 });
triggerDomEvent('mousemove', draggableElement, { clientX: 7, clientY: 10 });
expect(draggableElement.style.position).to.equal('fixed');
expect(draggableElement.style.top).to.be.ok;
expect(draggableElement.style.left).to.be.ok;
expect(draggableElement.previousSibling).to.be.ok;
expect(
(draggableElement.previousElementSibling as HTMLElement).style.visibility
).to.equal('hidden');
expect(
(draggableElement.previousElementSibling as HTMLElement).hasAttribute(
'mwldraggable'
)
).to.be.true;
triggerDomEvent('mouseup', draggableElement, { clientX: 7, clientY: 8 });
expect(draggableElement.style.position).not.to.be.ok;
expect(draggableElement.style.top).not.to.be.ok;
expect(draggableElement.style.left).not.to.be.ok;
expect(
(draggableElement.previousElementSibling as HTMLElement).hasAttribute(
'mwldraggable'
)
).to.be.false;
});
});

0 comments on commit 6e0a1a3

Please sign in to comment.