cedro
Version:
Javascript library to build user interfece based on widgets.
167 lines (130 loc) • 4.26 kB
text/typescript
import { OrientationTypes } from "../types/orientation.type";
import "./styles/draggable.css";
import { WidgetTypes } from "./widget.types";
import { Widget } from "./widget.ui";
export type DragOrientation = OrientationTypes | "both";
export class Draggable {
target: Widget;
background: Widget;
dragging: boolean = false;
dragDistX: number;
dragDistY: number;
dragOrientation: DragOrientation;
minX: number | null;
minY: number | null;
maxX: number | null;
maxY: number | null;
draggingClass: string | null;
constructor(widget: Widget, orientation: DragOrientation = "both") {
this.target = widget;
this.background = new Widget(this.target.id + ".Draggable.Background", "div", null);
this.background.setType(WidgetTypes.CUSTOM);
this.background.addClass("WUIDraggableBackground");
this.draggingClass = null;
this.dragDistX = 0;
this.dragDistY = 0;
this.maxX = null;
this.maxY = null;
this.minX = null;
this.minY = null;
this.dragOrientation = orientation;
this.target.subscribe({
event: "mousedown",
then: (e, _w) => {
this.startDrag(e as MouseEvent);
},
});
this.background.subscribe({
event: "mousemove",
then: (e, _w) => {
this.draggingTarget(e as MouseEvent);
},
});
this.background.subscribe({
event: "mouseup",
then: (_e, _w) => {
this.endDrag();
},
});
this.background.subscribe({
event: "mouseout",
then: (_e, _w) => {
this.endDrag();
},
});
this.background.subscribe({
event: "mouseleave",
then: (_e, _w) => {
this.endDrag();
},
});
this.background.setVisible(false);
}
public setBackgroundCursor(cursor: string): void {
this.background.getBody().style.cursor = cursor;
}
public setDraggingClass(draggingClass: string | null): void {
this.draggingClass = draggingClass;
}
private startDrag(e: MouseEvent): void {
e.preventDefault();
const mouseX = e.clientX;
const mouseY = e.clientY;
this.dragDistX = Math.abs(this.target.getX() - mouseX);
this.dragDistY = Math.abs(this.target.getY() - mouseY);
this.dragging = true;
this.background.setVisible(true);
this.background.raisteTop();
if (this.draggingClass) {
this.target.addClass(this.draggingClass);
}
}
private draggingTarget(e: MouseEvent): void {
if (!this.dragging) {
return;
}
e.preventDefault();
const mouseX = e.clientX;
const mouseY = e.clientY;
if (this.dragOrientation === "both" || this.dragOrientation === "horizontal") {
let newX = mouseX - this.dragDistX;
if (this.maxX != null && newX > this.maxX) {
newX = this.maxX;
}
if (this.minX != null && newX < this.minX) {
newX = this.minX;
}
this.target.setX(newX);
}
if (this.dragOrientation === "both" || this.dragOrientation === "vertical") {
let newY = mouseY - this.dragDistY;
if (this.maxY != null && newY > this.maxY) {
newY = this.maxY;
}
if (this.minY != null && newY < this.minY) {
newY = this.minY;
}
this.target.setY(newY);
}
this.target.run("drag");
}
private endDrag(): void {
this.dragging = false;
this.background.setVisible(false);
if (this.draggingClass) {
this.target.deleteClass(this.draggingClass);
}
}
public setMaxX(x: number | null): void {
this.maxX = x;
}
public setMaxY(y: number | null): void {
this.maxY = y;
}
public setMinX(x: number | null): void {
this.minX = x;
}
public setMinY(y: number | null): void {
this.minY = y;
}
}