Drag and Drop in HTML 5

Introduction

 
 
The Drag and Drop API is one of the most important parts of the HTML5 API specifications because more and more sites are using the drag and drop functionality. It talks about dragging an object on the site and dropping it anywhere. It further extends drag and drops for use between browsers and your computer which was impossible earlier (they stated security as the reason).
 
The DnD API specification of HTML5 is based on Microsoft's drag & drop implementation which came in IE5.0 and later adopted by both IE and Safari. While building HTML5 specifications for drag and drop, this was taken as the base.
 

Browser Support

 
The following browsers support the DnD APIs of HTML 5:
  • Chrome 4+: After version 4 of Chrome, the DnD APIs are supported. Chrome & Safari are the most updated with the HTML 5 specifications. 
     
    In fact, Google recently provided a new feature in Gmail, that you can drag & drop your attachment to the desktop if you are using Google Chrome.
     
  • Safari 4+: After version 4, Safari is also supporting the DnD APIs of HTML 5.
  • Firefox 3.5+: Firefox started its support with version 3.5 and above.
  • IE 7: Internet Explorer claims to support the API specification partially for IE7 and above. I am not sure what it means :). In fact, this is a strange inconsistency, especially since the spec is supposed to be based on the IE implementation.
If you want to see whether your browser supports the native HTML5 specifications or not, you can put the following check-in your code
  1.  if (Modernizr.draganddrop)  
  2.    // support   
  3. else        
  4.    // does not support  
Caution: The way browsers have implemented drag and drop is very different from the specifications in the API. So it may be a challenge to provide DnD functionality across browsers seamlessly to the users.
 

This API work in two steps:

 
Step 1: First declare an Element to be draggable. This can be done by defining the draggable="true" attribute of that object.
 
Links & Images are draggable by default.
 
Step 2: Listen to the drag start event and set the data being dragged in the drag transfer object of the event. You may call the preventDefault function of the event to stop the drag (in the case when said data of the object is being dragged rather than the entire object itself).
 
For example: If we have declared an article object like below (article object is also introduced in HTML 5, you may think of it as a div tag of previous HTML versions).
  1. <article id="dragMe1" draggable="true" ondragstart="return dragStart(event)" ondragend="return dragEnd(event)"> Drag to Green</article>   
The dragStart function will be something like below:
  1. function dragStart(e) {  
  2.     e.dataTransfer.effectAllowed='move';        
  3.     e.dataTransfer.setData("Text", e.target.getAttribute('id'));         
  4.     e.dataTransfer.setDragImage(e.target,0,0);         
  5.     return true;   
  6. }  
The setDragImage function sets the image which you will see when your object is being dragged.
 
Step 3: Define a drop target for the dragged object. The drop target must listen to at least the 3 events:
  • Dragenter
  • Dragover - must be canceled (return false) before the object is allowed to drop.
  • Drop
The dragEnd event can be used if we want to perform some operation on the original event being dragged, such as removing the original object from the view once the drag is complete.
 
We can also transfer data between the drag & drop event using the data-transfer object of event. The data can include text, images, and files.

 
Demo Code:

 
The following code uses other features (besides DnD) of HTML5 specifications, such as the DOCTYPE does not have a DTD, which we used to give in the prior versions of HTML. Notice also a few other differences in the presentation; I have not used the <div> tags but the HTML5 specific <section> and <article> tags.
 
Copy and paste the following code and feel free to play with it :)
  1. UTF-8" http-equiv="content-type"/>  
  2. <title>Drag-n-Drop demo</title>  
  3. <style> 
  4. #mainText{color:red}  
  5. #section1, #section2, #section3 {float:left; width:165px; height:165px; padding:20px; margin:10px}  
  6. #section1 { background-color: #ff0000; }  
  7. #section2 { background-color: #00ff00; }  
  8. #section3 { background-color: #0000ff; }  
  9. #dragMe1, #dragMe2, #dragMe3 { width:100px; height:30px; padding:5px; margin:5px; }  
  10. </style>  
  11. <script type="text/javascript">  
  12. function dragStart(e) {  
  13.     e.dataTransfer.effectAllowed='move';  
  14.     e.dataTransfer.setData("Text", e.target.getAttribute('id')); 
  15.     e.dataTransfer.setDragImage(e.target,0,0);  
  16.     return true;  
  17. }  
  18. function dragEnd(e) {  
  19.     e.dataTransfer.clearData("Text");  
  20.     return true  
  21. }  
  22. function dragEnter(e) {  
  23.     var idelt = e.dataTransfer.getData("Text");  
  24.     return true;  
  25. }  
  26. function dragOver(e) {  
  27.     var articleID = e.dataTransfer.getData("Text");  
  28.     var sectionId = e.target.getAttribute('id');  
  29.     if( articleID=="dragMe3" || sectionId == "section1" || (sectionId == "section2" && articleID == "dragMe1") ||  
  30.  (sectionId == "section3" && articleID == "dragMe2") )  
  31.  return false;  
  32.     else  
  33.  return true;  
  34. }  
  35. function dragDrop(e) {  
  36.     var idelt = e.dataTransfer.getData("Text");  
  37.     e.target.appendChild(document.getElementById(idelt));  
  38.     e.stopPropagation();  
  39.     return false;   
  40. }  
  41. </script>undefined</head>undefined<body>  
  42. <h1>Drag-n-drop Demo</h1>  
  43. <article id="mainText"> Select a text from Red section and try dropping it to Green & Blue</article>  
  44. <section id="section1" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)">  
  45.     <article id="dragMe1" draggable="true" ondragstart="return dragStart(event)" ondragend="return dragEnd(event)">Drag to Green</article>  
  46.     <article id="dragMe2" draggable="true" ondragstart="return dragStart(event)" ondragend="return dragEnd(event)">Drag to Blue</article>  
  47.     <article id="dragMe3" draggable="true" ondragstart="return dragStart(event)" ondragend="return dragEnd(event)">Drag to Any</article>  
  48. </section>  
  49. <section id="section2" dropZone="f:image/png" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)"></section>  
  50. <section id="section3" ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)" ondragover="return dragOver(event)"></section>