Drag and Drop Tutorial
The Drag and Drop API is perhaps the most complicated and controversial of all the HTML5 APIs. While it is a welcome addition to the HTML5 specification as part of a move to a more applications based web experience, its somewhat complicated implementation procedures has raised the ire of many web developers. Nonetheless, it does offer the possibility of including some fun interactivity to your website.
This tutorial will give a very basic and simplified example of a somewhat complicated API. A couple of the latest browsers, like Chrome, and Safari have included the API. It is recommended that you use one of these browsers to test this example.
-> See live example Here
Let us start with the HTML we are going to work with. We have an image and two drop zones represented by two <div> elements.
<body>
<p> Drag this image into one of the boxes below.</p>
<img id= "dragImg" src= "images/flower.png" />
<div id= "dropzone1"><p>Drop Box A</p> </div>
<div id= "dropzone2" ><p>Drop Box B</p></div>
</body>
We will style the elements to look like the image below.

To make any HTML element moveable, you have to add to it the attribute draggable. Its values can be set to true or false. In order the make the element moveable, you have to set the attribute to true.
In several of the browsers images and links are draggable by default so it is not necessary to set the attribute. However it is recommended that you set the attribute to avoid any browser inconsistency.
In this case, since the image is what we would like to move, we will set its draggable attribute to true.
<img id= "dragImg" draggable= "true" src= "images/flower.png" />
Next in order to make the drag happen, we have to set up several functions using JavaScript. These functions have to be trigged following specific browser events. There are several new events that go with the drag and drop API. To get a full list and explanation of these events click here.
The first function we must set up will control the beginning of the drag or the dragstart event. The event is trigged when the element to be moved is clicked and the drag beings. The function will have to grab the element to be moved so that another function can put it in another location.
To make this function work we will need to use the dataTransfer object. (Click here for details of the dataTrasnfer object.) Using the dataTransfer object, we can set the effectAllowed value. In other words we can set what we want the browser to do with the element being dragged. We can set it to copy the element, move the element or link it to another element. In our example, we will set the effectAllowed value to “move,” since we want to be able to remove the image from its original position and put it in one of the boxes.
Next we want the function to grab the image so that it can be moved. We will use the setData() method to grab the element being moved using its id. Finally we want the function to return true.
function dragStart(ev) {
ev.dataTransfer.effectAllowed= 'move';
ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));
return true;
}
The next step is to set up the function needed to handle our drop zones. In order to get the drag and drop API work properly, the official specifications require you to turn off several default behaviors. The second function we must set up is associated with the dragenter event. This event occurs when the element being dragged enters the drop zone, before the actual drop occurs. Our function is triggered when this event occurs. However, we will need to turn off the default browser behavior for this event. To do that we will use the preventDefault() method. This function should also be set to return true.
function dragEnter(ev) {
event.preventDefault();
return true;
}
Next we need to prevent another event triggered when the element to be dropped moves over the target area. This is the dragover event. It occurs, just like the drageneter event, when the element moves over the target area before it is dropped. We will have to set up a function to prevent the default behavior and return false.
function dragOver(ev) {
return false;
}
The last function we must set up will handle the actual drop part. This function will be triggered when the drop event occurs. The drop event is triggered when the element being dragged is finally dropped over the target area. The function uses the getData() to retrieve the element being moved using its id. The element is then inserted into the drop zone element as a child element. In our example the image is added to the <div> element as a child element of the <div> element, making the drop complete. As with the other drop related events, we have to prevent the browser defaults, in order for this function to work properly.
function dragDrop(ev) {
var eleid = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(eleid));
ev.preventDefault();
}
Now let us tie these functions to our HTML. First we have to get dragStart() function we created earlier to trigger when the image is being dragged. To do this we add the ondragstart event listener to the image element. Since this is the only function associated with the object being dragged, we don’t have to add anything else.
<img id= "dragImg" draggable= "true" ondragstart= "return dragStart(event)" src= "images/flower.png" />
Next we must add the events associated with the drop zones to the drop elements. In our example there are three functions associated with the drop zones. The dragEnter() function must be triggered when the dragenter event occurs. To create the link between the event and function, we use the ondragenter event listener. We also have to create a link between the dragover event and the dragOver() function we created. We can do this by using the ondragover event listener. Finally we need to trigger the dragDrop() event when the actual drop occurs or when the drop event occurs. Once again we need to add an event listener. In this case we have to add the ondrop event listener.
In our example we have two drop zones. The same three function will added to both of these separate drop zones.
<div id= "dropzone1" ondragenter= "return dragEnter(event)" ondragover= "return dragOver(event)" ondrop= "return dragDrop(event)" ><p>Drop Box A</p> </div>
<div id= "dropzone2" ondragenter= "return dragEnter(event)" ondragover= "return dragOver(event)" ondrop= "return dragDrop(event)" ><p>Drop Box B</p></div>
Here is our full script
<script>
//This function starts the event
function dragStart(ev) {
ev.dataTransfer.effectAllowed= 'move'; //Makes the element movable
ev.dataTransfer.setData("Text", ev.target.getAttribute('id')); // Grabs the element by its id
return true;
}
//Prevents default but does not turn it off
function dragEnter(ev) {
event.preventDefault();
return true;
}
//Turns off the dragover event and prevents default behavior
function dragOver(ev) {
return false;
}
//This function performs the actual drop
function dragDrop(ev) {
var eleid = ev.dataTransfer.getData("Text"); //The dragged element’s id is set to a variable
ev.target.appendChild(document.getElementById(eleid)); //The element is added as a child of the target
ev.preventDefault();
}
</script>
Now let us look at the API in action.
Open up the example in a browser. Now click and hold down on image as shown below. As you can see, not a whole lot seems to be happening with the browser. But behind the scenes, the mouse click is actually triggering the dragstart event, which in our script sets the dragStart() function in motion. The function as we know grabs the image element by its id and passes it on to the the setData() method.

