UNPKG

verstak

Version:
383 lines (382 loc) 14.6 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { options, reactive, atomic, observable, Transaction, LoggingLevel } from "reactronic"; import { findTargetElementData, SymDataForSensor } from "./DataForSensor.js"; import { HtmlElementSensor } from "./HtmlElementSensor.js"; import { extractModifierKeys, KeyboardModifiers } from "./KeyboardSensor.js"; export class HtmlDragSensor extends HtmlElementSensor { constructor(element, windowSensor) { super(element, windowSensor); this.draggable = undefined; this.dragSource = undefined; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.dragStarted = false; this.dragFinished = false; this.startX = Infinity; this.startY = Infinity; this.dataByFormat = new Map(); this.draggingImage = undefined; this.draggingImageX = Infinity; this.draggingImageY = Infinity; this.dropEffect = "none"; this.dataTypesAllowed = []; this.effectAllowed = "uninitialized"; this.dropAllowed = false; this.draggingOver = false; this.draggingDataTypes = []; this.positionX = Infinity; this.positionY = Infinity; this.modifiers = KeyboardModifiers.none; this.dropX = Infinity; this.dropY = Infinity; this.dropped = false; this.immediatePositionX = Infinity; this.immediatePositionY = Infinity; this.immediateModifiers = KeyboardModifiers.none; } getData(format) { return this.dataByFormat.get(format); } setData(format, value) { this.dataByFormat.set(format, value); } clearData(format) { if (format) this.dataByFormat.delete(format); else this.dataByFormat.clear(); } setDragImage(value, x, y) { this.draggingImage = value; this.draggingImageX = x; this.draggingImageY = y; } listen(enabled = true) { const t = Transaction.current; Transaction.outside(() => { t.whenFinished(true).then(() => { const element = this.sourceElement; if (enabled) { element.addEventListener("dragstart", this.onDragStart.bind(this), { capture: true }); element.addEventListener("drag", this.onDrag.bind(this), { capture: true }); element.addEventListener("dragenter", this.onDragEnter.bind(this), { capture: false }); element.addEventListener("dragleave", this.onDragLeave.bind(this), { capture: false }); element.addEventListener("dragover", this.onDragOver.bind(this), { capture: true }); element.addEventListener("drop", this.onDrop.bind(this), { capture: true }); element.addEventListener("dragend", this.onDragEnd.bind(this), { capture: true }); } else { element.removeEventListener("dragstart", this.onDragStart.bind(this), { capture: true }); element.removeEventListener("drag", this.onDrag.bind(this), { capture: true }); element.removeEventListener("dragenter", this.onDragEnter.bind(this), { capture: false }); element.removeEventListener("dragleave", this.onDragLeave.bind(this), { capture: false }); element.removeEventListener("dragover", this.onDragOver.bind(this), { capture: true }); element.removeEventListener("drop", this.onDrop.bind(this), { capture: true }); element.removeEventListener("dragend", this.onDragEnd.bind(this), { capture: true }); } }, e => { }); }); } onDragStart(e) { this.startDragging(e); this.updateEventOnDragStart(e); } onDrag(e) { this.dragging(e); } onDragEnter(e) { this.enterTarget(e); this.updateEventOnDropAllowed(e); } onDragLeave(e) { this.leaveTarget(e); } onDragOver(e) { this.dragOver(e); this.updateEventOnDropAllowed(e); } onDrop(e) { this.drop(e); } onDragEnd(e) { this.finishDragging(e); this.reset(); } startDragging(e) { var _a; this.preventDefault = false; this.stopPropagation = false; const targetPath = e.composedPath(); const underPointer = document.elementsFromPoint(e.clientX, e.clientY); const { data, window } = findTargetElementData(targetPath, underPointer, SymDataForSensor, ["htmlDraggable"]); this.draggable = data === null || data === void 0 ? void 0 : data.htmlDraggable; this.dragSource = (_a = findTargetElementData(targetPath, underPointer, SymDataForSensor, ["htmlDrag"], true).data) === null || _a === void 0 ? void 0 : _a.htmlDrag; this.dragStarted = true; this.dragFinished = false; this.startX = e.clientX; this.startY = e.clientY; this.modifiers = extractModifierKeys(e); this.positionX = e.clientX; this.positionY = e.clientY; this.dropped = false; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.revision++; Transaction.isolate(() => { var _a; (_a = this.windowSensor) === null || _a === void 0 ? void 0 : _a.setActiveWindow(window, "htmlDrag"); }); } dragging(e) { this.dragStarted = true; this.dragFinished = false; this.revision++; } finishDragging(e) { this.dragFinished = true; this.revision++; } enterTarget(e) { this.updateDragTarget(e); this.dropped = false; this.revision++; } leaveTarget(e) { } dragOver(e) { this.updateDragTarget(e); this.dropped = false; this.revision++; } drop(e) { this.updateDragTarget(e); this.modifiers = this.immediateModifiers; this.dropX = e.clientX; this.dropY = e.clientY; this.dropped = true; const dt = e.dataTransfer; if (dt) { let dataByFormat = this.dataByFormat; dt.types.forEach(type => { if (!dataByFormat.has(type)) { const data = dt.getData(type); if (data !== "") { this.dataByFormat = dataByFormat = dataByFormat.toMutable(); dataByFormat.set(type, data); } } }); } this.revision++; } updateEventOnDragStart(e) { const dt = e.dataTransfer; if (dt) { dt.dropEffect = this.dropEffect; dt.effectAllowed = this.effectAllowed; this.dataByFormat.forEach((data, format) => { if (typeof data === "string") dt.setData(format, data); }); if (this.draggingImage) { dt.setDragImage(this.draggingImage, this.draggingImageX, this.draggingImageY); } } } updateEventOnDropAllowed(e) { if (this.dropAllowed) e.preventDefault(); } reset() { this.draggable = undefined; this.dragSource = undefined; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.dragStarted = false; this.dragFinished = false; this.startX = Infinity; this.startY = Infinity; this.dataByFormat.clear(); this.draggingImage = undefined; this.draggingImageX = Infinity; this.draggingImageY = Infinity; this.dropEffect = "none"; this.dataTypesAllowed = []; this.effectAllowed = "uninitialized"; this.dropAllowed = false; this.draggingOver = false; this.draggingDataTypes = []; this.positionX = Infinity; this.positionY = Infinity; this.modifiers = KeyboardModifiers.none; this.dropX = Infinity; this.dropY = Infinity; this.dropped = false; this.immediatePositionX = Infinity; this.immediatePositionY = Infinity; this.immediateModifiers = KeyboardModifiers.none; this.revision++; } updateDragTarget(e) { var _a; const targetPath = e.composedPath(); const underPointer = document.elementsFromPoint(e.clientX, e.clientY); const { data, window } = findTargetElementData(targetPath, underPointer, SymDataForSensor, ["htmlDrag"]); const dragTarget = data === null || data === void 0 ? void 0 : data.htmlDrag; if (dragTarget !== this.dragTarget) { this.previousDragTarget = this.dragTarget; this.dragTarget = dragTarget; this.dragTargetWindow = window; } const types = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.types; if (types) { if (!areEqualArrays(types, this.draggingDataTypes)) { const draggingDataTypes = new Array(); for (let i = 0; i < types.length; i++) draggingDataTypes.push(types[i]); this.draggingDataTypes = draggingDataTypes; } } this.immediateModifiers = extractModifierKeys(e); this.immediatePositionX = e.clientX; this.immediatePositionY = e.clientY; this.draggingOver = true; } whenDragging() { if (this.draggingOver) { this.positionX = this.immediatePositionX; this.positionY = this.immediatePositionY; this.modifiers = this.immediateModifiers; } } } __decorate([ observable(false), __metadata("design:type", Map) ], HtmlDragSensor.prototype, "dataByFormat", void 0); __decorate([ observable(false), __metadata("design:type", Object) ], HtmlDragSensor.prototype, "draggingImage", void 0); __decorate([ observable(false), __metadata("design:type", Number) ], HtmlDragSensor.prototype, "draggingImageX", void 0); __decorate([ observable(false), __metadata("design:type", Number) ], HtmlDragSensor.prototype, "draggingImageY", void 0); __decorate([ observable(false), __metadata("design:type", String) ], HtmlDragSensor.prototype, "dropEffect", void 0); __decorate([ observable(false), __metadata("design:type", Array) ], HtmlDragSensor.prototype, "dataTypesAllowed", void 0); __decorate([ observable(false), __metadata("design:type", String) ], HtmlDragSensor.prototype, "effectAllowed", void 0); __decorate([ observable(false), __metadata("design:type", Boolean) ], HtmlDragSensor.prototype, "dropAllowed", void 0); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "startDragging", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "dragging", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "finishDragging", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "enterTarget", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "leaveTarget", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "dragOver", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "drop", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "updateEventOnDragStart", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "updateEventOnDropAllowed", null); __decorate([ atomic, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "reset", null); __decorate([ reactive, options({ throttling: 0 }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "whenDragging", null); function areEqualArrays(array1, array2) { let result = true; for (let i = 0; i < array1.length; i++) { if (array1[i] !== array2[i]) { result = false; break; } } return result; }