2019-10-05 02:09:52 +02:00
|
|
|
import { $$ } from './dom';
|
2022-04-17 15:12:21 +02:00
|
|
|
import { delegate } from './events';
|
2019-10-05 02:09:52 +02:00
|
|
|
|
2022-04-17 14:42:13 +02:00
|
|
|
let dragSrcEl: HTMLElement | null = null;
|
2019-10-05 02:09:52 +02:00
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function dragStart(event: DragEvent, target: HTMLElement) {
|
2019-10-05 02:09:52 +02:00
|
|
|
target.classList.add('dragging');
|
|
|
|
dragSrcEl = target;
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
if (!event.dataTransfer) return;
|
|
|
|
|
2019-10-05 02:09:52 +02:00
|
|
|
if (event.dataTransfer.items.length === 0) {
|
|
|
|
event.dataTransfer.setData('text/plain', '');
|
|
|
|
}
|
|
|
|
|
|
|
|
event.dataTransfer.effectAllowed = 'move';
|
|
|
|
}
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function dragOver(event: DragEvent) {
|
2019-10-05 02:09:52 +02:00
|
|
|
event.preventDefault();
|
2022-03-25 22:34:08 +01:00
|
|
|
if (event.dataTransfer) {
|
|
|
|
event.dataTransfer.dropEffect = 'move';
|
|
|
|
}
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function dragEnter(event: DragEvent, target: HTMLElement) {
|
2019-10-05 02:09:52 +02:00
|
|
|
target.classList.add('over');
|
|
|
|
}
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function dragLeave(event: DragEvent, target: HTMLElement) {
|
2019-10-05 02:09:52 +02:00
|
|
|
target.classList.remove('over');
|
|
|
|
}
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function drop(event: DragEvent, target: HTMLElement) {
|
2019-10-05 02:09:52 +02:00
|
|
|
event.preventDefault();
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
if (!dragSrcEl) return;
|
|
|
|
|
2019-10-05 02:09:52 +02:00
|
|
|
dragSrcEl.classList.remove('dragging');
|
|
|
|
|
|
|
|
if (dragSrcEl === target) return;
|
|
|
|
|
|
|
|
// divide the target element into two sets of coordinates
|
2022-03-25 22:34:08 +01:00
|
|
|
// and determine how to act based on the relative mouse position
|
2019-10-05 02:09:52 +02:00
|
|
|
const bbox = target.getBoundingClientRect();
|
2022-03-25 22:34:08 +01:00
|
|
|
const detX = bbox.left + bbox.width / 2;
|
2019-10-05 02:09:52 +02:00
|
|
|
|
|
|
|
if (event.clientX < detX) {
|
|
|
|
target.insertAdjacentElement('beforebegin', dragSrcEl);
|
2024-07-03 22:54:14 +02:00
|
|
|
} else {
|
2019-10-05 02:09:52 +02:00
|
|
|
target.insertAdjacentElement('afterend', dragSrcEl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
function dragEnd(event: DragEvent, target: HTMLElement) {
|
2022-04-03 02:13:15 +02:00
|
|
|
clearDragSource();
|
2019-10-05 02:09:52 +02:00
|
|
|
|
2022-03-25 22:34:08 +01:00
|
|
|
if (target.parentNode) {
|
2024-07-03 23:03:46 +02:00
|
|
|
$$('.over', target.parentNode).forEach(t => t.classList.remove('over'));
|
2022-03-25 22:34:08 +01:00
|
|
|
}
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function initDraggables() {
|
2022-04-17 15:12:21 +02:00
|
|
|
const draggableSelector = '.drag-container [draggable]';
|
2024-07-03 22:54:14 +02:00
|
|
|
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 });
|
2019-10-05 02:09:52 +02:00
|
|
|
}
|
2022-04-03 02:13:15 +02:00
|
|
|
|
|
|
|
export function clearDragSource() {
|
|
|
|
if (!dragSrcEl) return;
|
|
|
|
|
|
|
|
dragSrcEl.classList.remove('dragging');
|
2022-04-17 14:42:13 +02:00
|
|
|
dragSrcEl = null;
|
2022-04-03 02:13:15 +02:00
|
|
|
}
|