Let's continue to develop the example. We show how to drag an element and detect a drop, receiving a value which corresponds to the dragged element. Then we change the page content accordingly.
When a draggable <li> element is being dragged, in the dragstart handler get the value of its data-value attribute and copy it to the "drag and drop clipboard" for later use.
When data is copied to this clipboard, a key/value pair must be given. The data copied to the clipboard is associated with this name.
The variable event.target at line 5 below is the <li> element that has been dragged, and event.target.dataset.value is the value of its data-value attribute (in our case "apples", "oranges" or "pears"):
function dragStartHandler(event) {
console.log('dragstart event, target: ' + event.target.innerHTML);
// Copy to the drag'n'drop clipboard the value of the
// data* attribute of the target,
// with a type "Fruit".
event.dataTransfer.setData("Fruit", event.target.dataset.value);
}
Any visible HTML element may become a "drop zone"; if we attach an event listener for the drop event. Note that most of the time, as events may be propagated, we will also listen for dragover or dragend events and stop their propagation. More on this later...
<div ondragover="return false" ondrop="dropHandler(event);">
Drop your favorite fruits below:
<ol id="droppedFruits"></ol>
</div>
Whenever the mouse is moving above a (any) drop zone, dragover events will fire. Accordingly, a large number of dragover events may need to be handled before the element is finally dropped. The ondragover handler is used to avoid propagating dragover events. This is done by returning the false value at line 1.
function dropHandler(event) {
console.log('drop event, target: ' + event.target.innerHTML);
...
// get the data from the drag'n'drop clipboard,GET
// with a type="Fruit"
var data = event.dataTransfer.getData("Fruit");
// do something with the data
...
}
Typically, in the drop handler, we need to acquire data about the element that has been dropped (we get this from the clipboard at lines 6-8, the data was copied there during step 1 in the dragstart handler).
Try it in your browser below or play with it at CodePen:
Source code:
<!DOCTYPE html>
<html>
<head>
<script>
function dragStartHandler(event) {
console.log('dragstart event, target: ' +
event.target.innerHTML);
// Copy to the drag'n'drop clipboard the value
// of the data* attribute of
// the target, with a type "Fruits".
event.dataTransfer.setData("Fruit",
event.target.dataset.value);
}
function dropHandler(event) {
console.log('drop event, target: ' +
event.target.innerHTML);
var li = document.createElement('li');
// get the data from the drag'n'drop clipboard,
// with a type="Fruit"
var data = event.dataTransfer.getData("Fruit");
if (data == 'fruit-apple') {
li.textContent = 'Apples';
} else if (data == 'fruit-orange') {
li.textContent = 'Oranges';
} else if (data == 'fruit-pear') {
li.textContent = 'Pears';
} else {
li.textContent = 'Unknown Fruit';
}
// add the dropped data as a child of the list.
document.querySelector("#droppedFruits").appendChild(li);
}
</script>
</head>
<body>
<p>What fruits do you like? Try to drag an element!</p>
<ol ondragstart="dragStartHandler(event)">
<li draggable="true" data-value="fruit-apple">Apples</li>
<li draggable="true" data-value="fruit-orange">Oranges</li>
<li draggable="true" data-value="fruit-pear">Pears</li>
</ol>
<div ondragover="return false" ondrop="dropHandler(event);">
Drop your favorite fruits below:
<ol id="droppedFruits"></ol>
</div>
<body>
<html>
In the above code, note:
Line 44: we define the drop zone (ondrop=...), and when a drag enters the zone we prevent event propagation (ondragover="return false")
When we enter the dragstart listener (line 5), we copy the dragged-element's data-value attribute to the drag and drop clipboard with a name/key equal to "Fruit" (line 11),
When a drop occurs in the "drop zone" (the <div> at line 44), the dropHandler(event) function is called. This always occurs after a call to the dragstart handler. In other words: when we enter the drop handler, there must always be something on the clipboard! We use an event.dataTransfer.setData(...) in the dragstart handler, and an event.dataTransfer.getData(...) in the drop handler.
The dropHandler function is called (line 15), we get the object with a name/key equal to "Fruit" (line 21) from the clipboard , we create a <li> element (line 18), and set its value according to the value in that clipboard object (lines 23-31),
Finally we add the <li> element to the <ol> list within the drop zone <div>.
Notice that we use some CSS to set aside some screen-space for the drop zone (not presented in the source code above, but available in the online example):
div {
height: 150px;
width: 150px;
float: left;
border: 2px solid #666666;
background-color: #ccc;
margin-right: 5px;
border-radius: 10px;
box-shadow: inset 0 0 3px #000;
text-align: center;
cursor: move;
}
li:hover {
border: 2px dashed #000;
}