Mercurial Hosting > linkmystyle
comparison src/dad.js @ 0:8f4df159f06b
start public repo
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 11 Jul 2025 20:57:49 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:8f4df159f06b |
---|---|
1 'use strict'; | |
2 | |
3 let dad = {}; | |
4 | |
5 { | |
6 // override these if needed | |
7 dad.whatToDrag = function(draggable) { | |
8 return draggable; | |
9 }; | |
10 dad.onStart = function(event) {}; | |
11 dad.onEnter = function(event) {}; | |
12 dad.onLeave = function(event) {}; | |
13 dad.onDrop = function(event) {}; | |
14 dad.onDropped = function(event) {}; | |
15 | |
16 | |
17 let original = null; | |
18 let dragging = null; | |
19 let dropzone = null; | |
20 let touchX, touchY; | |
21 | |
22 function isIn(x,y,rect) { | |
23 return rect.x <= x && x <= rect.x+rect.width && rect.y <= y && y <= rect.y+rect.height; | |
24 } | |
25 | |
26 function myEvent(mouseEvent) { | |
27 return { | |
28 original: original, | |
29 dragging: dragging, | |
30 dropzone: dropzone, | |
31 mouseEvent: mouseEvent, | |
32 }; | |
33 } | |
34 | |
35 function onMouseMove(event) { | |
36 { | |
37 event.preventDefault(); | |
38 let rect = dragging.getBoundingClientRect(); | |
39 dragging.style.left = `${rect.x+event.movementX}px`; | |
40 let y = rect.y + event.movementY; | |
41 if( y < 0 ) { | |
42 window.scrollBy( 0, y ); | |
43 } else if( y + rect.height > window.innerHeight ) { | |
44 window.scrollBy( 0, y + rect.height - window.innerHeight ); | |
45 } | |
46 dragging.style.top = `${y}px`; | |
47 } | |
48 { | |
49 let x = event.clientX; | |
50 let y = event.clientY; | |
51 if( !(dropzone && isIn(x,y,dropzone.getBoundingClientRect())) ) { | |
52 if( dropzone ) { | |
53 dad.onLeave(myEvent(event)); | |
54 dropzone = null; | |
55 } | |
56 let dropzones = document.querySelectorAll('[dad-dropzone]'); | |
57 for( let i=0; i<dropzones.length; i++ ) { | |
58 let dz = dropzones[i]; | |
59 if( dz === dragging ) | |
60 continue; | |
61 if( isIn(x,y,dz.getBoundingClientRect()) ) { | |
62 let old = dropzone; | |
63 dropzone = dz; | |
64 let f = dad.onEnter(myEvent(event)); | |
65 if( f === false ) | |
66 dropzone = old; | |
67 else | |
68 break; | |
69 } | |
70 } | |
71 } | |
72 } | |
73 } | |
74 | |
75 function onTouchMove(event) { | |
76 let touches = event.touches; | |
77 if( touches.length !== 1 ) | |
78 return; | |
79 let touch = touches[0]; | |
80 let x = touch.clientX; | |
81 let y = touch.clientY; | |
82 event.clientX = x; | |
83 event.clientY = y; | |
84 event.movementX = x - touchX; | |
85 event.movementY = y - touchY; | |
86 touchX = x; | |
87 touchY = y; | |
88 onMouseMove(event); | |
89 } | |
90 | |
91 function onMouseUp(event) { | |
92 dad.onDrop(myEvent(event)); | |
93 if( dropzone ) { | |
94 dad.onLeave(myEvent(event)); | |
95 } | |
96 original.removeAttribute('dad-original'); | |
97 dragging.parentNode.removeChild(dragging); | |
98 document.removeEventListener('mousemove',onMouseMove); | |
99 document.removeEventListener('mouseup',onMouseUp); | |
100 document.removeEventListener('touchmove',onTouchMove); | |
101 document.removeEventListener('touchend',onMouseUp); | |
102 original.scrollIntoViewIfNeeded(false); | |
103 let droppedEvent = { | |
104 original: original, | |
105 }; | |
106 original = null; | |
107 dragging = null; | |
108 dropzone = null; | |
109 dad.onDropped(droppedEvent); | |
110 } | |
111 | |
112 function start(event) { | |
113 original = dad.whatToDrag(event.target); | |
114 dragging = original.cloneNode(true); | |
115 original.setAttribute('dad-original',''); | |
116 dragging.setAttribute('dad-dragging',''); | |
117 let rect = original.getBoundingClientRect(); | |
118 dragging.style.left = `${rect.x}px`; | |
119 dragging.style.top = `${rect.y}px`; | |
120 dragging.style.width = `${rect.width}px`; | |
121 dragging.style.height = `${rect.height}px`; | |
122 original.parentNode.appendChild(dragging); | |
123 dad.onStart(myEvent(event)); | |
124 } | |
125 | |
126 function onMouseDown(event) { | |
127 start(event); | |
128 document.addEventListener('mousemove',onMouseMove); | |
129 document.addEventListener('mouseup',onMouseUp); | |
130 } | |
131 | |
132 function onTouchStart(event) { | |
133 event.preventDefault(); | |
134 start(event); | |
135 let touches = event.touches; | |
136 if( touches.length !== 1 ) | |
137 return; | |
138 let touch = touches[0]; | |
139 touchX = touch.clientX; | |
140 touchY = touch.clientY; | |
141 document.addEventListener('touchmove',onTouchMove); | |
142 document.addEventListener('touchend',onMouseUp); | |
143 } | |
144 | |
145 dad.setDraggable = function(el) { | |
146 el.setAttribute('dad-drag',''); | |
147 el.setAttribute('draggable','false'); | |
148 el.addEventListener('mousedown',onMouseDown); | |
149 el.addEventListener('touchstart',onTouchStart); | |
150 }; | |
151 | |
152 dad.setDropzone = function(el) { | |
153 el.setAttribute('dad-dropzone',''); | |
154 }; | |
155 } |