The HTML5 Drag and Drop (DnD) specification, also known as the HTML5 DnD API defines the event-based drag and drop mechanism that allows a visual element to be moved with a pointing device. The drag involves a mouse down event followed by a mouse move event, and the drop is triggered when the mouse pointer is released. An interesting caveat is that the specification does not define exactly what a drag-and-drop operation actually is, but does state that once implemented, a drag and drop operation must have a starting point (mouse click or file selection), and while there may be any number of intermediate steps, it must have an end point where a mouse or pointer is released, or the operation is cancelled.
Browser support for DnD
Browser support for the HTML5 DnD API is listed below as found on Can I Use Drag and Drop:
- IE 10.0
- Firefox 18.0+
- Chrome 24.0+
- Safari 5.1+
- Opera 12.1+
Currently the DnD API is not supported by any mobile browsers, and one known issue exists with Chrome, where DataTransfer.addElement is not implemented. The short table of browser support is displayed in Figure B below:
Click to enlarge.
DnD Events
There are a number of events that can be attached during the entire DnD process, and these events are fired during various stages of the typical drag and drop operation. Note that during the drag events any mouse events are not fired during the drag operation. The seven DnD events as listed by the specification are displayed in the table below:
Events |
Description |
dragstart | Fired on an element when a drag is started. As the user is requesting to drag the element the dragstart event is fired, and during this event, a listener would set information such the drag data and image to be associated with the drag. |
dragenter | Fired when the mouse is first moved over an element while a drag is occurring. A listener for this event should indicate whether a drop is allowed over this location. If there are no listeners, or the listeners perform no operations, then a drop is not allowed by default. This is also the event to listen to if you want to provide feedback that a drop is allowed such as displaying a highlight or insertion marker. |
dragover | This event is fired as the mouse is moved over an element when a drag is occurring. Much of the time, the operation that occurs during a listener will be the same as the dragenter event. |
dragleave | This event is fired when the mouse leaves an element while a drag is occurring. Listeners should remove any highlighting or insertion markers used for drop feedback. |
drag | This event is fired at the source of the drag, that is, the element where dragstart was fired, during the drag operation. |
drop | The drop event is fired on the element where the drop was occurred at the end of the drag operation. A listener would be responsible for retrieving the data being dragged and inserting it at the drop location. This event will only fire if a drop is desired. It will not fire if the user cancelled the drag operation, for example by pressing the Escape key, or if the mouse button was released while the mouse was not over a valid drop target. |
dragend | The source of the drag will receive a dragend event when the drag operation is complete, whether it was successful or not. |
DataTransfer Object Property
The dataTransfer property of all drag events is where the real mechanism behind the API occurs, this is where it holds data about the drag and drop operation. The dataTransfer objects are used during the drag-and-drop events, and are only valid while those events are being fired. The nine dataTransfer attributes as listed in the specification and their associated descriptions are listed below:
DataTransfer Object |
Description |
dataTransfer.dropEffect [ = value ] | Returns the kind of operation that is currently selected. If the kind of operation isn’t one of those that are allowed by the effectAllowed attribute, then the operation will fail. Can be set, to change the selected operation
The possible values are “none”, “copy”, “link”, and “move”. |
dataTransfer.effectAllowed [ = value ] | Returns the kinds of operations that are to be allowed. Can be set (during the dragstart event), to change the allowed operations.
The possible values are “none”, “copy”, “copyLink”, “copyMove”, “link”, “linkMove”, “move”, “all”, and “uninitialized”, |
dataTransfer.items | Returns a DataTransferItemList object, with the drag data. |
dataTransfer.setDragImage(element, x, y) | Uses the given element to update the drag feedback, replacing any previously specified feedback. |
dataTransfer.types | Returns an array listing the formats that were set in the dragstart event. In addition, if any files are being dragged, then one of the types will be the string “Files”. |
data = dataTransfer.getData(format) | Returns the specified data. If there is no such data, returns the empty string. |
dataTransfer.setData(format, data) | Adds the specified data. |
dataTransfer.clearData( [ format ] ) | Removes the data of the specified formats. Removes all data if the argument is omitted. |
dataTransfer.files | Returns a FileList of the files being dragged, if any. |
Online demonstrations
Several places offer nice demonstrations of the DnD in action, including using file upload which incorporates the HTML5 File API as well. Several links to the demonstrations are listed below:
- HTML5 Drag and Drop File Upload with Canvas – this demo is an example of HTML5 drag and drop with file upload and includes the ability to resize, crop or reformat, or filter the uploaded image through HTML5 canvas before sending it to the server.
- Microsoft Test Drive Magnetic Poetry – is an example of a site that uses HTML5 Drag and Drop to create an experience that previously would have needed a plug-in or JavaScript library.
- Implementing HTML5 Drag and Drop Shopping Cart Demo – This demo shows an example of implementing native drag and drop to build a simple shopping cart interface.
- Drag’n Drop – Towers of Hanoi – Featured in the Mozilla Developers Network, it uses the DnD API to implement the popular classic game of “Towers of Hanoi”, along with a few lines of CSS3 for shadows, gradients, positioning, and border radius. The game demo is shown in Figure C below:
Figure C
Code snippet example
This code snippet below, modified from Tutorials Point – HTML5 Drag and drop, demonstrates a simple example of dragging a purple box into a pink box as shown in Figure D (the ‘click’), Figure E (the ‘drag’), and Figure F (the ‘drop’).
<script type="text/javascript">
function dragStart(ev) {
ev.dataTransfer.effectAllowed='move';
ev.dataTransfer.setData("Text", ev.target.getAttribute('id'));
ev.dataTransfer.setDragImage(ev.target,0,0);
return true;
}
function dragEnter(ev) {
event.preventDefault();
return true;
}
function dragOver(ev) {
return false;
}
function dragDrop(ev) {
var src = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(src));
ev.stopPropagation();
return false;
}
</script>
<article>Try to move the purple box into the pink box.</article>
<article id="boxB" ondragenter="return dragEnter(event)"
ondrop="return dragDrop(event)"
ondragover="return dragOver(event)">Dustbin</article>
<article id="boxA" draggable="true"
ondragstart="return dragStart(event)">
<p>Drag Me</p>
</article>
Figure D
Figure E
Figure F
Other resources
- Mozilla Developer Network Drag and Drop – Firefox and other Mozilla applications support a number of features for handling drag and drop.
- Dev.Opera HTML5 Drag and Drop – Describes in what manner the Opera browser supports the DnD API.
- HTML5.1 Nightly Editors Draft – Drag and Drop – The nightly update of the latest HTML5 editor’s draft.
- Android Developers Drag and Drop – Not an example of HTML5, but it is the Android drag/drop framework to allow users to move data from one View to another View on Android devices and browsers.