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 } |
