How to use HTML5’s drag and drop

For a long time JavaScript functions have existed that allow us to create drag and drop interfaces, but none of these implementations were native to the browser.

In HTML5, we have a native method of creating drag and drop interfaces (with a little help from JavaScript).

I’m going to let you in on how to achieve this…

 

Browser support

I’d like to get this out of the way before we progress: currently HTML5 drag and drop is supported by all major desktop browsers (including IE (even IE 5.5 has partial support)) but it’s not currently supported by any of the popular mobile browsers.

 

Drag and drop events

At every stage of the drag and drop operation a different event is fired so that the browser knows what JavaScript code to execute; the events are:

  • dragStart : fires when the user starts dragging the element.
  • dragEnter : fires when the draggable element is first dragged over the target element.
  • dragOver: fires when the mouse is moved over an element when the drag is occurring.
  • dragLeave: fired if the user’s cursor leaves an element when dragging.
  • drag: fires every time we move the mouse during the dragging of our element.
  • drop: fired when the actual drop is performed.
  • dragEnd: fires when the user releases the mouse while dragging the object.

With all of these event listeners you have a lot of control over how your interface works and precisely how it performs in different circumstances.

 

The dataTransfer object

This is where all the drag and drop magic happens; this object holds the data that was sent by the drag operation. The data can be set and retrieved in various ways, the most important ones are:

  • dataTransfer.effectAllowed=value: this returns the types of action permitted, possible values are none, copy, copyLink, copyMove, link, linkMove, move, all and uninitialized.
  • dataTransfer.setData(format, data): adds the specified data and its format.
  • dataTransfer.clearData( format ): clears all the data for a specific format.
  • dataTransfer.setDragImage(element, x, y): sets the image you wish to drag, the x and y values specify where the mouse cursor should be (0, 0 will place it top left).
  • data = dataTransfer.getData(format) : As the name says it returns the data available for a specific format.

 

Creating a drag and drop example

Now we will start creating our simple drag and drop example, you can see that we have two small divs and a larger one, we can drag and drop the small ones inside the big one and we can even move them back.

Dragging the object

The first thing we need to do is create our HTML. We make the divs draggable with the draggable attribute, like so:

<div id="boxA" draggable="true"></div>

When this is done we need to define the javascript function that will run when we start to drag this element:

function dragStart(ev) {
   ev.dataTransfer.effectAllowed='move';
   ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));   ev.dataTransfer.setDragImage(ev.target,100,100);
   return true;
}

In this code we first declare what type of effect we allow in the operation and we set that to move, in the second line we set the data for the operation and in this case the type is Text and the value is the ID of the element we are dragging. After this we use the setDragImage method to set what we will be dragging and then where the cursor will be while dragging, and since the cubes are 200 by 200px I placed that at the very center. Finally we return true.

Dropping the object

In order for an element to accept a drop it needs to listen to 3 different events: dragEnter, dragOver and also the drop event so let’s add this to our html in the div with the ID of big:

<div id="big" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)"></div>

Now that we added event listeners we need to create these functions we will start by the dragenter and dragover events:

function dragEnter(ev) {
   ev.preventDefault();
   return true;
}
function dragOver(ev) {
    ev.preventDefault();
}

In the first function we define what we want to happen when the element we are dragging reaches the element it’s supposed to be dropped in, in this case we only prevent the default behavior of the browser but you can do any number of things like change the background or add some text to indicate that the user is dragging to the correct area and using the dragleave event you can revert the changes you made. Next in the dragOver function we simply prevent the default to allow for the drop.

The next part is where we define the function for when we actually drop the element on the desired target:

function dragDrop(ev) {
   var data = ev.dataTransfer.getData("Text");
   ev.target.appendChild(document.getElementById(data));
   ev.stopPropagation();
   return false;
}

In this last part we first set a variable called data in which we get all the data that is available for the text format and then we append that data (which will be the element that we are dragging) to the div where we wish to drop the element. Finally some final touches like stopping propagation and also returning false.

