Drag and drop in HTML
• Blog post by Asif Khan - Published at 2022-06-03
Introduction
The questions that strike someone’s mind are ‘What is this Drag and Drop API? What’s the purpose of using it?. So let’s dig in deep and find out the answers to these questions.
What is Drag and Drop API?
As the name suggests, this API lets us grab an element by double-tapping the left mouse button and moving along the way where we want to place an element or to drop an element as you can say. And this movement of an element from its initial position to its destination(or where we are dropping it) is called dragging. This is by far the most simplistic definition of Drag and Drop API and in fact, nothing is complex about it.
What’s the purpose of using it?
The purpose is straightforward i.e, just for the sake of user experience, we are using this Drag and Drop feature. In this part of the world, user’s tastes, user’s experience is all we have to take into consideration while developing web applications. This feature provides users highly interactive experience. For example, let’s consider a scenario where you have to upload a file to any website. There are two options for doing that and the first option is the old-fashioned one i.e, to navigate through the entire file structure within a folder and select the appropriate file to upload. But the second option is a more modern and very simple one, just drag that particular file and drop it to the placeholder provided by the website and it’s done. See how interactive and simple it is, that’s what users need and we have to take it into consideration.
What needs to keep in mind when using this API?
Before we get into the meat and potatoes of this API, let’s discuss the minor things that we have to keep in mind before using this API. This will prevent us from falling into various pitfalls.
While performing the events related to drag and drop, we have to explicitly disable the other events of the DOM like onMouseDown, onMouseUp, onMouseOver, etc. as these events restrict the drag and drop event to happen. So in our handler function, we have to disable this default behavior by writing an event.preventDefault(). We’ll see how we can do that with an example.
Whenever we drag an element we have to make use of the data transfer object which comes with the drag and drop API of HTML. It holds the data and other information of the particular draggable element and we can make use of this information when we drop the element. So data transfer object holds the state of data of an element that we are dragging.
The above two points will become crystal clear when we discuss each individual topic and implement them in our basic drag and drop application.
Drag/Drop Events
There are many events and event handlers in this API. Using these events we can control the entire Drag and Drop lifecycle. The Drag and Drop lifecycle of an element is nothing but the entire phase which starts when we grab an element, moving it along the way and finally drop it inside a container. For example, the drag start event occurs when we grab an element with a mouse.
Let’s examine all the events and event handlers associated with it:
- drag: This event occurs when we are dragging an element and we can handle this event by specifying the ondrag event handler inside an element as an attribute. The value to this attribute will be a function that gets invoked when this event is fired.
- dragend: This event occurs when we stopped dragging an element (drag operation ends) such as releasing a mouse button or hitting the ESC key. We can handle this event by specifying the ondragend event handler inside an element as an attribute.
- dragenter: This event occurs when the element enters a valid drop container or target. And of course, we can handle it using an ondragenter handler.
- dragleave: This event occurs when the element leaves a valid drop container or target. The associated event handler is ondragleave.
- dragover: This event occurs when we drag an element over a valid droppable container or target. This event is fired every few hundred milliseconds. ondragover is the associated event handler for this.
- dragstart: This event occurs when the user starts dragging an item. The moment when an element is grabbed. ondragstart is the associated event handler. drop: This event occurs when the element is dropped into a droppable target container. ondrop is the associated event handler.
Drag/Drop Interfaces
There are four major HTML Drag and Drop interfaces namely DragEvent, DataTransfer, DataTransferItem and DataTransferItemList.
DragEvent:
The DragEvent interface is a DOM event that will be initiated when a user puts a mouse pointer and starts dragging the element. This interface provides an object which is very useful to us as we can utilize it to add drag and drop functionality to it.
DataTransfer:
The DataTransfer object is used to hold the data that is being dragged during a drag and drop operation. This is by far the most important one.
DataTransferItem:
The DataTransfer object contains the list of drag data items whereas the DataTransferItem object represents one drag data item.
DataTransferItemList:
The DataTransferItemList object is a list of DataTransferItem objects representing items being dragged. During a drag operation, each DragEvent has a dataTransfer property and that property is a DataTransferItemList.
Understanding By Example
We’ll make a simple Drag and Drop application where we drag and drop the image from one container to another by making use of the above concepts.
The application looks something like this:
Let’s write some HTML for this:
<body> <div class="drop-box"> <div class="draggable-element" id="drag-me"></div> </div> <div class="drop-box"></div> <div class="drop-box"></div> </body>
Let’s style the HTML using CSS:
<style > body { background-color: rgb(238, 199, 185); display: flex; justify-content: center; align-items: center; } .draggable-element { background-image: url("https://source.unsplash.com/145x145/?person"); position: relative; top: 7px; left: 5px; height: 145px; width: 145px; /* By setting cursor pointer you'll get the essence of dragging something. */ cursor: pointer; } .drop-box { display: inline-block; height: 155px; width: 155px; margin: 10px; background-color: white; border: 2px solid black; }
We’ve taken a random image from https://source.unsplash.com. But you can choose whichever image you want.
Now after styling our HTML we have to implement drag and drop functionality so that we can drag the image to one of the containers.
For making any element draggable, we have to explicitly provide an attribute 'draggable' to the corresponding element and set its value to true as by default it is set to false.
<div class="draggable-element" draggable="true" id="drag-me"></div>
Now we have to provide an event handler ondragstart as an attribute to this element to set or store the data in the dataTransfer object via invoking our function dragIt().
<div class="draggable-element" draggable="true" ondragstart="dragIt(event)" id="drag-me" ></div>
Implementation of dragIt() function:
const dragIt = (event) => { event.dataTransfer.setData("text", event.target.id); };
This function takes a DOM event object as a parameter. This event object has all the necessary information about the element such as its ID. We have set the data associated with this element such as its id to the dataTransfer object using the setData() function. setData() set the data for a given type. If data for the type does not exist, it is added at the end, such that the last item in the types list will be the new format. If data for the type already exists, the existing data is replaced in the same position.
We have made an element draggable, now let’s make a container droppable so that we can drop this element into it:
<div class="drop-box" ondragover="allowDrop(event)"></div>
To make a container droppable we have to disable the default onmouse events of the target element where we are dropping (This is the point we have to keep in mind, as I mentioned earlier).
So to make the container droppable we use the ondragover attribute as this event handler handles the event when the element is dragged over the target container. We pass in a function allowDrop() which allows the element to be dropped inside the target container.
const allowDrop = (event) => { event.preventDefault(); };
event.preventDefault() prevents the default mouse events and allows the elements to be dropped on it.
Just making the container droppable doesn’t mean we can place an element inside of it. For that, we have to append the element as a child inside the container. So, we have to append the element inside of it and the better time of doing that is when we drop an element. So we use the ondrop event handler as drop event is taking place.
<div class="drop-box" ondragover="allowDrop(event)" ondrop="dropIt(event)" ></div>
This event handler takes the dropIt() function as its value which is invoked to append the element as its child.
const dropIt = (event) => { let data = event.dataTransfer.getData("text"); event.target.append(document.getElementById(data)); };
Now it’s done. We’ve made a drag and drop application. You can drag and drop it in one of the three containers.
The image is of course different because every time we reload a page we get a different image as we’ve used a random image from source.unsplash.com.
Entire code at one glance:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Drag and Drop API</title> <style> body { background-color: rgb(238, 199, 185); display: flex; justify-content: center; align-items: center; } .draggable-element { background-image: url("https://source.unsplash.com/145x145/?person"); position: relative; top: 7px; left: 5px; height: 145px; width: 145px; /* By setting cursor pointer you'll get the essence of dragging something. */ cursor: pointer; } .drop-box { display: inline-block; height: 155px; width: 155px; margin: 10px; background-color: white; border: 2px solid black; } </style> </head> <body> <div class="drop-box" ondragover="allowDrop(event)" ondrop="dropIt(event)"> <!-- For making any element draggable, we have to explicitly provide an attribute 'draggable' to the corresponding element and set its value to true as by default it is set to false. --> <div class="draggable-element" draggable="true" ondragstart="dragIt(event)" id="drag-me" ></div> </div> <div class="drop-box" ondragover="allowDrop(event)" ondrop="dropIt(event)" ></div> <div class="drop-box" ondragover="allowDrop(event)" ondrop="dropIt(event)" ></div> </body> <script> const dragIt = (event) => { event.dataTransfer.setData("text", event.target.id); }; const allowDrop = (event) => { event.preventDefault(); }; const dropIt = (event) => { let data = event.dataTransfer.getData("text"); event.target.append(document.getElementById(data)); }; </script> </html>
Key takeaways
Finally, we are at the fag end of the topic and most probably the topic is done and dusted. To summarize this, we started out with a brief introduction of the topic and got to know the motivation behind using the Drag and Drop feature and then we explored all the core concepts related to Drag and Drop API. Finally, we made a simple Drag and Drop application using all the necessary concepts of Drag and Drop. So it is not the end of the road here, there are way more things present in this API just expand your domain and explore all about it as learning has no endpoint. Keep a closer eye on our future posts as they may prove helpful to you.