forked from rocicorp/replicache
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdrag.js
More file actions
83 lines (72 loc) · 2.08 KB
/
Copy pathdrag.js
File metadata and controls
83 lines (72 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import {generateKeyBetween} from 'fractional-indexing';
let activeDrag = null;
async function handleDragStart(
e,
targetID,
startIndex,
getCurrentTodos,
handleRender,
handleDragEnd,
) {
const target = document.querySelectorAll('.todo-item')[startIndex];
activeDrag = {
targetID,
startIndex,
getCurrentTodos,
handleRender,
handleDragEnd,
startY: e.pageY,
itemHeight: target.offsetHeight,
};
document.body.classList.add('dragging');
activeDrag.handleRender(activeDrag.getCurrentTodos());
e.preventDefault();
}
async function handleDragMove(e) {
if (!activeDrag) {
return;
}
const dPx = e.pageY - activeDrag.startY;
const dItem = Math.round(dPx / activeDrag.itemHeight);
const todos = activeDrag.getCurrentTodos();
const newIndex = Math.max(
0,
Math.min(todos.length, activeDrag.startIndex + dItem),
);
const currentIndex = todos.findIndex(todo => todo.id == activeDrag.targetID);
if (currentIndex == -1) {
handleDragEnd();
return;
}
if (newIndex == currentIndex) {
return;
}
const dragTodos = [...activeDrag.getCurrentTodos()];
const [todo] = dragTodos.splice(currentIndex, 1);
dragTodos.splice(newIndex, 0, todo);
activeDrag.handleRender(dragTodos);
}
async function handleDragEnd() {
document.body.classList.remove('dragging');
if (!activeDrag) {
return;
}
const todos = activeDrag.getCurrentTodos();
const currentIndex = todos.findIndex(todo => todo.id == activeDrag.targetID);
if (currentIndex == -1) {
console.log(`todo ${todo.id} no longer present on dragend`);
return;
}
const prev = currentIndex == 0 ? null : todos[currentIndex - 1].order;
const next =
currentIndex == todos.length - 1 ? null : todos[currentIndex + 1].order;
const order = generateKeyBetween(prev, next);
await activeDrag.handleDragEnd(activeDrag.targetID, order);
activeDrag = null;
}
function isDragging(id) {
return activeDrag?.targetID === id;
}
document.addEventListener('mousemove', handleDragMove);
document.addEventListener('mouseup', handleDragEnd);
export {handleDragStart, isDragging};