So Drag & Drop

An HTML5 example of drag & drop feature.

by softwareinnovator

HTML

<!DOCTYPE html>
<body>

<h1>So drag & drop</h1>
<div id="todrag" class="w25 fleft">
	<span draggable="true">Draggable n°1</span>
	<span draggable="true">Draggable n°2</span>
	<span draggable="true">Draggable n°3</span>
	<span draggable="true">Draggable n°4</span>
</div>

<div class="w50 fleft">
	<h2>Lâchez ici &darr;</h2>
	<div id="mydropzone" dropzone="move">
	</div>
</div>

<div class="w25 fright">
	<div id="mylist" class="hidden">

	</div>
</div>

<script src="js/script.js"></script>
</body>

CSS

body{
	font-family:Calibri, sans-serif;
	font-size:14px;
	width:800px;
	margin:auto;
}

#todrag{
	list-style-type: none;
	padding:0;
	margin:0;
	padding-bottom:5px;
}

h1, h2, h3, h4, h5, h6{ text-align:center; }

/*
 * Let's tune our draggable items !
 */
[draggable=true]{
	cursor: move;
	padding:1em;

	border-radius:2px;

	border:1px black solid;
	margin-bottom:0.1em;
	display:block;
}
[draggable=true]:hover{
	box-shadow:0 0 5px green;
}

#mylist, [dropzone]{
	width:90%;
	margin:auto;
	border:2px gray solid;
	border-radius:2px;
}

/* Soft background transition */
[draggable=true], [dropzone]{
	transition:
		box-shadow linear 0.2s,
		background-color linear 0.2s,
		color linear 0.2s;
}

[dropzone]{
	color:gray;
	font-style:italic;
	font-size:1.5rem;
	text-align:center;
	border:2px gray dashed;
	padding:1em 0;
}
#mylist img, #mylist span{
	display:block;
	padding:1em;
}
#mylist img{
	margin:auto;
}

.hidden{ visibility:hidden; }
.w25{ width:25%; }
.w50{ width:50%; }
.fleft{	float:left; }
.fright{ float:right; }

JavaScript

/*
 * Because "dragend" is called both if you drop the item on the dropzone
 * or if you drop the item anywhere else, we have to mind if we can
 * remove it.
 *
 * When the item is successfuly dropped on the dropzone, dnd_successful
 * is true and we can remove it safely.
 */
dnd_successful = false;

/*
 * Set all the <span> and <img> DnD events up.
 * Most of the browser have already set <img> DnD events up, but we
 * override them to define a specific behavior.
 */
var draggables = [];
var spans = document.getElementsByTagName('span');
var imgs = document.images;
for(var k = 0; k < spans.length; k++)
	draggables.push(spans[k]);
for(var j = 0; j < imgs.length; j++)
	draggables.push(imgs[j]);

for(var i = 0; i < draggables.length; i++)
{
	draggables[i].addEventListener('dragstart', function(event){
		event.target.style.background = "green";

		/* Allow specific type of transfers */
		event.dataTransfer.effectAllowed = "move";

		/* 
		 * Set the data to send to the dropzone.
		 * Two cases :
		 * 1 - it is a picture, make a text/html data string.
		 * 2 - it is plain text, make a simple text/plain data string.
		 */
		var src = event.target.getAttribute('src');
		var alt = event.target.getAttribute('alt');
		if(null !== src) //Case 1
			event.dataTransfer.setData("text/html", '<img src="' + src + '" alt="' + alt + '"/>');
		else //Case 2
			event.dataTransfer.setData("text/plain", event.target.innerText || event.target.textContent);

		dnd_successful = false;
	});

	draggables[i].addEventListener('dragend', function(event){
		if(dnd_successful)
			event.target.parentNode.removeChild(event.target);
		else
			event.target.style.background = 'white';
	});
}

var dropzone = document.getElementById('mydropzone');

dropzone.addEventListener('dragenter', function(event){
	event.target.style.background = "#CCCCCC";
	event.preventDefault();
});

dropzone.addEventListener('dragleave', function(event){
	event.target.style.background =...