121 lines
3.6 KiB
JavaScript
121 lines
3.6 KiB
JavaScript
|
import { TpTable } from "./tp-table";
|
||
|
|
||
|
export default class ColumnMover {
|
||
|
constructor(wrap, handleSelector) {
|
||
|
this._handleSelector = handleSelector;
|
||
|
this._mouseDown = this._mouseDown.bind(this);
|
||
|
this._dragging = this._dragging.bind(this);
|
||
|
this._draggingEnd = this._draggingEnd.bind(this);
|
||
|
this._trackingStarted = false;
|
||
|
|
||
|
// Amount of pixels the handle must be moved before its registered as a tracking gesture.
|
||
|
this.threshold = 5;
|
||
|
|
||
|
wrap.addEventListener('mousedown', this._mouseDown, true);
|
||
|
}
|
||
|
|
||
|
_mouseDown(e) {
|
||
|
const handle = e.composedPath().find(node => node.matches && node.matches(this._handleSelector));
|
||
|
if (!handle) return;
|
||
|
|
||
|
e.stopPropagation();
|
||
|
e.preventDefault();
|
||
|
this._cHandle = handle;
|
||
|
this._startX = e.pageX;
|
||
|
this._watchDrag();
|
||
|
}
|
||
|
|
||
|
_watchDrag() {
|
||
|
window.addEventListener('mousemove', this._dragging);
|
||
|
window.addEventListener('mouseup', this._draggingEnd);
|
||
|
}
|
||
|
|
||
|
_stopWatchDrag() {
|
||
|
window.removeEventListener('mousemove', this._dragging);
|
||
|
window.removeEventListener('mouseup', this._draggingEnd);
|
||
|
}
|
||
|
|
||
|
_dragging(e) {
|
||
|
if (this._trackingStarted === false && Math.abs(e.pageX - this._startX) >= this.threshold) {
|
||
|
this._trackingStarted = true;
|
||
|
this._showClone();
|
||
|
this._clearSelection();
|
||
|
}
|
||
|
|
||
|
if (this._trackingStarted === true) {
|
||
|
this._positionClone(e.pageX, e.pageY);
|
||
|
this._cHandle.dispatchEvent(new CustomEvent('track-move', { detail: { target: this._cHandle, state: 'track', x: e.pageX, y: e.pageX }, bubbles: true, composed: true }));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_draggingEnd(e) {
|
||
|
this._trackingStarted = false;
|
||
|
this._cHandle.dispatchEvent(new CustomEvent('track-move', { detail: { target: this._cHandle, state: 'end', x: e.pageX, y: e.pageX }, bubbles: true, composed: true }));
|
||
|
this._stopWatchDrag();
|
||
|
this._cHandle = null;
|
||
|
this._startX = 0;
|
||
|
this._clearSelection();
|
||
|
this._clone.remove();
|
||
|
this._clone = null;
|
||
|
if (this._indicator) {
|
||
|
this._indicator.remove();
|
||
|
this._indicator = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_clearSelection() {
|
||
|
const sel = window.getSelection ? window.getSelection() : document.selection;
|
||
|
if (sel) {
|
||
|
if (sel.removeAllRanges) {
|
||
|
sel.removeAllRanges();
|
||
|
} else if (sel.empty) {
|
||
|
sel.empty();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Show indicator to visualize where a column would be dropped after releasing the mouse.
|
||
|
* @param {number} x X-coordinate
|
||
|
* @param {number} y Y-coordinate
|
||
|
*/
|
||
|
showIndicator(x, y) {
|
||
|
if (!this._indicator) {
|
||
|
const icon = document.createElement('tp-icon');
|
||
|
icon.icon = TpTable.downIcon;
|
||
|
icon.style.position = 'fixed';
|
||
|
icon.style.left = '0px';
|
||
|
icon.style.right = '0px';
|
||
|
icon.style.zIndex = '100000';
|
||
|
document.body.appendChild(icon);
|
||
|
this._indicator = icon;
|
||
|
}
|
||
|
|
||
|
const rect = this._indicator.getBoundingClientRect();
|
||
|
this._indicator.style.transform = `translate(${x - ((rect.right - rect.left) / 2)}px, ${y - rect.height}px)`;
|
||
|
}
|
||
|
|
||
|
_showClone() {
|
||
|
const div = document.createElement('div');
|
||
|
div.style.background = 'rgba(255, 255, 255, 0.6)';
|
||
|
div.style.border = 'solid 1px rgba(255, 255, 255, 0.8)';
|
||
|
div.style.padding = '5px 10px';
|
||
|
div.style.borderRadius = '2px';
|
||
|
div.style.position = 'fixed';
|
||
|
div.style.zIndex = '99999';
|
||
|
div.style.left = '0px';
|
||
|
div.style.top = '0px';
|
||
|
div.style.display = 'flex';
|
||
|
div.style.alignItems = 'center';
|
||
|
div.style.justifyContent = 'center';
|
||
|
div.innerHTML = this._cHandle.column.label;
|
||
|
|
||
|
this._clone = div;
|
||
|
document.body.appendChild(div);
|
||
|
}
|
||
|
|
||
|
_positionClone(x, y) {
|
||
|
this._clone.style.transform = `translate(${x + 10}px, ${y}px)`;
|
||
|
}
|
||
|
}
|