Simple D&D demo.
snippet
<style>
#foobar { background-color:yellow; width:100px; height:100px; cursor:move; }
#catcher { background-color:blue; width:150px; height:150px; padding:5px; margin-bottom:5px; }
</style>
Enable D&D:-
Put the draggable attribute on the element you want to be drag-enabled:
snippet
<div id="catcher">...</div>
<div id="foobar" draggable="true">...</div>
We need to use the JavaScript API and D&D events to tell the browser where the element can be dragged to, and what to do once it's dropped there.
For example, we can listen for the dragstart event, and style the element differently
when it's being dragged (like putting a border around it or making it partially transparent).
snippet
var foobar = document.getElementById("foobar");
foobar.addEventListener("dragstart", function(evt) {
this.style.border = "3px dotted #000"; // black dotted-line border
}, false);
Lets style an element that can receive the drop, so that when the dragged item is over it, it makes it obvious that you can drop the element there (as opposed to just dropping it in any location):
snippet
var catcher = document.getElementById("catcher"); // will catch the dropped element
catcher.addEventListener("dragenter", function(evt) {
this.style.border = "3px solid red"; // make the catcher have a red border
}, false);
catcher.addEventListener("dragleave", function(evt) {
this.style.border = ""; // remove the border from the catcher
}, false);
catcher.addEventListener("dragover", function(evt) {
if (evt.preventDefault) evt.preventDefault();
return false;
}, false);
Add event listeners to the element that catch our dropped element for the dragover, dragenter, and dragleave events.
dragenter and
dragleave - events simply toggle on a red border to our target element to make it clear that
you can drop the element there.
dragover - event is fired continuously while dragging around on top of the target.
So we would not want to toggle on the red border in that handler, as that would create unnecessary work for the browser. However, we do need to prevent that event from various default behavior, depending on the type of element being dragged. This is why we use
preventDefault()
and return false.
Modify our
dragstart event handler to wire up a
dataTransfer object with data that the browser needs for handling the D&D actions
snippet
foobar.addEventListener("dragstart", function(evt) {
this.style.border = "3px dotted #000"; // black dotted-line border
evt.dataTransfer.effectAllowed = "move";
evt.dataTransfer.setData("Text", this.id);
}, false);
effectAllowed property - controls what visual feedback—generally the mouse cursor—the browser gives on the type of drag event that is occurring (move, copy, etc.).
setData(...) - method tells the D&D mechanism in the browser which data from the element being dragged should be dropped into the target element, otherwise known as the drop catcher. Here we specify that only the id property of the original element is transferred, which is used later to actually move the element.
Define a
dragend event handler to clear up the visuals, and a drop event handler, to actually do the moving of our element:
snippet
foobar.addEventListener("dragend", function(evt) {
this.style.border = ""; // remove the border
}, false);
catcher.addEventListener("drop", function(evt) {
if (evt.preventDefault) evt.preventDefault();
if (evt.stopPropagation) evt.stopPropagation();
this.style.border = ""; // remove the border from the catcher
var id = evt.dataTransfer.getData("Text"); // get the id
var elem = document.getElementById(id);
elem.parentNode.removeChild(elem); // remove the element
this.appendChild(elem); // add the element back into our catcher
return false;
}, false);
The drop event handler, we first get the data that was transferred in the drop, which in this case was the id property of the original source element that we dragged. Next, we remove that element from its current location, and finally add it back into the new location inside our catcher container.