dmathieu - HTML5 Drag and Drop

HTML5 Drag and Drop

Tuesday, 31 August 2010 in Development Articles by Damien Mathieu Creative Commons License

In this article, we’re gonna see one of the awesome new features of HTML 5 : moving elements in the page and tracking it in javascript.

A demonstration of what we're gonna do is available online.

Why HTML 5 ?

Indeed ! We could very well be using javascript frameworks such as jQuery which already implements drag & drop There are several problems to that however :

  • You become dependant of the jQuery framework.
  • The thing’s ergonomy could be discussed whenever you have a bit complex objects (in my case, nested arrays, every element of the array should be moveable from one parent to one of the childs and the opposite).
  • It’s quite heavy.
  • It’s not accessible at all when you don’t have a mouse.

That’s why we’re gonna look into implementing this drag & drop thing in HTML5.

The HTML tag

We will create, in our page, two simple elements which will be the containers.

1
2
<div class="box"></div>
<div class="box></div>

Then, in the first one, we’ll add an element which will be moveable to the second.

1
<div class="box"><div class="element" id="first">Hey !</div></div>

In order to see them better, we’ll add a bit of style.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.box {
  border: 1px solid #CCC;
  width: 150px;
  height: 150px;
  float: left;
  margin: 10px;
}
.element {
  width: 50px;
  height: 50px;
  background-color: #CCCCCC;
  margin: 5px;
  padding: 3px
}

We know have all the needed elements to make a simple drag & drop in our page. Let’s move it.

The events

We have access to several new events which allows us to activate that drag & drop.

Moving the element

Only one event will be needed for now : ondragstart. This event is triggered whenever you start the drag & drop on an object which allows it.

To make an element draggable, we must add it the draggable=true attribute. Then in the box which contains it, we add the appropriate event.

1
2
3
4
function dragStart(event) {
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData("Text", event.target.getAttribute('id'));
}

And in the HTML:

1
2
3
<div class="box" ondragstart="dragStart(event);">
    <div id="first" class="element" draggable="true">Hey !</div>
</div>

Let’s analyse that code.

The dataTransfer object

The two methods used are part of the dataTransfer object. It’s a new object of HTML5. It allows you to keep track of some datas between events.

So, when in an event, we update a data in dataTransfer, it’ll be accessible to all the other events. Like that, we can save datas and get them back in an other event. This will be very useful to move the appropriate object.

effectAllowed allows us to define the type of move that we’re allowing. The moved are the following :

  • all - The event can be copied, moved and linked.
  • copy - The event can be copied.
  • copyLink - The event can be copied and linked.
  • copyMove - The event can be copied and moved.
  • link - The event can be linked.
  • linkMove - The event can be moved and linked.
  • move - The event can be moved.
  • none - The event can’t be copied, moved nor linked.
  • uninitialized - Default value, which means “move” for editable elements, “link” for anchors and “copy” for anything else.

setData allows us to define a value to our dataTransfer. Here, we define the element’s id. But you could define whatever you want and which will allow you to get back that element thereafter.

The "Text" key isn't definable as you wish. It means the format of the string we transmis (here, some text). Some browsers, like Firefox, accepts any value. Chrome, however, will require you to use the appropriate one.

Our object is now moveable in the page. Let’s drop it in the second box.

Dropping the element

Just being able to move the elemnt won’t bring us very far. In order to drop it, we’ll add two events : ondragover and ondrop.

ondragover is executed whenever our mouse goes over an element when dragging. It’ll allow us to allow or not dropping the element in the second box.

By default, javascript doesn’t accepts that we drop the element. Consequently, we must return false to stop propagating the event and don’t have the default behavior.

ondrop is executed when we drop the element in the second box. That’s when we effectively move the element in the dom.

Here’s what we get.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function dragStart(event) {
  event.dataTransfer.effectAllowed = 'move';
  event.dataTransfer.setData("Text", event.target.getAttribute('id'));
}

function dragOver(event) {
  return false;
}

function drop(event) {
  var element = event.dataTransfer.getData("Text");
  event.target.appendChild(document.getElementById(element));
  event.stopPropagation();

  return false;
}

And in the HTML:

1
2
3
4
<div class="box" ondragstart="dragStart(event);" ondragover="return dragOver(event);" ondrop="return drop(event);">
    <div id="first" class="element" draggable="true">Hey !</div>
</div>
<div class="box" ondragstart="dragStart(event);" ondragover="return dragOver(event);" ondrop="return drop(event);">

Try it yourself. You can drag/drop the element from a box to an other ! :-)

You can use the online demonstration to try it.

All the available events

We’ve seen here how to something very simple. However it’s possible to make it more complex depending of your needs. Here’s all the events you can use.

  • dragstart - Represents the beginning of the move. It’s executed whenever you start moving an element.
  • drag - Event executed at regular intervals whenever you’re moving (the HTML5 documentation says every 350ms). If it returns false, the move it stopped and canceled.
  • dragenter - Event executed whenever the event you’re moving is coming into an other element.
  • dragleave - Event executed whenever the event you’re moving leaves an other element.
  • dragover - Event executed whenever you’re coming above an other element. If you let it’s propagation continue (if you don’t return false), it won’t be possible to drop the object you’re moving in that element.
  • drop - Event executed when you drop the object in an other element.
  • dragend - Event executed when the move ends.

Conclusion

Right now, only Opera doesn’t supports drag & drop. All other recent browsers have it. This solution is, of course, to be prefered to any full javascript one which will only simulate something which can be natively managed by the browser.