Now let us move the image. Click and drag the image to the area in between the two boxes. When the image is dragged over an area where a drop is not permitted, the pointer changes into a “not allowed” symbol. At the same time, while the image remains in its original location, a transparent copy of the image appears with the pointer and will move with it.

Now let us look at what happens when you hover the image over one of the drop boxes. When the image is hovered over an area of the browsers where a drop is permitted, the pointer icon changes from a “not allowed” symbol to rectangular icon. Behind the scenes, as the image is hovered over the drop area, it triggers the dragenter event.

Now let us see what happens when the drop actually happens. When you release the mouse over the box, the image disappears from its original position and appears inside the box. If you recall, when the mouse is released, it triggers the drop event, which in turn triggers the dragDrop() function we created. The function grabs the image using the getData() method. It then adds the image as a child element of the <div> element or the drop box A.

Once the image is inside drop box A, you can still move it to any other part of the browser where a drop is permitted. In our example, since both boxes have the drop functions attached to them, you can move the image from one box to the other. Once again you can see the pointer change from a “not allowed” symbol to a small rectangle as we drag the image over drop box B.

When you release the image over box B the dragDrop() function is triggered and the image disappears from the box A and appears in box B.

You can move it back to box A.

Release the mouse and image is now in box A.

-> See live example Here

May 10th, 2011 at 2:40 pm
Thank you for this tutorial but I still am confused.
I want to use drag and drop and re-position img elements. That is, I’m not trying to drop something in a bin, but move something to a location. So for this, I think I need to know the mouse coordinates
when the thing is picked up and also when it is put down.
This is what I wrote:
http://faculty.purchase.edu/jeanine.meyer/html5/dragtest.html
It sort of works some of the time, but not exactly and sometimes it jumps.
Any help would be appreciated.
[Reply]
February 13th, 2012 at 9:24 am
Thanks a lot for this tutorial, its so useful,
I tried it Firefox and it worked very well, but on IE it doesn’t I got these errors:
1) ‘target’ is null or not an object line 71
line 71 refers to: ev.dataTransfer.setData(“Image”, ev.target.getAttribute(‘id’)); // Grabs the element by its id
2) Object doesn’t support this property or method line 77
line 77 refers to: ev.preventDefault();
[Reply]