Making the section a drop target

Checking the demo, you can see we also made sure that the two divs could be dragged back to their original location. Happily, adding another drop target may be simpler than you think; because the functions are already in place, all we have to do is add the event listeners, like so:

<section id="section" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)">

And that is all we need to in order to allow dragging of the divs to the original place.

 

Conclusion

There are plenty of drag and drop applications built using JavaScript libraries, and it is often simpler to use those libraries. But I hope that, in this HTML5 & JavaScript technique, you see the future potential of the native solution.

Have you built a drag and drop interface? How does native HTML5 compare to pure JavaScript solutions? Let us know in the comments.

Featured image/thumbnail, drop image via photophilde.

  • azumbrunnen

    I built a whole user interface based on HTML5 dnd. I wouldn’t do it again. It’s a lot easier to just use jQuery or other JS libraries for this. I don’t know about you, but I felt there were some extremely broken things at the time I used it (like 1 year ago).

    We would need an abstraction of the Drag & Drop interfaces that easens the implementation of native DND. Maybe there is already one?

    • Sara Vieira

      There is still a lot of bugs and inconsistencies when it comes to HTML5 and I do share your opinion that it’s easier to create this interfaces with jQuery but HTML5 Drag and Drop is one of those things that we should also know how to natively.

      I don’t think there is one yet :/

      • azumbrunnen

        Keep you posted. I might share my idea about it soon. Thanks for the article! great stuff!

  • Ludwig CRON

    Well Explained! To Add, for ensuring a compatibility you should a litteral object for the dataTransfer like that dataTransfer = (function(){
    var elem = null, text = “”; return{
    getData:function(input){
    switch(input){
    case “text/plain”:
    return text;
    break;
    case “text/html”:
    return elem.innerHTML;
    break;
    }
    throw “NotImplemented”;

    },
    setData:function(input, val){…}

    };})();

    And for mobile use drag events were nerver listen. Thus you need to create yourself or use a jquery drag & drop. To my mind in a project a javascript only is lighter and you could use the transform property in CSS3 to ensure the hardware acceleration.[translate3d(…)]

  • Robert Mackin

    Thanks for the tutorial, makes me think that maybe the future of video websites is ones which the user can customize, dropping and dragging their favorite videos into whatever position they want.

  • Twinone

    You have a little bug there that new programmers won’t understand:
    Change event to ev in the second line of this code:

    function dragEnter(ev) {
    event.preventDefault();
    return true;
    }

    • http://www.webdesignerdepot.com/ Benjie — WebdesignerDepot

      Thanks for the heads up. We’ve fixed it.

  • nk

    Oh C’mon! It’s HTML5 and you still use inline event attributes?

  • Yemista

    well presentable and easy to place in web designs.

  • http://www.totalmarketingaustralia.com.au/ Mike Manning

    It is a very informative and useful post thanks it is good material to read this post increases my knowledge.

  • http://www.linkworxseo.com/ Link Worx Seo

    This is great, but I have already tried a drag and drop feature with jQuery on a site. Worked fine, but I was trying to figure out how to change the CSS from the load position to the new position after being dropped. Basically I want the position attribute to change from the starting point to the final point of the drop. Any thoughts on this question?

  • didbob

    This is not working in Firefox 22 or IE 10 . I get the error:

    ReferenceError: event is not definedevent.preventDefault();

  • didbob

    This is not working in Firefox 22 or IE 10. I get the error:
    ReferenceError: event is not definedevent.preventDefault();

  • mwaage

    Thank you for providing this info. This functionality would make a current clunky CMS tool a lot easier. I knew it could be done…

  • Terra Mater

    its good….. nd easy to understand………sara…
    [ http://www.terramatertech.com/ ]

  • Alagu Sundar

    Great article. Thanks for the explanations.
    http://www.cavinitsolutions.com/

  • Maryam Kureshi

    http://www.toontuts.com/easy-html5-drag-drop/ – its another way to implement simple drag and drop on HTML Containers.