Drag and Drop API

Contact Us or call 1-877-932-8228
Drag and Drop API

Drag and Drop API

The HTML5 Drag and Drop API provides a great illustration of the downside of the "paving the cowpaths" approach of HTML5. It standardizes the drag-and-drop API originally created in Internet Explorer 5 (yup, 5). As other browsers implemented the same API, it was decided that this was a cowpath worth paving. We explain basic usage here, which ironically doesn't work very well in Internet Explorer version prior to 10, but does work in the other HTML5-compliant browsers.

To build a drag-and-drop application, you need to do the following:

  1. Create a draggable element.
  2. Create an element to be your drop zone.
  3. Capture and respond to drag-and-drop events.
  4. Optionally change styles during drag-and-drop process.

It's easiest to understand by looking at a small demo application:

Code Sample:

html5-apis/Demos/drag-and-drop.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Drag and Drop API</title>
<script src="../../html5-common/dateFormat.js" type="text/javascript"></script>
<script src="dragdrop/script.js" type="text/javascript"></script>
<link href="dragdrop/style.css" rel="stylesheet">
</head>
<body>
<h1>Drag and Drop</h1>
<div id="dropzone">Last Dropped: <time>never</time></div>
<div id="drag" draggable="true"></div>
<ol id="output"></ol>
</body>
</html>

We have two divs:

  1. "dropzone" for capturing the drop events
  2. "drag" for dragging - notice the draggable="true" attribute

Code Sample:

html5-apis/Demos/dragdrop/style.css
#dropzone {
	border:1px solid black;
	width:100px;
	height:100px;	
	float:left;
	margin-right:10px;
	text-align:center;
}

#drag {
	background-color:red;
	width:50px;
	height:50px;	
	float:left;
	cursor:move;
}

#output {
	background-color:white;	
	float:left;
	width:200px;
	margin-right:25px;
}

time {
	text-decoration:underline;	
}

Nothing too exciting here. Just some basic styling.

Code Sample:

html5-apis/Demos/dragdrop/script.js
var dropzone, drag;
window.addEventListener("load",dragDrop,false);
function dragDrop() {
	dropzone = document.getElementById("dropzone");
	drag = document.getElementById("drag");
	drag.addEventListener("dragstart", handleDragStart, false);
	drag.addEventListener("drag", handleDrag, false);
	drag.addEventListener("dragend", handleDragEnd, false);
	dropzone.addEventListener("dragenter", handleDragEnter, false);
	dropzone.addEventListener("dragover", handleDragOver, false);
	dropzone.addEventListener("dragleave", handleDragLeave, false);
	dropzone.addEventListener("drop", handleDrop, false);
}

function handleDragStart(e) {
	this.style.backgroundColor="green";
	document.getElementById("output").innerHTML+="<li>Dragging Started</li>";
	e.dataTransfer.setData('Text',this.id);
}

var dragReported=false;
function handleDrag(e) {
	if (!dragReported) document.getElementById("output").innerHTML+="<li>Dragging</li>";
	dragReported = true;
}

function handleDragEnter(e) {
	document.getElementById("output").innerHTML+="<li>Drag Enter</li>";
	cancel(e);
}

var dragOverReported=false;
function handleDragLeave(e) {
	document.getElementById("output").innerHTML+="<li>Drag Leave</li>";
	dragOverReported = false;
}

function handleDragOver(e) {
	if (!dragOverReported) document.getElementById("output").innerHTML+="<li>Dragging Over</li>";
	dragOverReported = true;
	cancel(e);
}

function handleDrop(e) {
	var droppedElem = e.dataTransfer.getData('Text');
	document.getElementById("output").innerHTML+="<li><strong>" + droppedElem + "</strong> dropped on <strong>" + this.id + "</strong></li>";
	var now = new Date();
	this.getElementsByTagName("time")[0].innerHTML = now.format("H:MM:ss");
	cancel(e);
}

function handleDragEnd(e) {
	document.getElementById("output").innerHTML+="<li>Dragging Ended</li>";
	this.style.backgroundColor="red";
}

function cancel(e) {
	if (e.preventDefault) {
		e.preventDefault();
	}
	return false;
}

Here is where the action takes place. We capture these events for the draggable element:

  1. dragstart
  2. drag
  3. dragend

And these events for the drop zone:

  1. dragenter
  2. dragover
  3. dragleave
  4. drop

Note that the drag and dragover events fire repeatedly as the draggable element is dragged. That's why we use the booleans dragReported and dragOverReported to stop the reporting. If you leave those out, you'll likely crash your browser.

The excitement happens in the handleDrop() function, which writes out the time of the drop. You could do anything at this point; for example, change the position of the element or add an item to a shopping cart.

You may have noticed the two calls to cancel():

  1. In handleDragOver(), that allows us to drop the draggable element.
  2. In handleDrop(), that prevents the browser from trying to navigate to another page when the element is dropped.

The unfortunate reality is that the drag-and-drop API in HTML5 does not make developers' lives easier. If you're working a lot with drag-and-drop, you're almost definitely better off using a framework like jQuery or YUI. However, the concepts covered in this section are the same as you'll see in those libraries.

You'll get a chance to try out the drag-and-drop API in the next exercise.

Next