changeset 6:4d699321068f

add dropzones
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 23 Apr 2023 18:34:12 -0600
parents 1293cb0d30da
children 332d3e280f7e
files src/dad.css src/dad.js src/examples/dropzones.html src/index.html
diffstat 4 files changed, 123 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/dad.css	Sun Apr 23 17:14:52 2023 -0600
+++ b/src/dad.css	Sun Apr 23 18:34:12 2023 -0600
@@ -9,4 +9,5 @@
 
 [dad-dragging] {
 	position: fixed !important;
+	z-index: 100;
 }
--- a/src/dad.js	Sun Apr 23 17:14:52 2023 -0600
+++ b/src/dad.js	Sun Apr 23 18:34:12 2023 -0600
@@ -9,24 +9,64 @@
 	};
 	dad.onDrop = function(event) {};
 	dad.onDropped = function(event) {};
+	dad.onEnter = function(event) {};
+	dad.onLeave = 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 onMouseMove(event) {
 		//console.log(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 );
+		{
+			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`;
 		}
-		dragging.style.top = `${y}px`;
+		{
+			let x = event.clientX;
+			let y = event.clientY;
+			if( !(dropzone && isIn(x,y,dropzone.getBoundingClientRect())) ) {
+				if( dropzone ) {
+					dad.onLeave({
+						original: original,
+						dragging: dragging,
+						dropzone: dropzone,
+						mouseEvent: 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()) ) {
+						dropzone = dz;
+						dad.onEnter({
+							original: original,
+							dragging: dragging,
+							dropzone: dropzone,
+							mouseEvent: event,
+						});
+						break;
+					}
+				}
+			}
+		}
 	}
 
 	function onTouchMove(event) {
@@ -36,6 +76,8 @@
 		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;
@@ -48,8 +90,17 @@
 		dad.onDrop({
 			original: original,
 			dragging: dragging,
+			dropzone: dropzone,
 			mouseEvent: event,
 		});
+		if( dropzone ) {
+			dad.onLeave({
+				original: original,
+				dragging: dragging,
+				dropzone: dropzone,
+				mouseEvent: event,
+			});
+		}
 		original.removeAttribute('dad-original');
 		dragging.parentNode.removeChild(dragging);
 		document.removeEventListener('mousemove',onMouseMove);
@@ -62,6 +113,7 @@
 		};
 		original = null;
 		dragging = null;
+		dropzone = null;
 		dad.onDropped(droppedEvent);
 	}
 
@@ -100,4 +152,8 @@
 		el.addEventListener('mousedown',onMouseDown);
 		el.addEventListener('touchstart',onTouchStart);
 	};
+
+	dad.setDropzone = function(el) {
+		el.setAttribute('dad-dropzone','');
+	};
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/dropzones.html	Sun Apr 23 18:34:12 2023 -0600
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1">
+		<style>
+			@import "/site.css";
+			@import "/dad.css";
+
+			[drag] {
+				display: inline-block;
+				background-color: LightGreen;
+				padding: 8px;
+			}
+			[dropzone] {
+				background-color: LightBlue;
+				padding: 8px;
+			}
+			[dropzone][in] {
+				border: 1px solid;
+			}
+		</style>
+		<script src="/dad.js"></script>
+		<script>
+			dad.onEnter = function(event) {
+				event.dropzone.setAttribute('in','');
+			};
+
+			dad.onLeave = function(event) {
+				event.dropzone.removeAttribute('in');
+			};
+
+			dad.onDrop = function(event) {
+				if( event.dropzone )
+					event.dropzone.appendChild(event.original);
+			};
+
+			function init() {
+				let drag = document.querySelector('[drag]');
+				dad.setDraggable(drag);
+				let dropzones = document.querySelectorAll('[dropzone]');
+				for( let i=0; i<dropzones.length; i++ ) {
+					let dropzone = dropzones[i];
+					dad.setDropzone(dropzone);
+				}
+			}
+		</script>
+	</head>
+	<body>
+		<h1>Dropzones</h1>
+		<p dropzone>dropzone 1 <span drag>drag me</span></p>
+		<p dropzone>dropzone 2 </p>
+		<p dropzone>dropzone 3 </p>
+		<p>bottom</p>
+	</body>
+	<script> init(); </script>
+</html>
--- a/src/index.html	Sun Apr 23 17:14:52 2023 -0600
+++ b/src/index.html	Sun Apr 23 18:34:12 2023 -0600
@@ -30,6 +30,7 @@
 			<li><a href="/examples/simple.html">Simple</a></li>
 			<li><a href="/examples/handle.html">Handle</a></li>
 			<li><a href="/examples/drop.html">Drop</a></li>
+			<li><a href="/examples/dropzones.html">Dropzones</a></li>
 		</ul>
 		<p>These use <a href="/dad.js">dad.js</a> and <a href="/dad.css">dad.css</a>.