HTML5 Drag and Drop API
HTML5 introduced the Drag and Drop API which allows users to manipulate pages using drag and drop actions.
Identifying what is draggable in HTML
To make an element draggable it must have the draggable='true'
attribute added:
<div class="dragme" draggable='true'></div>
Note this does not work as a boolean attribute - using the shortcut <div class="dragme" draggable>
would not work. When not set the default value of auto
will use the browser’s defaults, which will allow text selections, images and links to be dragged.
The ondragstart
event handler
As well as the draggable attribute you must also set up an event handler for the dragstart
event, using either the ondragstart
attribute or adding an event listener for the drag
event:
<div class="dragme1" draggable="true" ondragstart="console.log('Starting drag...')"></div>
<div class="dragme2" draggable="true"></div>
<script>
function onDragStart() {
console.log('Starting drag...');
}
const target = document.querySelector('.dragme2');
target.addEventListener('dragstart', onDragStart);
</script>
The event handler can set the dataTransfer
property that can set the data type and contents of the dragged data, for instance:
e.dataTransfer.setData("text/plain", "This is the data");
to store a string in the drag data.
The drag image
The dataTransfer
object also allows you to set an image to use instead of the default translucent image generated from the drag target:
e.dataTransfer.setDragImage(img, 10, 10);
The drag effect
When dragging an object you can trigger different types of operations on drop. The dataTransfer.effectAllowed
attribute determines this and can be set to values such as copy
to indicate the object will be copied, move
to indicate the object will be moved to the target or link
to indicate a connection will be made between the target and source.
The dragenter
and dragover
events
Up to this point, we have only been concerned with allowing an element to be dragged, however, the default handling for most targets on a page is to not allow a drop, giving you no targets to drag your source to. In order to allow a drop, you must prevent this default handling of drag events, either by returning false from either the ondragover
or ondragenter
<div class="target1" ondragover="return false"></div>
<div class="target2"></div>
<script>
function onDragEnter(e) {
e.preventDefault;
}
const target = document.querySelector('.target2');
target.addEventListener('dragenter', onDragEnter);
</script>
The Drop event
When the user releases the mouse the drag operation ends, and if dropped on a valid drop target (where the dragenter
or dragover
events cancel the default behaviour) the drop
event will fire at the drop target.
Note if the drop is not over a valid target the drop
event will not be fired and the drag operation is cancelled.
The drop event holds the data that was set by dataTransfer.setData
, and the getData
method can now be used to retrieve that data, with a key of the data type to retrieve:
function handleDrop(e) {
const data = e.dataTransfer.getData("text/plain");
e.target.textContent = data;
e.preventDefault();
}
The dragend
event
Finally, the dragend
event is fired at the source of the drag operation. This will be triggered whether the drag was a success or if it was cancelled. If cancelled, the e.dataTransfer.dropEffect
property will be set to none
. The dragend
event handling can be used to perform any cleanup required on the source element.
Examples
Moving an image between boxes
The following CodePen is a simple demonstration of dragging an image between different boxes:
See the Pen Drag and Drop by Neil Lupton (@Neil188) on CodePen.
Using dataTransfer.getData to transfer data
The following CodePen is a mock character set up for a game, which allows you to choose a character class by dragging your choice up the main character panel.
See the Pen Drag And Drop Characters by Neil Lupton (@Neil188) on CodePen.