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