Investigating the HTML5 Drag and Drop API

One of the many new API’s available to developers with HTML5 is the Drag and Drop API. Drag and Drop is nothing new, it has been available for quite a few years now using JavaScript libraries (Prototype + script.aculo.us, Mootools, jQueryUI, YUI), and even in IE; HTML5 drag and drop is based on work done by Microsoft in 1999 (wow!). That being said, each library implements it in their own specific way, usually this isn’t a problem but it means all developers on a team have to know how that library works, which isn’t always the case. Luckily the HTML5 D&D API promises to level the playing field by supporting drag and drop natively in the browser using vanilla JavaScript (but how long it will take for this to happen is anybody’s guess).

It’s an interesting time for JavaScript libraries with these new native browser API’s coming out. I’m guessing it will be a case that if the browser supports drag and drop natively the method will be used, if not then fall back the the library implementation. For the developer this should mean no extra code, but for the library authors it could be a little tricky as browsers gradually roll out native support. Browser sniffing is never a good thing, but if browser vendors don’t agree on its implementation it may be required.

To see how HTML5 drag and drop works I’ve put together a simple little experiment. The experiment allows you to drag a thumbnail image onto a drop area to load a larger version of the image using the canvas element. It’s easy to see how this could be adapted for use in an e-commerce shopping cart or an online web application (perfect for iPad users!). Note: I’ve only tested in FF 3.6, I don’t want to get into the cross-browser issues (yet!), but for more information about what a mess it seems to be take a look at “The HTML5 drag and drop disaster” by Peter-Paul Koch.

It’s fairly simple to start using the drag and drop API, you just need to add a couple of attributes and events to an element to make it drag-able, then attach events to the drop element to do something with the data from the dropped element:

1
2
3
4
5
6
<!-- Our dragabble element -->
<li draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'bonfire'); event.dataTransfer.mozSetDataAt('application/x-moz-node', event.target, 0);">
    <img src="images/bonfire.jpg" alt="bonfire" id="bonfire">
</li>
<!-- Our drop area -->
<div id="drop" ondragover="dragDrop.imageDragOver(event);" ondrop="dragDrop.imageDrop(event);" ondragleave="dragDrop.imageLeave(event);"></div>

Now create a function that will fire once an element has been dropped; this will collect the data from the element and do something with it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    //.....
        imageDrop: function(event){
            //Does the drop contain node data?
            var isNode = event.dataTransfer.types.contains("application/x-moz-node");

            var imageData;
            //Look for node data first, fall back to plain if unavailable
            if(isNode){
                var nodeData = event.dataTransfer.mozGetDataAt("application/x-moz-node", 0);
                imageData = nodeData.id;
            } else {
                imageData = event.dataTransfer.getData("text/plain");
            }
            //Pass the data to the image load function
            this.loadCanvasData(imageData);

            //Prevents page jumping to the image
            event.preventDefault();
        },
    //.....
}

As you can see from the example above, it is possible to pass different types of data to the drop element. These include plain text, links, HTML / XML, files, images and document nodes. I’ve used the document node data by default and have added a check to see if the dragged element has any node data attached to it, if not it falls back to plain text data. You can see this check in action by dragging image two over the drop area. The background will turn red signalling that there is no node data attached. If you wanted, you could restrict what data type accepted by the drop box, but I added a fall back instead.

The example only took a couple of hours to put together, it may be very simple but it demonstrates how easy it is to implement the drag and drop API into your web application (assuming all browsers agree on how it should be implemented!).