philomena/assets/js/utils/draggable.ts
2024-07-05 21:48:17 -04:00

78 lines
2.1 KiB
TypeScript

import { $$ } from './dom';
import { delegate } from './events';
let dragSrcEl: HTMLElement | null = null;
function dragStart(event: DragEvent, target: HTMLElement) {
target.classList.add('dragging');
dragSrcEl = target;
if (!event.dataTransfer) return;
if (event.dataTransfer.items.length === 0) {
event.dataTransfer.setData('text/plain', '');
}
event.dataTransfer.effectAllowed = 'move';
}
function dragOver(event: DragEvent) {
event.preventDefault();
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'move';
}
}
function dragEnter(event: DragEvent, target: HTMLElement) {
target.classList.add('over');
}
function dragLeave(event: DragEvent, target: HTMLElement) {
target.classList.remove('over');
}
function drop(event: DragEvent, target: HTMLElement) {
event.preventDefault();
if (!dragSrcEl) return;
dragSrcEl.classList.remove('dragging');
if (dragSrcEl === target) return;
// divide the target element into two sets of coordinates
// and determine how to act based on the relative mouse position
const bbox = target.getBoundingClientRect();
const detX = bbox.left + bbox.width / 2;
if (event.clientX < detX) {
target.insertAdjacentElement('beforebegin', dragSrcEl);
} else {
target.insertAdjacentElement('afterend', dragSrcEl);
}
}
function dragEnd(event: DragEvent, target: HTMLElement) {
clearDragSource();
if (target.parentNode) {
$$('.over', target.parentNode).forEach(t => t.classList.remove('over'));
}
}
export function initDraggables() {
const draggableSelector = '.drag-container [draggable]';
delegate(document, 'dragstart', { [draggableSelector]: dragStart });
delegate(document, 'dragover', { [draggableSelector]: dragOver });
delegate(document, 'dragenter', { [draggableSelector]: dragEnter });
delegate(document, 'dragleave', { [draggableSelector]: dragLeave });
delegate(document, 'dragend', { [draggableSelector]: dragEnd });
delegate(document, 'drop', { [draggableSelector]: drop });
}
export function clearDragSource() {
if (!dragSrcEl) return;
dragSrcEl.classList.remove('dragging');
dragSrcEl = null;
}