ngx-drag-and-drop
Version:
Angular library that allow you to build drag and drop without the native HTML5 API
606 lines (599 loc) • 21.8 kB
JavaScript
import { __decorate } from 'tslib';
import { HostListener, Directive, EventEmitter, ElementRef, Input, Output, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
var myDoc = document;
myDoc.elementsFromPoint = myDoc.elementsFromPoint || function (x, y) {
var element;
var old_visibility = [];
var elements = [];
while (true) {
element = document.elementFromPoint(x, y);
if (!element || element === document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
return elements;
};
/*
interface ShadowRoot extends DocumentFragment {
styleSheets : StyleSheetList;
innerHTML : string;
host : Element;
activeElement : Element;
elementFromPoint (x : number, y : number) : Element;
elementsFromPoint (x : number, y : number) : Element[];
caretPositionFromPoint (x : number, y : number); // => CaretPosition
};
interface ElementWithShadowRoot extends HTMLElement {
shadowRoot : ShadowRoot;
};*/
var dragPointerId = 'dragPointer';
var DragManager = /** @class */ (function () {
function DragManager() {
this.draggingPointer = new Map();
this.draggedStructures = new Map();
this.dropZones = new Map();
}
DragManager.prototype.preStartDrag = function (idPointer, x, y, delay, dist) {
var _this = this;
this.draggingPointer.set(idPointer, { x: x, y: y });
return new Promise(function (resolve, reject) {
setTimeout(function () {
var ptr = _this.draggingPointer.get(idPointer);
var gogo = ptr && (Math.abs(x - ptr.x) + Math.abs(y - ptr.y)) < dist;
_this.draggingPointer.delete(idPointer);
gogo ? resolve() : reject();
}, Math.max(0, delay));
});
};
DragManager.prototype.startDrag = function (idPointer, dragged) {
this.draggedStructures.set(idPointer, dragged);
var possibleDropZones = new Map();
this.dropZones.forEach(function (dz) {
if (dz.checkAccept(dragged)) {
dz.appendDropCandidatePointer(idPointer);
possibleDropZones.set(dz.root, dz);
}
});
return possibleDropZones;
};
DragManager.prototype.isAssociatedToDropZone = function (element) {
return this.dropZones.has(element);
};
DragManager.prototype.registerDropZone = function (dropzone) {
this.dropZones.set(dropzone.root, dropzone);
};
DragManager.prototype.unregisterDropZone = function (dropzone) {
this.dropZones.delete(dropzone.root);
};
DragManager.prototype.pointerMove = function (idPointer, x, y) {
var ptr = this.draggingPointer.get(idPointer);
if (ptr) {
ptr.x = x;
ptr.y = y;
}
var dragged = this.draggedStructures.get(idPointer);
if (dragged && dragged instanceof Draggable) {
dragged.move(x, y);
}
return dragged !== undefined;
};
DragManager.prototype.pointerRelease = function (idPointer) {
var dragged = this.draggedStructures.get(idPointer);
if (dragged) {
if (dragged instanceof Draggable) {
dragged.stop();
}
}
this.draggedStructures.delete(idPointer);
this.draggingPointer.delete(idPointer);
return dragged !== undefined;
};
return DragManager;
}());
var DM = new DragManager();
var dragDropInit = false;
var DragDrop = /** @class */ (function () {
function DragDrop() {
this.nbDragEnter = 0;
if (dragDropInit) {
console.error('Do not create multiple instance of directive drag-and-drop-wrapper !');
}
else {
dragDropInit = true;
}
}
DragDrop.prototype.removeFeedbackForDragPointer = function () {
this.nbDragEnter = 0;
DM.dropZones.forEach(function (dz) {
dz.removePointerHover(dragPointerId);
dz.removeDropCandidatePointer(dragPointerId);
});
};
DragDrop.prototype.drop = function (e) {
e.preventDefault();
e.stopPropagation();
this.removeFeedbackForDragPointer();
};
DragDrop.prototype.dragover = function (e) {
e.preventDefault();
e.stopPropagation();
};
DragDrop.prototype.dragenter = function (e) {
this.nbDragEnter++;
if (this.nbDragEnter === 1) {
DM.startDrag(dragPointerId, e);
}
};
DragDrop.prototype.dragleave = function (e) {
this.nbDragEnter--;
if (this.nbDragEnter === 0) {
this.removeFeedbackForDragPointer();
DM.pointerRelease(dragPointerId);
}
};
DragDrop.prototype.dragend = function (e) {
DM.pointerRelease(dragPointerId);
this.removeFeedbackForDragPointer();
e.preventDefault();
};
DragDrop.prototype.mousemove = function (e) {
DM.pointerMove('mouse', e.clientX, e.clientY);
};
DragDrop.prototype.mouseup = function (e) {
DM.pointerRelease('mouse');
};
DragDrop.prototype.touchmove = function (e) {
for (var i = 0; i < e.changedTouches.length; i++) {
var touch = e.changedTouches.item(i);
if (DM.pointerMove(touch.identifier.toString(), touch.clientX, touch.clientY)) {
e.preventDefault();
e.stopPropagation();
}
}
};
DragDrop.prototype.touchend = function (e) {
for (var i = 0; i < e.changedTouches.length; i++) {
var touch = e.changedTouches.item(i);
if (DM.pointerRelease(touch.identifier.toString())) {
e.preventDefault();
e.stopPropagation();
}
}
};
__decorate([
HostListener('document: drop', ['$event'])
], DragDrop.prototype, "drop", null);
__decorate([
HostListener('document: dragover', ['$event'])
], DragDrop.prototype, "dragover", null);
__decorate([
HostListener('document: dragenter', ['$event'])
], DragDrop.prototype, "dragenter", null);
__decorate([
HostListener('document: dragleave', ['$event'])
], DragDrop.prototype, "dragleave", null);
__decorate([
HostListener('document: dragend', ['$event'])
], DragDrop.prototype, "dragend", null);
__decorate([
HostListener('document: mousemove', ['$event'])
], DragDrop.prototype, "mousemove", null);
__decorate([
HostListener('document: mouseup', ['$event'])
], DragDrop.prototype, "mouseup", null);
__decorate([
HostListener('document: touchmove', ['$event'])
], DragDrop.prototype, "touchmove", null);
__decorate([
HostListener('document: touchend', ['$event'])
], DragDrop.prototype, "touchend", null);
DragDrop = __decorate([
Directive({
selector: '*[drag-and-drop-wrapper]'
})
], DragDrop);
return DragDrop;
}());
var offsetElement = function (element) {
var left = 0, top = 0;
while (element) {
top += element.offsetTop - element.scrollTop + element.clientTop;
left += element.offsetLeft - element.scrollLeft + element.clientLeft;
element = element.offsetParent;
}
return { left: left, top: top };
};
var ɵ0 = offsetElement;
var Draggable = /** @class */ (function () {
function Draggable(el) {
this.disabled = false;
this.onDragStart = new EventEmitter();
this.onDragEnd = new EventEmitter();
this.isBeingDragged = false;
this.cloneNode = null;
this.possibleDropZones = new Map();
this.root = el.nativeElement;
if (!dragDropInit) {
console.error('You should add one dragdrop attribute to your code before using draggable');
}
}
Draggable.prototype.ngOnInit = function () {
//
};
Draggable.prototype.ngOnDestroy = function () {
// XXX No stop in case of unplug while dragging... : // this.stop();
};
Draggable.prototype.onMouseDown = function (event) {
if (!this.disabled) {
event.preventDefault();
event.stopPropagation();
this.prestart('mouse', event.clientX, event.clientY);
}
};
Draggable.prototype.onTouchStart = function (event) {
event.stopPropagation();
for (var i = 0; i < event.changedTouches.length; i++) {
var touch = event.changedTouches.item(i);
this.prestart(touch.identifier.toString(), touch.clientX, touch.clientY);
}
};
Draggable.prototype.prestart = function (idPointer, x, y) {
var _this = this;
DM.preStartDrag(idPointer, x, y, this.startDelay || 0, this.startDistance || 10).then(function () {
_this.start(idPointer, x, y);
}, function () {
// console.error('skip the drag');
});
};
Draggable.prototype.start = function (idPointer, x, y) {
if (!this.isBeingDragged) {
this.isBeingDragged = true;
this.idPointer = idPointer;
var offset = offsetElement(this.root);
this.ox = x;
this.oy = y;
this.dx = x - offset.left;
this.dy = y - offset.top;
this.tx = this.root.offsetWidth;
this.ty = this.root.offsetHeight;
this.getClone();
this.cloneNode.style.left = (x - this.dx) + 'px';
this.cloneNode.style.top = (y - this.dy) + 'px';
this.onDragStart.emit(this.draggedData);
this.possibleDropZones = DM.startDrag(idPointer, this);
}
};
Draggable.prototype.stop = function () {
var _this = this;
this.possibleDropZones.forEach(function (dz) {
dz.removePointerHover(_this.idPointer);
dz.removeDropCandidatePointer(_this.idPointer);
});
this.isBeingDragged = false;
this.possibleDropZones.clear();
this.idPointer = null;
if (this.currentDropZone) {
this.currentDropZone.drop(this.draggedData);
}
this.currentDropZone = null;
this.onDragEnd.emit(this.draggedData);
this.deleteClone();
};
Draggable.prototype.move = function (x, y) {
var element = null;
if (this.cloneNode === null) {
this.getClone();
}
if (this.cloneNode) {
this.cloneNode.style.left = (x - this.dx) + 'px';
this.cloneNode.style.top = (y - this.dy) + 'px';
var visibility = this.cloneNode.style.visibility;
this.cloneNode.style.visibility = 'hidden';
var top_1 = this.cloneNode.style.top;
this.cloneNode.style.top = '999999999px';
element = myDoc.elementFromPoint(x, y);
this.cloneNode.style.top = top_1;
this.cloneNode.style.visibility = visibility;
var prevDropZone = this.currentDropZone;
while (element) {
this.currentDropZone = this.possibleDropZones.get(element);
if (this.currentDropZone) {
break;
}
element = element.parentElement;
}
if (prevDropZone !== this.currentDropZone) {
if (prevDropZone) {
prevDropZone.removePointerHover(this.idPointer);
}
if (this.currentDropZone) {
this.currentDropZone.appendPointerHover(this.idPointer);
}
}
}
return this;
};
Draggable.prototype.deepStyle = function (original, clone) {
if (original instanceof HTMLElement) {
var style = window.getComputedStyle(original);
for (var i = 0; i < style.length; i++) {
var att = style[i];
clone.style[att] = style[att];
}
for (var i = 0; i < original.children.length; i++) {
this.deepStyle(original.children.item(i), clone.children.item(i));
}
}
};
Draggable.prototype.deleteClone = function () {
if (this.cloneNode) {
if (this.cloneNode.parentNode) {
this.cloneNode.parentNode.removeChild(this.cloneNode);
}
this.cloneNode = null;
}
};
Draggable.prototype.getClone = function () {
if (this.cloneNode === null) {
this.cloneNode = this.root.cloneNode(true);
this.deepStyle(this.root, this.cloneNode);
document.body.appendChild(this.cloneNode);
this.cloneNode.style.position = 'absolute';
this.cloneNode.style.zIndex = '999';
this.cloneNode.style.marginLeft = '0';
this.cloneNode.style.marginTop = '0';
this.cloneNode.style.marginRight = '0';
this.cloneNode.style.marginBottom = '0';
this.cloneNode.style.opacity = '';
this.cloneNode.style.cursor = '';
this.cloneNode.style.transform = '';
this.cloneNode.style.transformOrigin = '';
this.cloneNode.style.animation = '';
this.cloneNode.style.transition = '';
this.cloneNode.classList.add('drag-and-drop-clone-node');
}
return this.cloneNode;
};
Draggable.ctorParameters = function () { return [
{ type: ElementRef }
]; };
__decorate([
Input('draggable')
], Draggable.prototype, "draggedData", void 0);
__decorate([
Input('drag-start-delay')
], Draggable.prototype, "startDelay", void 0);
__decorate([
Input('start-distance')
], Draggable.prototype, "startDistance", void 0);
__decorate([
Input('disabled')
], Draggable.prototype, "disabled", void 0);
__decorate([
Output('drag-start')
], Draggable.prototype, "onDragStart", void 0);
__decorate([
Output('drag-end')
], Draggable.prototype, "onDragEnd", void 0);
__decorate([
HostListener('mousedown', ['$event'])
], Draggable.prototype, "onMouseDown", null);
__decorate([
HostListener('touchstart', ['$event'])
], Draggable.prototype, "onTouchStart", null);
Draggable = __decorate([
Directive({
selector: '*[draggable]'
})
], Draggable);
return Draggable;
}());
var Dropzone = /** @class */ (function () {
function Dropzone(el) {
this.nbDragEnter = 0;
this.onDropEmitter = new EventEmitter();
this.onDragStart = new EventEmitter();
this.onDragEnd = new EventEmitter();
this.onDragEnter = new EventEmitter();
this.onDragLeave = new EventEmitter();
this.dropCandidateofPointers = [];
this.pointersHover = [];
if (!dragDropInit) {
console.error('You should add one dragdrop attribute to your code before using dropzone');
}
this.root = el.nativeElement;
DM.registerDropZone(this);
}
Dropzone.prototype.ngOnInit = function () {
//
};
Dropzone.prototype.ngOnDestroy = function () {
DM.unregisterDropZone(this);
};
Dropzone.prototype.BrowserDragEnter = function (event) {
this.nbDragEnter++;
if (this.nbDragEnter === 1) {
this.appendPointerHover(dragPointerId);
}
};
Dropzone.prototype.BrowserDragLeave = function (event) {
this.nbDragEnter--;
if (this.nbDragEnter === 0) {
this.removePointerHover(dragPointerId);
}
};
Dropzone.prototype.BrowserDrop = function (event) {
DM.pointerRelease(dragPointerId);
this.nbDragEnter = 0;
this.onDropEmitter.emit(event);
};
Dropzone.prototype.drop = function (obj) {
this.onDropEmitter.emit(obj);
};
Dropzone.prototype.checkAccept = function (drag) {
var res;
if (drag instanceof Draggable) {
res = this.acceptFunction ? this.acceptFunction(drag.draggedData) : true;
}
else {
res = this.acceptFunction ? this.acceptFunction(drag) : true;
}
return res;
};
Dropzone.prototype.hasPointerHover = function (idPointer) {
return this.pointersHover.indexOf(idPointer) >= 0;
};
Dropzone.prototype.appendPointerHover = function (idPointer) {
if (this.pointersHover.indexOf(idPointer) === -1) {
var dragged = DM.draggedStructures.get(idPointer);
this.pointersHover.push(idPointer);
if (dragged instanceof Draggable) {
if (this.dragOverCSS_pointer) {
dragged.getClone().classList.add(this.dragOverCSS_pointer);
}
this.onDragEnter.emit(dragged.draggedData);
}
else {
this.onDragEnter.emit(dragged);
}
if (this.dragOverCSS) {
this.root.classList.add(this.dragOverCSS);
}
}
};
Dropzone.prototype.removePointerHover = function (idPointer) {
var pos = this.pointersHover.indexOf(idPointer);
if (pos >= 0) {
var dragged = DM.draggedStructures.get(idPointer);
this.pointersHover.splice(pos, 1);
if (dragged instanceof Draggable) {
if (this.dragOverCSS_pointer) {
dragged.getClone().classList.remove(this.dragOverCSS_pointer);
}
this.onDragLeave.emit(dragged.draggedData);
}
else {
this.onDragLeave.emit(dragged);
}
if (this.pointersHover.length === 0 && this.dragOverCSS) {
this.root.classList.remove(this.dragOverCSS);
}
}
};
Dropzone.prototype.appendDropCandidatePointer = function (idPointer) {
if (this.dropCandidateofPointers.indexOf(idPointer) === -1) {
var dragged = DM.draggedStructures.get(idPointer);
if (dragged instanceof Draggable) {
this.onDragStart.emit(dragged.draggedData);
}
else {
this.onDragStart.emit(dragged);
}
this.dropCandidateofPointers.push(idPointer);
if (this.dragCSS) {
this.root.classList.add(this.dragCSS);
}
}
};
Dropzone.prototype.removeDropCandidatePointer = function (idPointer) {
var pos = this.dropCandidateofPointers.indexOf(idPointer);
if (pos >= 0) {
var dragged = DM.draggedStructures.get(idPointer);
if (dragged instanceof Draggable) {
this.onDragEnd.emit(dragged.draggedData);
}
else {
this.onDragEnd.emit(dragged);
}
this.dropCandidateofPointers.splice(pos, 1);
if (this.dropCandidateofPointers.length === 0 && this.dragCSS) {
this.root.classList.remove(this.dragCSS);
}
}
};
Dropzone.ctorParameters = function () { return [
{ type: ElementRef }
]; };
__decorate([
Input('drag-css')
], Dropzone.prototype, "dragCSS", void 0);
__decorate([
Input('drag-over-css')
], Dropzone.prototype, "dragOverCSS", void 0);
__decorate([
Input('drag-over-css-for-draggable')
], Dropzone.prototype, "dragOverCSS_pointer", void 0);
__decorate([
Input('accept-function')
], Dropzone.prototype, "acceptFunction", void 0);
__decorate([
Output('ondrop')
], Dropzone.prototype, "onDropEmitter", void 0);
__decorate([
Output('drag-start')
], Dropzone.prototype, "onDragStart", void 0);
__decorate([
Output('drag-end')
], Dropzone.prototype, "onDragEnd", void 0);
__decorate([
Output('drag-enter')
], Dropzone.prototype, "onDragEnter", void 0);
__decorate([
Output('drag-leave')
], Dropzone.prototype, "onDragLeave", void 0);
__decorate([
HostListener('dragenter', ['$event'])
], Dropzone.prototype, "BrowserDragEnter", null);
__decorate([
HostListener('dragleave', ['$event'])
], Dropzone.prototype, "BrowserDragLeave", null);
__decorate([
HostListener('drop', ['$event'])
], Dropzone.prototype, "BrowserDrop", null);
Dropzone = __decorate([
Directive({ selector: '*[dropzone]' })
], Dropzone);
return Dropzone;
}());
var NgxDragAndDropModule = /** @class */ (function () {
function NgxDragAndDropModule() {
}
NgxDragAndDropModule_1 = NgxDragAndDropModule;
NgxDragAndDropModule.forRoot = function () {
return {
ngModule: NgxDragAndDropModule_1,
providers: []
};
};
var NgxDragAndDropModule_1;
NgxDragAndDropModule = NgxDragAndDropModule_1 = __decorate([
NgModule({
imports: [
CommonModule,
],
declarations: [
Draggable,
Dropzone,
DragDrop,
],
exports: [
Draggable,
Dropzone,
DragDrop,
]
})
], NgxDragAndDropModule);
return NgxDragAndDropModule;
}());
/**
* Generated bundle index. Do not edit.
*/
export { NgxDragAndDropModule, DragDrop as ɵa, Draggable as ɵb, Dropzone as ɵc };
//# sourceMappingURL=ngx-drag-and-drop.js.map