405 lines
63 KiB
JavaScript
405 lines
63 KiB
JavaScript
|
import { DirTypes } from './gridsterConfig.interface';
|
||
|
import { GridsterPush } from './gridsterPush.service';
|
||
|
import { cancelScroll, scroll } from './gridsterScroll.service';
|
||
|
import { GridsterSwap } from './gridsterSwap.service';
|
||
|
import { GridsterUtils } from './gridsterUtils.service';
|
||
|
const GRIDSTER_ITEM_RESIZABLE_HANDLER_CLASS = 'gridster-item-resizable-handler';
|
||
|
var Direction;
|
||
|
(function (Direction) {
|
||
|
Direction["UP"] = "UP";
|
||
|
Direction["DOWN"] = "DOWN";
|
||
|
Direction["LEFT"] = "LEFT";
|
||
|
Direction["RIGHT"] = "RIGHT";
|
||
|
})(Direction || (Direction = {}));
|
||
|
export class GridsterDraggable {
|
||
|
constructor(gridsterItem, gridster, zone) {
|
||
|
this.zone = zone;
|
||
|
this.collision = false;
|
||
|
this.dragMove = (e) => {
|
||
|
e.stopPropagation();
|
||
|
e.preventDefault();
|
||
|
GridsterUtils.checkTouchEvent(e);
|
||
|
// get the directions of the mouse event
|
||
|
let directions = this.getDirections(e);
|
||
|
if (this.gridster.options.enableBoundaryControl) {
|
||
|
// prevent moving up at the top of gridster
|
||
|
if (directions.includes(Direction.UP) &&
|
||
|
this.gridsterItem.el.getBoundingClientRect().top <
|
||
|
this.gridster.el.getBoundingClientRect().top +
|
||
|
(this.outerMarginTop ?? this.margin)) {
|
||
|
directions = directions.filter(direction => direction != Direction.UP);
|
||
|
e = new MouseEvent(e.type, {
|
||
|
clientX: e.clientX,
|
||
|
clientY: this.lastMouse.clientY
|
||
|
});
|
||
|
}
|
||
|
// prevent moving left at the leftmost column of gridster
|
||
|
if (directions.includes(Direction.LEFT) &&
|
||
|
this.gridsterItem.el.getBoundingClientRect().left <
|
||
|
this.gridster.el.getBoundingClientRect().left +
|
||
|
(this.outerMarginLeft ?? this.margin)) {
|
||
|
directions = directions.filter(direction => direction != Direction.LEFT);
|
||
|
e = new MouseEvent(e.type, {
|
||
|
clientX: this.lastMouse.clientX,
|
||
|
clientY: e.clientY
|
||
|
});
|
||
|
}
|
||
|
// prevent moving right at the rightmost column of gridster
|
||
|
if (directions.includes(Direction.RIGHT) &&
|
||
|
this.gridsterItem.el.getBoundingClientRect().right >
|
||
|
this.gridster.el.getBoundingClientRect().right -
|
||
|
(this.outerMarginRight ?? this.margin)) {
|
||
|
directions = directions.filter(direction => direction != Direction.RIGHT);
|
||
|
e = new MouseEvent(e.type, {
|
||
|
clientX: this.lastMouse.clientX,
|
||
|
clientY: e.clientY
|
||
|
});
|
||
|
}
|
||
|
// prevent moving down at the bottom of gridster
|
||
|
if (directions.includes(Direction.DOWN) &&
|
||
|
this.gridsterItem.el.getBoundingClientRect().bottom >
|
||
|
this.gridster.el.getBoundingClientRect().bottom -
|
||
|
(this.outerMarginBottom ?? this.margin)) {
|
||
|
directions = directions.filter(direction => direction != Direction.DOWN);
|
||
|
e = new MouseEvent(e.type, {
|
||
|
clientX: e.clientX,
|
||
|
clientY: this.lastMouse.clientY
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
// do not change item location when there is no direction to go
|
||
|
if (directions.length) {
|
||
|
this.offsetLeft =
|
||
|
this.gridster.el.scrollLeft - this.gridster.el.offsetLeft;
|
||
|
this.offsetTop = this.gridster.el.scrollTop - this.gridster.el.offsetTop;
|
||
|
scroll(this.gridster, this.left, this.top, this.width, this.height, e, this.lastMouse, this.calculateItemPositionFromMousePosition);
|
||
|
this.calculateItemPositionFromMousePosition(e);
|
||
|
}
|
||
|
};
|
||
|
this.calculateItemPositionFromMousePosition = (e) => {
|
||
|
if (this.gridster.options.scale) {
|
||
|
this.calculateItemPositionWithScale(e, this.gridster.options.scale);
|
||
|
}
|
||
|
else {
|
||
|
this.calculateItemPositionWithoutScale(e);
|
||
|
}
|
||
|
this.calculateItemPosition();
|
||
|
this.lastMouse.clientX = e.clientX;
|
||
|
this.lastMouse.clientY = e.clientY;
|
||
|
this.zone.run(() => {
|
||
|
this.gridster.updateGrid();
|
||
|
});
|
||
|
};
|
||
|
this.dragStop = (e) => {
|
||
|
e.stopPropagation();
|
||
|
e.preventDefault();
|
||
|
cancelScroll();
|
||
|
this.cancelOnBlur();
|
||
|
this.mousemove();
|
||
|
this.mouseup();
|
||
|
this.mouseleave();
|
||
|
this.touchmove();
|
||
|
this.touchend();
|
||
|
this.touchcancel();
|
||
|
this.gridsterItem.renderer.removeClass(this.gridsterItem.el, 'gridster-item-moving');
|
||
|
this.gridster.dragInProgress = false;
|
||
|
this.gridster.updateGrid();
|
||
|
this.path = [];
|
||
|
if (this.gridster.options.draggable &&
|
||
|
this.gridster.options.draggable.stop) {
|
||
|
Promise.resolve(this.gridster.options.draggable.stop(this.gridsterItem.item, this.gridsterItem, e)).then(this.makeDrag, this.cancelDrag);
|
||
|
}
|
||
|
else {
|
||
|
this.makeDrag();
|
||
|
}
|
||
|
setTimeout(() => {
|
||
|
if (this.gridster) {
|
||
|
this.gridster.movingItem = null;
|
||
|
this.gridster.previewStyle(true);
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
this.cancelDrag = () => {
|
||
|
this.gridsterItem.$item.x = this.gridsterItem.item.x || 0;
|
||
|
this.gridsterItem.$item.y = this.gridsterItem.item.y || 0;
|
||
|
this.gridsterItem.setSize();
|
||
|
if (this.push) {
|
||
|
this.push.restoreItems();
|
||
|
}
|
||
|
if (this.swap) {
|
||
|
this.swap.restoreSwapItem();
|
||
|
}
|
||
|
if (this.push) {
|
||
|
this.push.destroy();
|
||
|
this.push = null;
|
||
|
}
|
||
|
if (this.swap) {
|
||
|
this.swap.destroy();
|
||
|
this.swap = null;
|
||
|
}
|
||
|
};
|
||
|
this.makeDrag = () => {
|
||
|
if (this.gridster.$options.draggable.dropOverItems &&
|
||
|
this.gridster.options.draggable &&
|
||
|
this.gridster.options.draggable.dropOverItemsCallback &&
|
||
|
this.collision &&
|
||
|
this.collision !== true &&
|
||
|
this.collision.$item) {
|
||
|
this.gridster.options.draggable.dropOverItemsCallback(this.gridsterItem.item, this.collision.item, this.gridster);
|
||
|
}
|
||
|
this.collision = false;
|
||
|
this.gridsterItem.setSize();
|
||
|
this.gridsterItem.checkItemChanges(this.gridsterItem.$item, this.gridsterItem.item);
|
||
|
if (this.push) {
|
||
|
this.push.setPushedItems();
|
||
|
}
|
||
|
if (this.swap) {
|
||
|
this.swap.setSwapItem();
|
||
|
}
|
||
|
if (this.push) {
|
||
|
this.push.destroy();
|
||
|
this.push = null;
|
||
|
}
|
||
|
if (this.swap) {
|
||
|
this.swap.destroy();
|
||
|
this.swap = null;
|
||
|
}
|
||
|
};
|
||
|
this.dragStartDelay = (e) => {
|
||
|
const target = e.target;
|
||
|
if (target.classList.contains(GRIDSTER_ITEM_RESIZABLE_HANDLER_CLASS)) {
|
||
|
return;
|
||
|
}
|
||
|
if (GridsterUtils.checkContentClassForEvent(this.gridster, e)) {
|
||
|
return;
|
||
|
}
|
||
|
GridsterUtils.checkTouchEvent(e);
|
||
|
if (!this.gridster.$options.draggable.delayStart) {
|
||
|
this.dragStart(e);
|
||
|
return;
|
||
|
}
|
||
|
const timeout = setTimeout(() => {
|
||
|
this.dragStart(e);
|
||
|
cancelDrag();
|
||
|
}, this.gridster.$options.draggable.delayStart);
|
||
|
const cancelMouse = this.gridsterItem.renderer.listen('document', 'mouseup', cancelDrag);
|
||
|
const cancelMouseLeave = this.gridsterItem.renderer.listen('document', 'mouseleave', cancelDrag);
|
||
|
const cancelOnBlur = this.gridsterItem.renderer.listen('window', 'blur', cancelDrag);
|
||
|
const cancelTouchMove = this.gridsterItem.renderer.listen('document', 'touchmove', cancelMove);
|
||
|
const cancelTouchEnd = this.gridsterItem.renderer.listen('document', 'touchend', cancelDrag);
|
||
|
const cancelTouchCancel = this.gridsterItem.renderer.listen('document', 'touchcancel', cancelDrag);
|
||
|
function cancelMove(eventMove) {
|
||
|
GridsterUtils.checkTouchEvent(eventMove);
|
||
|
if (Math.abs(eventMove.clientX - e.clientX) > 9 ||
|
||
|
Math.abs(eventMove.clientY - e.clientY) > 9) {
|
||
|
cancelDrag();
|
||
|
}
|
||
|
}
|
||
|
function cancelDrag() {
|
||
|
clearTimeout(timeout);
|
||
|
cancelOnBlur();
|
||
|
cancelMouse();
|
||
|
cancelMouseLeave();
|
||
|
cancelTouchMove();
|
||
|
cancelTouchEnd();
|
||
|
cancelTouchCancel();
|
||
|
}
|
||
|
};
|
||
|
this.gridsterItem = gridsterItem;
|
||
|
this.gridster = gridster;
|
||
|
this.lastMouse = {
|
||
|
clientX: 0,
|
||
|
clientY: 0
|
||
|
};
|
||
|
this.path = [];
|
||
|
}
|
||
|
destroy() {
|
||
|
if (this.gridster.previewStyle) {
|
||
|
this.gridster.previewStyle(true);
|
||
|
}
|
||
|
this.gridsterItem = this.gridster = this.collision = null;
|
||
|
if (this.mousedown) {
|
||
|
this.mousedown();
|
||
|
this.touchstart();
|
||
|
}
|
||
|
}
|
||
|
dragStart(e) {
|
||
|
if (e.which && e.which !== 1) {
|
||
|
return;
|
||
|
}
|
||
|
if (this.gridster.options.draggable &&
|
||
|
this.gridster.options.draggable.start) {
|
||
|
this.gridster.options.draggable.start(this.gridsterItem.item, this.gridsterItem, e);
|
||
|
}
|
||
|
e.stopPropagation();
|
||
|
e.preventDefault();
|
||
|
this.zone.runOutsideAngular(() => {
|
||
|
this.mousemove = this.gridsterItem.renderer.listen('document', 'mousemove', this.dragMove);
|
||
|
this.touchmove = this.gridster.renderer.listen(this.gridster.el, 'touchmove', this.dragMove);
|
||
|
});
|
||
|
this.mouseup = this.gridsterItem.renderer.listen('document', 'mouseup', this.dragStop);
|
||
|
this.mouseleave = this.gridsterItem.renderer.listen('document', 'mouseleave', this.dragStop);
|
||
|
this.cancelOnBlur = this.gridsterItem.renderer.listen('window', 'blur', this.dragStop);
|
||
|
this.touchend = this.gridsterItem.renderer.listen('document', 'touchend', this.dragStop);
|
||
|
this.touchcancel = this.gridsterItem.renderer.listen('document', 'touchcancel', this.dragStop);
|
||
|
this.gridsterItem.renderer.addClass(this.gridsterItem.el, 'gridster-item-moving');
|
||
|
this.margin = this.gridster.$options.margin;
|
||
|
this.outerMarginTop = this.gridster.$options.outerMarginTop;
|
||
|
this.outerMarginRight = this.gridster.$options.outerMarginRight;
|
||
|
this.outerMarginBottom = this.gridster.$options.outerMarginBottom;
|
||
|
this.outerMarginLeft = this.gridster.$options.outerMarginLeft;
|
||
|
this.offsetLeft = this.gridster.el.scrollLeft - this.gridster.el.offsetLeft;
|
||
|
this.offsetTop = this.gridster.el.scrollTop - this.gridster.el.offsetTop;
|
||
|
this.left = this.gridsterItem.left - this.margin;
|
||
|
this.top = this.gridsterItem.top - this.margin;
|
||
|
this.originalClientX = e.clientX;
|
||
|
this.originalClientY = e.clientY;
|
||
|
this.width = this.gridsterItem.width;
|
||
|
this.height = this.gridsterItem.height;
|
||
|
if (this.gridster.$options.dirType === DirTypes.RTL) {
|
||
|
this.diffLeft =
|
||
|
e.clientX - this.gridster.el.scrollWidth + this.gridsterItem.left;
|
||
|
}
|
||
|
else {
|
||
|
this.diffLeft = e.clientX + this.offsetLeft - this.margin - this.left;
|
||
|
}
|
||
|
this.diffTop = e.clientY + this.offsetTop - this.margin - this.top;
|
||
|
this.gridster.movingItem = this.gridsterItem.$item;
|
||
|
this.gridster.previewStyle(true);
|
||
|
this.push = new GridsterPush(this.gridsterItem);
|
||
|
this.swap = new GridsterSwap(this.gridsterItem);
|
||
|
this.gridster.dragInProgress = true;
|
||
|
this.gridster.updateGrid();
|
||
|
this.path.push({
|
||
|
x: this.gridsterItem.item.x || 0,
|
||
|
y: this.gridsterItem.item.y || 0
|
||
|
});
|
||
|
}
|
||
|
calculateItemPositionWithScale(e, scale) {
|
||
|
if (this.gridster.$options.dirType === DirTypes.RTL) {
|
||
|
this.left =
|
||
|
this.gridster.el.scrollWidth -
|
||
|
this.originalClientX +
|
||
|
(e.clientX - this.originalClientX) / scale +
|
||
|
this.diffLeft;
|
||
|
}
|
||
|
else {
|
||
|
this.left =
|
||
|
this.originalClientX +
|
||
|
(e.clientX - this.originalClientX) / scale +
|
||
|
this.offsetLeft -
|
||
|
this.diffLeft;
|
||
|
}
|
||
|
this.top =
|
||
|
this.originalClientY +
|
||
|
(e.clientY - this.originalClientY) / scale +
|
||
|
this.offsetTop -
|
||
|
this.diffTop;
|
||
|
}
|
||
|
calculateItemPositionWithoutScale(e) {
|
||
|
if (this.gridster.$options.dirType === DirTypes.RTL) {
|
||
|
this.left = this.gridster.el.scrollWidth - e.clientX + this.diffLeft;
|
||
|
}
|
||
|
else {
|
||
|
this.left = e.clientX + this.offsetLeft - this.diffLeft;
|
||
|
}
|
||
|
this.top = e.clientY + this.offsetTop - this.diffTop;
|
||
|
}
|
||
|
calculateItemPosition() {
|
||
|
this.gridster.movingItem = this.gridsterItem.$item;
|
||
|
this.positionX = this.gridster.pixelsToPositionX(this.left, Math.round);
|
||
|
this.positionY = this.gridster.pixelsToPositionY(this.top, Math.round);
|
||
|
this.positionXBackup = this.gridsterItem.$item.x;
|
||
|
this.positionYBackup = this.gridsterItem.$item.y;
|
||
|
this.gridsterItem.$item.x = this.positionX;
|
||
|
if (this.gridster.checkGridCollision(this.gridsterItem.$item)) {
|
||
|
this.gridsterItem.$item.x = this.positionXBackup;
|
||
|
}
|
||
|
this.gridsterItem.$item.y = this.positionY;
|
||
|
if (this.gridster.checkGridCollision(this.gridsterItem.$item)) {
|
||
|
this.gridsterItem.$item.y = this.positionYBackup;
|
||
|
}
|
||
|
this.gridster.gridRenderer.setCellPosition(this.gridsterItem.renderer, this.gridsterItem.el, this.left, this.top);
|
||
|
if (this.positionXBackup !== this.gridsterItem.$item.x ||
|
||
|
this.positionYBackup !== this.gridsterItem.$item.y) {
|
||
|
const lastPosition = this.path[this.path.length - 1];
|
||
|
let direction = '';
|
||
|
if (lastPosition.x < this.gridsterItem.$item.x) {
|
||
|
direction = this.push.fromWest;
|
||
|
}
|
||
|
else if (lastPosition.x > this.gridsterItem.$item.x) {
|
||
|
direction = this.push.fromEast;
|
||
|
}
|
||
|
else if (lastPosition.y < this.gridsterItem.$item.y) {
|
||
|
direction = this.push.fromNorth;
|
||
|
}
|
||
|
else if (lastPosition.y > this.gridsterItem.$item.y) {
|
||
|
direction = this.push.fromSouth;
|
||
|
}
|
||
|
this.push.pushItems(direction, this.gridster.$options.disablePushOnDrag);
|
||
|
this.swap.swapItems();
|
||
|
this.collision = this.gridster.checkCollision(this.gridsterItem.$item);
|
||
|
if (this.collision) {
|
||
|
this.gridsterItem.$item.x = this.positionXBackup;
|
||
|
this.gridsterItem.$item.y = this.positionYBackup;
|
||
|
if (this.gridster.$options.draggable.dropOverItems &&
|
||
|
this.collision !== true &&
|
||
|
this.collision.$item) {
|
||
|
this.gridster.movingItem = null;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
this.path.push({
|
||
|
x: this.gridsterItem.$item.x,
|
||
|
y: this.gridsterItem.$item.y
|
||
|
});
|
||
|
}
|
||
|
this.push.checkPushBack();
|
||
|
}
|
||
|
else {
|
||
|
// reset the collision when you drag and drop on an adjacent cell that is not empty
|
||
|
// and go back to the cell you were in from the beginning,
|
||
|
// this is to prevent `dropOverItemsCallback'
|
||
|
this.collision = false;
|
||
|
}
|
||
|
this.gridster.previewStyle(true);
|
||
|
}
|
||
|
toggle() {
|
||
|
const enableDrag = this.gridsterItem.canBeDragged();
|
||
|
if (!this.enabled && enableDrag) {
|
||
|
this.enabled = !this.enabled;
|
||
|
this.mousedown = this.gridsterItem.renderer.listen(this.gridsterItem.el, 'mousedown', this.dragStartDelay);
|
||
|
this.touchstart = this.gridsterItem.renderer.listen(this.gridsterItem.el, 'touchstart', this.dragStartDelay);
|
||
|
}
|
||
|
else if (this.enabled && !enableDrag) {
|
||
|
this.enabled = !this.enabled;
|
||
|
this.mousedown();
|
||
|
this.touchstart();
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Returns the list of directions for given mouse event
|
||
|
* @param e Mouse event
|
||
|
* */
|
||
|
getDirections(e) {
|
||
|
const directions = [];
|
||
|
if (this.lastMouse.clientX === 0 && this.lastMouse.clientY === 0) {
|
||
|
this.lastMouse.clientY = e.clientY;
|
||
|
this.lastMouse.clientX = e.clientX;
|
||
|
}
|
||
|
if (this.lastMouse.clientY > e.clientY) {
|
||
|
directions.push(Direction.UP);
|
||
|
}
|
||
|
if (this.lastMouse.clientY < e.clientY) {
|
||
|
directions.push(Direction.DOWN);
|
||
|
}
|
||
|
if (this.lastMouse.clientX < e.clientX) {
|
||
|
directions.push(Direction.RIGHT);
|
||
|
}
|
||
|
if (this.lastMouse.clientX > e.clientX) {
|
||
|
directions.push(Direction.LEFT);
|
||
|
}
|
||
|
return directions;
|
||
|
}
|
||
|
}
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZHN0ZXJEcmFnZ2FibGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZ3JpZHN0ZXIyL3NyYy9saWIvZ3JpZHN0ZXJEcmFnZ2FibGUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFaEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV4RCxNQUFNLHFDQUFxQyxHQUFHLGlDQUFpQyxDQUFDO0FBRWhGLElBQUssU0FLSjtBQUxELFdBQUssU0FBUztJQUNaLHNCQUFTLENBQUE7SUFDVCwwQkFBYSxDQUFBO0lBQ2IsMEJBQWEsQ0FBQTtJQUNiLDRCQUFlLENBQUE7QUFDakIsQ0FBQyxFQUxJLFNBQVMsS0FBVCxTQUFTLFFBS2I7QUFFRCxNQUFNLE9BQU8saUJBQWlCO0lBeUM1QixZQUNFLFlBQTRDLEVBQzVDLFFBQW9DLEVBQzVCLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFRO1FBTHRCLGNBQVMsR0FBNkMsS0FBSyxDQUFDO1FBdUg1RCxhQUFRLEdBQUcsQ0FBQyxDQUFhLEVBQVEsRUFBRTtZQUNqQyxDQUFDLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDcEIsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ25CLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFakMsd0NBQXdDO1lBQ3hDLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFdkMs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
|