Mercurial Hosting > linkmystyle
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dad.js Fri Jul 11 20:57:49 2025 -0600 @@ -0,0 +1,155 @@ +'use strict'; + +let dad = {}; + +{ + // override these if needed + dad.whatToDrag = function(draggable) { + return draggable; + }; + dad.onStart = function(event) {}; + dad.onEnter = function(event) {}; + dad.onLeave = function(event) {}; + dad.onDrop = function(event) {}; + dad.onDropped = function(event) {}; + + + let original = null; + let dragging = null; + let dropzone = null; + let touchX, touchY; + + function isIn(x,y,rect) { + return rect.x <= x && x <= rect.x+rect.width && rect.y <= y && y <= rect.y+rect.height; + } + + function myEvent(mouseEvent) { + return { + original: original, + dragging: dragging, + dropzone: dropzone, + mouseEvent: mouseEvent, + }; + } + + function onMouseMove(event) { + { + event.preventDefault(); + let rect = dragging.getBoundingClientRect(); + dragging.style.left = `${rect.x+event.movementX}px`; + let y = rect.y + event.movementY; + if( y < 0 ) { + window.scrollBy( 0, y ); + } else if( y + rect.height > window.innerHeight ) { + window.scrollBy( 0, y + rect.height - window.innerHeight ); + } + dragging.style.top = `${y}px`; + } + { + let x = event.clientX; + let y = event.clientY; + if( !(dropzone && isIn(x,y,dropzone.getBoundingClientRect())) ) { + if( dropzone ) { + dad.onLeave(myEvent(event)); + dropzone = null; + } + let dropzones = document.querySelectorAll('[dad-dropzone]'); + for( let i=0; i<dropzones.length; i++ ) { + let dz = dropzones[i]; + if( dz === dragging ) + continue; + if( isIn(x,y,dz.getBoundingClientRect()) ) { + let old = dropzone; + dropzone = dz; + let f = dad.onEnter(myEvent(event)); + if( f === false ) + dropzone = old; + else + break; + } + } + } + } + } + + function onTouchMove(event) { + let touches = event.touches; + if( touches.length !== 1 ) + return; + let touch = touches[0]; + let x = touch.clientX; + let y = touch.clientY; + event.clientX = x; + event.clientY = y; + event.movementX = x - touchX; + event.movementY = y - touchY; + touchX = x; + touchY = y; + onMouseMove(event); + } + + function onMouseUp(event) { + dad.onDrop(myEvent(event)); + if( dropzone ) { + dad.onLeave(myEvent(event)); + } + original.removeAttribute('dad-original'); + dragging.parentNode.removeChild(dragging); + document.removeEventListener('mousemove',onMouseMove); + document.removeEventListener('mouseup',onMouseUp); + document.removeEventListener('touchmove',onTouchMove); + document.removeEventListener('touchend',onMouseUp); + original.scrollIntoViewIfNeeded(false); + let droppedEvent = { + original: original, + }; + original = null; + dragging = null; + dropzone = null; + dad.onDropped(droppedEvent); + } + + function start(event) { + original = dad.whatToDrag(event.target); + dragging = original.cloneNode(true); + original.setAttribute('dad-original',''); + dragging.setAttribute('dad-dragging',''); + let rect = original.getBoundingClientRect(); + dragging.style.left = `${rect.x}px`; + dragging.style.top = `${rect.y}px`; + dragging.style.width = `${rect.width}px`; + dragging.style.height = `${rect.height}px`; + original.parentNode.appendChild(dragging); + dad.onStart(myEvent(event)); + } + + function onMouseDown(event) { + start(event); + document.addEventListener('mousemove',onMouseMove); + document.addEventListener('mouseup',onMouseUp); + } + + function onTouchStart(event) { + event.preventDefault(); + start(event); + let touches = event.touches; + if( touches.length !== 1 ) + return; + let touch = touches[0]; + touchX = touch.clientX; + touchY = touch.clientY; + document.addEventListener('touchmove',onTouchMove); + document.addEventListener('touchend',onMouseUp); + } + + dad.setDraggable = function(el) { + el.setAttribute('dad-drag',''); + el.setAttribute('draggable','false'); + el.addEventListener('mousedown',onMouseDown); + el.addEventListener('touchstart',onTouchStart); + }; + + dad.setDropzone = function(el) { + el.setAttribute('dad-dropzone',''); + }; +}