angular-draggable-droppable
Version:
Drag and drop for angular 15.0+
575 lines • 84.3 kB
JavaScript
import { Directive, Output, EventEmitter, Input, Inject, Optional, } from '@angular/core';
import { Subject, Observable, merge, ReplaySubject, combineLatest, fromEvent, } from 'rxjs';
import { map, mergeMap, takeUntil, take, takeLast, pairwise, share, filter, count, startWith, } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';
import autoScroll from '@mattlewis92/dom-autoscroller';
import { addClass, removeClass } from './util';
import * as i0 from "@angular/core";
import * as i1 from "./draggable-helper.provider";
import * as i2 from "./draggable-scroll-container.directive";
export class DraggableDirective {
/**
* @hidden
*/
constructor(element, renderer, draggableHelper, zone, vcr, scrollContainer, document) {
this.element = element;
this.renderer = renderer;
this.draggableHelper = draggableHelper;
this.zone = zone;
this.vcr = vcr;
this.scrollContainer = scrollContainer;
this.document = document;
/**
* The axis along which the element is draggable
*/
this.dragAxis = { x: true, y: true };
/**
* Snap all drags to an x / y grid
*/
this.dragSnapGrid = {};
/**
* Show a ghost element that shows the drag when dragging
*/
this.ghostDragEnabled = true;
/**
* Show the original element when ghostDragEnabled is true
*/
this.showOriginalElementWhileDragging = false;
/**
* The cursor to use when hovering over a draggable element
*/
this.dragCursor = '';
/*
* Options used to control the behaviour of auto scrolling: https://www.npmjs.com/package/dom-autoscroller
*/
this.autoScroll = {
margin: 20,
};
/**
* Called when the element can be dragged along one axis and has the mouse or pointer device pressed on it
*/
this.dragPointerDown = new EventEmitter();
/**
* Called when the element has started to be dragged.
* Only called after at least one mouse or touch move event.
* If you call $event.cancelDrag$.emit() it will cancel the current drag
*/
this.dragStart = new EventEmitter();
/**
* Called after the ghost element has been created
*/
this.ghostElementCreated = new EventEmitter();
/**
* Called when the element is being dragged
*/
this.dragging = new EventEmitter();
/**
* Called after the element is dragged
*/
this.dragEnd = new EventEmitter();
/**
* @hidden
*/
this.pointerDown$ = new Subject();
/**
* @hidden
*/
this.pointerMove$ = new Subject();
/**
* @hidden
*/
this.pointerUp$ = new Subject();
this.eventListenerSubscriptions = {};
this.destroy$ = new Subject();
this.timeLongPress = { timerBegin: 0, timerEnd: 0 };
}
ngOnInit() {
this.checkEventListeners();
const pointerDragged$ = this.pointerDown$.pipe(filter(() => this.canDrag()), mergeMap((pointerDownEvent) => {
// fix for https://github.com/mattlewis92/angular-draggable-droppable/issues/61
// stop mouse events propagating up the chain
if (pointerDownEvent.event.stopPropagation && !this.scrollContainer) {
pointerDownEvent.event.stopPropagation();
}
// hack to prevent text getting selected in safari while dragging
const globalDragStyle = this.renderer.createElement('style');
this.renderer.setAttribute(globalDragStyle, 'type', 'text/css');
this.renderer.appendChild(globalDragStyle, this.renderer.createText(`
body * {
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
}
`));
requestAnimationFrame(() => {
this.document.head.appendChild(globalDragStyle);
});
const startScrollPosition = this.getScrollPosition();
const scrollContainerScroll$ = new Observable((observer) => {
const scrollContainer = this.scrollContainer
? this.scrollContainer.elementRef.nativeElement
: 'window';
return this.renderer.listen(scrollContainer, 'scroll', (e) => observer.next(e));
}).pipe(startWith(startScrollPosition), map(() => this.getScrollPosition()));
const currentDrag$ = new Subject();
const cancelDrag$ = new ReplaySubject();
if (this.dragPointerDown.observers.length > 0) {
this.zone.run(() => {
this.dragPointerDown.next({ x: 0, y: 0 });
});
}
const dragComplete$ = merge(this.pointerUp$, this.pointerDown$, cancelDrag$, this.destroy$).pipe(share());
const pointerMove = combineLatest([
this.pointerMove$,
scrollContainerScroll$,
]).pipe(map(([pointerMoveEvent, scroll]) => {
return {
currentDrag$,
transformX: pointerMoveEvent.clientX - pointerDownEvent.clientX,
transformY: pointerMoveEvent.clientY - pointerDownEvent.clientY,
clientX: pointerMoveEvent.clientX,
clientY: pointerMoveEvent.clientY,
scrollLeft: scroll.left,
scrollTop: scroll.top,
target: pointerMoveEvent.event.target,
};
}), map((moveData) => {
if (this.dragSnapGrid.x) {
moveData.transformX =
Math.round(moveData.transformX / this.dragSnapGrid.x) *
this.dragSnapGrid.x;
}
if (this.dragSnapGrid.y) {
moveData.transformY =
Math.round(moveData.transformY / this.dragSnapGrid.y) *
this.dragSnapGrid.y;
}
return moveData;
}), map((moveData) => {
if (!this.dragAxis.x) {
moveData.transformX = 0;
}
if (!this.dragAxis.y) {
moveData.transformY = 0;
}
return moveData;
}), map((moveData) => {
const scrollX = moveData.scrollLeft - startScrollPosition.left;
const scrollY = moveData.scrollTop - startScrollPosition.top;
return {
...moveData,
x: moveData.transformX + scrollX,
y: moveData.transformY + scrollY,
};
}), filter(({ x, y, transformX, transformY }) => !this.validateDrag ||
this.validateDrag({
x,
y,
transform: { x: transformX, y: transformY },
})), takeUntil(dragComplete$), share());
const dragStarted$ = pointerMove.pipe(take(1), share());
const dragEnded$ = pointerMove.pipe(takeLast(1), share());
dragStarted$.subscribe(({ clientX, clientY, x, y }) => {
if (this.dragStart.observers.length > 0) {
this.zone.run(() => {
this.dragStart.next({ cancelDrag$ });
});
}
this.scroller = autoScroll([
this.scrollContainer
? this.scrollContainer.elementRef.nativeElement
: this.document.defaultView,
], {
...this.autoScroll,
autoScroll() {
return true;
},
});
addClass(this.renderer, this.element, this.dragActiveClass);
if (this.ghostDragEnabled) {
const rect = this.element.nativeElement.getBoundingClientRect();
const clone = this.element.nativeElement.cloneNode(true);
if (!this.showOriginalElementWhileDragging) {
this.renderer.setStyle(this.element.nativeElement, 'visibility', 'hidden');
}
if (this.ghostElementAppendTo) {
this.ghostElementAppendTo.appendChild(clone);
}
else {
this.element.nativeElement.parentNode.insertBefore(clone, this.element.nativeElement.nextSibling);
}
this.ghostElement = clone;
this.document.body.style.cursor = this.dragCursor;
this.setElementStyles(clone, {
position: 'fixed',
top: `${rect.top}px`,
left: `${rect.left}px`,
width: `${rect.width}px`,
height: `${rect.height}px`,
cursor: this.dragCursor,
margin: '0',
willChange: 'transform',
pointerEvents: 'none',
});
if (this.ghostElementTemplate) {
const viewRef = this.vcr.createEmbeddedView(this.ghostElementTemplate);
clone.innerHTML = '';
viewRef.rootNodes
.filter((node) => node instanceof Node)
.forEach((node) => {
clone.appendChild(node);
});
dragEnded$.subscribe(() => {
this.vcr.remove(this.vcr.indexOf(viewRef));
});
}
if (this.ghostElementCreated.observers.length > 0) {
this.zone.run(() => {
this.ghostElementCreated.emit({
clientX: clientX - x,
clientY: clientY - y,
element: clone,
});
});
}
dragEnded$.subscribe(() => {
clone.parentElement.removeChild(clone);
this.ghostElement = null;
this.renderer.setStyle(this.element.nativeElement, 'visibility', '');
});
}
this.draggableHelper.currentDrag.next(currentDrag$);
});
dragEnded$
.pipe(mergeMap((dragEndData) => {
const dragEndData$ = cancelDrag$.pipe(count(), take(1), map((calledCount) => ({
...dragEndData,
dragCancelled: calledCount > 0,
})));
cancelDrag$.complete();
return dragEndData$;
}))
.subscribe(({ x, y, dragCancelled }) => {
this.scroller.destroy();
if (this.dragEnd.observers.length > 0) {
this.zone.run(() => {
this.dragEnd.next({ x, y, dragCancelled });
});
}
removeClass(this.renderer, this.element, this.dragActiveClass);
currentDrag$.complete();
});
merge(dragComplete$, dragEnded$)
.pipe(take(1))
.subscribe(() => {
requestAnimationFrame(() => {
this.document.head.removeChild(globalDragStyle);
});
});
return pointerMove;
}), share());
merge(pointerDragged$.pipe(take(1), map((value) => [, value])), pointerDragged$.pipe(pairwise()))
.pipe(filter(([previous, next]) => {
if (!previous) {
return true;
}
return previous.x !== next.x || previous.y !== next.y;
}), map(([previous, next]) => next))
.subscribe(({ x, y, currentDrag$, clientX, clientY, transformX, transformY, target, }) => {
if (this.dragging.observers.length > 0) {
this.zone.run(() => {
this.dragging.next({ x, y });
});
}
requestAnimationFrame(() => {
if (this.ghostElement) {
const transform = `translate3d(${transformX}px, ${transformY}px, 0px)`;
this.setElementStyles(this.ghostElement, {
transform,
'-webkit-transform': transform,
'-ms-transform': transform,
'-moz-transform': transform,
'-o-transform': transform,
});
}
});
currentDrag$.next({
clientX,
clientY,
dropData: this.dropData,
target,
});
});
}
ngOnChanges(changes) {
if (changes.dragAxis) {
this.checkEventListeners();
}
}
ngOnDestroy() {
this.unsubscribeEventListeners();
this.pointerDown$.complete();
this.pointerMove$.complete();
this.pointerUp$.complete();
this.destroy$.next();
}
checkEventListeners() {
const canDrag = this.canDrag();
const hasEventListeners = Object.keys(this.eventListenerSubscriptions).length > 0;
if (canDrag && !hasEventListeners) {
this.zone.runOutsideAngular(() => {
this.eventListenerSubscriptions.mousedown = this.renderer.listen(this.element.nativeElement, 'mousedown', (event) => {
this.onMouseDown(event);
});
this.eventListenerSubscriptions.mouseup = this.renderer.listen('document', 'mouseup', (event) => {
this.onMouseUp(event);
});
this.eventListenerSubscriptions.touchstart = this.renderer.listen(this.element.nativeElement, 'touchstart', (event) => {
this.onTouchStart(event);
});
this.eventListenerSubscriptions.touchend = this.renderer.listen('document', 'touchend', (event) => {
this.onTouchEnd(event);
});
this.eventListenerSubscriptions.touchcancel = this.renderer.listen('document', 'touchcancel', (event) => {
this.onTouchEnd(event);
});
this.eventListenerSubscriptions.mouseenter = this.renderer.listen(this.element.nativeElement, 'mouseenter', () => {
this.onMouseEnter();
});
this.eventListenerSubscriptions.mouseleave = this.renderer.listen(this.element.nativeElement, 'mouseleave', () => {
this.onMouseLeave();
});
});
}
else if (!canDrag && hasEventListeners) {
this.unsubscribeEventListeners();
}
}
onMouseDown(event) {
if (event.button === 0) {
if (!this.eventListenerSubscriptions.mousemove) {
this.eventListenerSubscriptions.mousemove = this.renderer.listen('document', 'mousemove', (mouseMoveEvent) => {
this.pointerMove$.next({
event: mouseMoveEvent,
clientX: mouseMoveEvent.clientX,
clientY: mouseMoveEvent.clientY,
});
});
}
this.pointerDown$.next({
event,
clientX: event.clientX,
clientY: event.clientY,
});
}
}
onMouseUp(event) {
if (event.button === 0) {
if (this.eventListenerSubscriptions.mousemove) {
this.eventListenerSubscriptions.mousemove();
delete this.eventListenerSubscriptions.mousemove;
}
this.pointerUp$.next({
event,
clientX: event.clientX,
clientY: event.clientY,
});
}
}
onTouchStart(event) {
let startScrollPosition;
let isDragActivated;
let hasContainerScrollbar;
if (this.touchStartLongPress) {
this.timeLongPress.timerBegin = Date.now();
isDragActivated = false;
hasContainerScrollbar = this.hasScrollbar();
startScrollPosition = this.getScrollPosition();
}
if (!this.eventListenerSubscriptions.touchmove) {
const contextMenuListener = fromEvent(this.document, 'contextmenu').subscribe((e) => {
e.preventDefault();
});
const touchMoveListener = fromEvent(this.document, 'touchmove', {
passive: false,
}).subscribe((touchMoveEvent) => {
if (this.touchStartLongPress &&
!isDragActivated &&
hasContainerScrollbar) {
isDragActivated = this.shouldBeginDrag(event, touchMoveEvent, startScrollPosition);
}
if (!this.touchStartLongPress ||
!hasContainerScrollbar ||
isDragActivated) {
touchMoveEvent.preventDefault();
this.pointerMove$.next({
event: touchMoveEvent,
clientX: touchMoveEvent.targetTouches[0].clientX,
clientY: touchMoveEvent.targetTouches[0].clientY,
});
}
});
this.eventListenerSubscriptions.touchmove = () => {
contextMenuListener.unsubscribe();
touchMoveListener.unsubscribe();
};
}
this.pointerDown$.next({
event,
clientX: event.touches[0].clientX,
clientY: event.touches[0].clientY,
});
}
onTouchEnd(event) {
if (this.eventListenerSubscriptions.touchmove) {
this.eventListenerSubscriptions.touchmove();
delete this.eventListenerSubscriptions.touchmove;
if (this.touchStartLongPress) {
this.enableScroll();
}
}
this.pointerUp$.next({
event,
clientX: event.changedTouches[0].clientX,
clientY: event.changedTouches[0].clientY,
});
}
onMouseEnter() {
this.setCursor(this.dragCursor);
}
onMouseLeave() {
this.setCursor('');
}
canDrag() {
return this.dragAxis.x || this.dragAxis.y;
}
setCursor(value) {
if (!this.eventListenerSubscriptions.mousemove) {
this.renderer.setStyle(this.element.nativeElement, 'cursor', value);
}
}
unsubscribeEventListeners() {
Object.keys(this.eventListenerSubscriptions).forEach((type) => {
this.eventListenerSubscriptions[type]();
delete this.eventListenerSubscriptions[type];
});
}
setElementStyles(element, styles) {
Object.keys(styles).forEach((key) => {
this.renderer.setStyle(element, key, styles[key]);
});
}
getScrollElement() {
if (this.scrollContainer) {
return this.scrollContainer.elementRef.nativeElement;
}
else {
return this.document.body;
}
}
getScrollPosition() {
if (this.scrollContainer) {
return {
top: this.scrollContainer.elementRef.nativeElement.scrollTop,
left: this.scrollContainer.elementRef.nativeElement.scrollLeft,
};
}
else {
return {
top: window.pageYOffset || this.document.documentElement.scrollTop,
left: window.pageXOffset || this.document.documentElement.scrollLeft,
};
}
}
shouldBeginDrag(event, touchMoveEvent, startScrollPosition) {
const moveScrollPosition = this.getScrollPosition();
const deltaScroll = {
top: Math.abs(moveScrollPosition.top - startScrollPosition.top),
left: Math.abs(moveScrollPosition.left - startScrollPosition.left),
};
const deltaX = Math.abs(touchMoveEvent.targetTouches[0].clientX - event.touches[0].clientX) - deltaScroll.left;
const deltaY = Math.abs(touchMoveEvent.targetTouches[0].clientY - event.touches[0].clientY) - deltaScroll.top;
const deltaTotal = deltaX + deltaY;
const longPressConfig = this.touchStartLongPress;
if (deltaTotal > longPressConfig.delta ||
deltaScroll.top > 0 ||
deltaScroll.left > 0) {
this.timeLongPress.timerBegin = Date.now();
}
this.timeLongPress.timerEnd = Date.now();
const duration = this.timeLongPress.timerEnd - this.timeLongPress.timerBegin;
if (duration >= longPressConfig.delay) {
this.disableScroll();
return true;
}
return false;
}
enableScroll() {
if (this.scrollContainer) {
this.renderer.setStyle(this.scrollContainer.elementRef.nativeElement, 'overflow', '');
}
this.renderer.setStyle(this.document.body, 'overflow', '');
}
disableScroll() {
/* istanbul ignore next */
if (this.scrollContainer) {
this.renderer.setStyle(this.scrollContainer.elementRef.nativeElement, 'overflow', 'hidden');
}
this.renderer.setStyle(this.document.body, 'overflow', 'hidden');
}
hasScrollbar() {
const scrollContainer = this.getScrollElement();
const containerHasHorizontalScroll = scrollContainer.scrollWidth > scrollContainer.clientWidth;
const containerHasVerticalScroll = scrollContainer.scrollHeight > scrollContainer.clientHeight;
return containerHasHorizontalScroll || containerHasVerticalScroll;
}
}
DraggableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: DraggableDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i1.DraggableHelper }, { token: i0.NgZone }, { token: i0.ViewContainerRef }, { token: i2.DraggableScrollContainerDirective, optional: true }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive });
DraggableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.3", type: DraggableDirective, selector: "[mwlDraggable]", inputs: { dropData: "dropData", dragAxis: "dragAxis", dragSnapGrid: "dragSnapGrid", ghostDragEnabled: "ghostDragEnabled", showOriginalElementWhileDragging: "showOriginalElementWhileDragging", validateDrag: "validateDrag", dragCursor: "dragCursor", dragActiveClass: "dragActiveClass", ghostElementAppendTo: "ghostElementAppendTo", ghostElementTemplate: "ghostElementTemplate", touchStartLongPress: "touchStartLongPress", autoScroll: "autoScroll" }, outputs: { dragPointerDown: "dragPointerDown", dragStart: "dragStart", ghostElementCreated: "ghostElementCreated", dragging: "dragging", dragEnd: "dragEnd" }, usesOnChanges: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.3", ngImport: i0, type: DraggableDirective, decorators: [{
type: Directive,
args: [{
selector: '[mwlDraggable]',
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i1.DraggableHelper }, { type: i0.NgZone }, { type: i0.ViewContainerRef }, { type: i2.DraggableScrollContainerDirective, decorators: [{
type: Optional
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DOCUMENT]
}] }]; }, propDecorators: { dropData: [{
type: Input
}], dragAxis: [{
type: Input
}], dragSnapGrid: [{
type: Input
}], ghostDragEnabled: [{
type: Input
}], showOriginalElementWhileDragging: [{
type: Input
}], validateDrag: [{
type: Input
}], dragCursor: [{
type: Input
}], dragActiveClass: [{
type: Input
}], ghostElementAppendTo: [{
type: Input
}], ghostElementTemplate: [{
type: Input
}], touchStartLongPress: [{
type: Input
}], autoScroll: [{
type: Input
}], dragPointerDown: [{
type: Output
}], dragStart: [{
type: Output
}], ghostElementCreated: [{
type: Output
}], dragging: [{
type: Output
}], dragEnd: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZ2dhYmxlLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZHJhZ2dhYmxlLWRyb3BwYWJsZS9zcmMvbGliL2RyYWdnYWJsZS5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFJVCxNQUFNLEVBQ04sWUFBWSxFQUNaLEtBQUssRUFLTCxNQUFNLEVBR04sUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxPQUFPLEVBQ1AsVUFBVSxFQUNWLEtBQUssRUFDTCxhQUFhLEVBQ2IsYUFBYSxFQUNiLFNBQVMsR0FDVixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFDTCxHQUFHLEVBQ0gsUUFBUSxFQUNSLFNBQVMsRUFDVCxJQUFJLEVBQ0osUUFBUSxFQUNSLFFBQVEsRUFDUixLQUFLLEVBQ0wsTUFBTSxFQUNOLEtBQUssRUFDTCxTQUFTLEdBQ1YsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxVQUFVLE1BQU0sK0JBQStCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxRQUFRLENBQUM7Ozs7QUEwRC9DLE1BQU0sT0FBTyxrQkFBa0I7SUFxSTdCOztPQUVHO0lBQ0gsWUFDVSxPQUFnQyxFQUNoQyxRQUFtQixFQUNuQixlQUFnQyxFQUNoQyxJQUFZLEVBQ1osR0FBcUIsRUFDVCxlQUFrRCxFQUM1QyxRQUFhO1FBTi9CLFlBQU8sR0FBUCxPQUFPLENBQXlCO1FBQ2hDLGFBQVEsR0FBUixRQUFRLENBQVc7UUFDbkIsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQ2hDLFNBQUksR0FBSixJQUFJLENBQVE7UUFDWixRQUFHLEdBQUgsR0FBRyxDQUFrQjtRQUNULG9CQUFlLEdBQWYsZUFBZSxDQUFt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