HTML5 Drag & Drop
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.
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.
<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.
<div class="box"><div class="element" id="first">Hey !</div></div>
In order to see them better, we'll add a bit of style.
<style type="text/css">
.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
}
</style>
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.
<script type="text/javascript">
function dragStart(event) {
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData("Text", event.target.getAttribute('id'));
}
</script>
<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.
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.
<script type="text/javascript">
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;
}
</script>
<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 ! :-)
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.
The image at the left is the search interface for the application on which I'm working.
