Loading...

How To Create an HTML5 Drag and Drop Component

With HTML5 drag and drop functions, you can implement dynamic interactive components in your websites. In this tutorial, we will build a simple drag and drop component in which the user will be able to move a selection of words around to form a sentence. The drag and drop functionality can be used to create games or simply to enhance user interaction with your sites. The process is fairly straightforward, with JavaScript and a little CSS code facilitating the end result.

Here is a preview of what we are working towards:

drag and drop component

The component should function in recent versions of the major desktop browsers, but will not be reliable in older browsers or on mobile. Although the component we create here is simple, the tutorial acts as a foundation for understanding drag and drop functionality in HTML5 and JavaScript, so you should be able to apply the basic principles to your own projects, building complexity into them as necessary.

Create Your Page

Start by creating your HTML5 page outline - use the following template:

<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
</style>
<script type="text/javascript">
</script>
</head>
<body>
</body>
</html>

We will drop JavaScript and CSS in the HTML page body as we go along.

Add Some Movable Elements

In the page body, we are going to create six div elements, each with a child div inside it. Each parent div will represent a drop position for the component, with the six child elements able to be dragged and dropped into these parent elements. Add the first set inside the body section of the page:

<div id="box1">
<div class="mover">Page</div>
</div>

Notice that the parent element has an ID - we will use this to identify it in JavaScript later. The child element has a class attribute and a single word as text content. Extend the child element, adding a draggable attribute to let the browser know users can drag it:

<div class="mover" draggable="true">Page</div>

Now add another five of these pairs of child/ parent div elements:

<div id="box2">
<div class="mover" draggable="true">This</div>
</div>
<div id="box3">
<div class="mover" draggable="true">Web</div>
</div>
<div id="box4">
<div class="mover" draggable="true">Is</div>
</div>
<div id="box5>
<div class="mover" draggable="true">Nice</div>
</div>
<div id="box6">
<div class="mover" draggable="true">A</div>
</div>

Each parent element has a unique ID and each child element has a different word contained within it. All of the child elements have the same class attribute and are specified as draggable. We will be adding attributes to these parent and child elements throughout the tutorial.

Drag Element Styling

Let's add some styling to make the component intuitive for users to interact with. In the style section of your page head, add the following section to style the draggable elements:

.mover {
width:60px; 
height:4em; 
line-height:4em; 
margin:10px; 
padding:5px; 
float:left; 
background:#ffff99; 
border:1px dotted #333333; 
text-align:center;}

Using a border and background color makes the draggable area clearer, as does adding margins etc.

Drag

Let's start implementing the drag operation. In your child div elements, you have already specified the draggable attribute. Now add an event listener attribute indicating a function to execute when the dragging starts:

ondragstart="dragWord(event)"

Add this to each draggable child div element in the page. When this function executes, the event parameter will pass information about the item being dragged. Add the function to your script section:

function dragWord(dragEvent){
//start drag
}

When you drag an item, you can pass data to retrieve in the drop function (which we will implement later). Typically this data would include what you want dragged and dropped between locations on the page. In this case we want the text word in the dragged element to be displayed in the element the user drops it onto. However, we also want to update the location the user dragged the data from.

Consider what we want to happen when the user interacts with the component. For example, if the user drags the word "This" from the second position onto the first position, where the word "Page" is initially displayed, we want position one to show "This" but we also want position two to display "Page", effectively swapping the two words. If we do not take steps to make this happen, the default behavior is for the dragged word to remain in its original position as well as being displayed in the new position it was dragged to, and the word it replaced will disappear from the page completely.

For these reasons, the data we pass between drag and drop functions is going to include the word being dragged and the position it was dragged from, which we will indicate using its parent element ID attribute, since this is unique within the page. When the user drags and drops a word, the location dragged from will update to show the word dragged on top of.

Inside your drag function, add the following:

dragEvent.dataTransfer.setData("text/html", dragEvent.target.textContent+"|"+dragEvent.target.parentNode.id);

We set the data type to text, passing a string representing the content of the element being dragged, the "|" bar character, then the ID of the parent element of the item being dragged. When the item is dropped, we will split the passed data string to retrieve these two pieces of data.

Drop

Before we implement the drop function, we need to add an attribute to each of the parent drop target div elements, preventing the browser's default behavior when an item is dragged over:

ondragover="event.preventDefault()"

Now we can add the function we want to execute when a dragged item is dropped on one of these parent elements:

ondrop="dropWord(event)"

We pass the event object, which will include the data we specified to drag and information about the drop target. Add this to each of the six parent elements. Then add the drop function to the script section of your page:

function dropWord(dropEvent){
//drop
}

Inside this function, let's first retrieve the dragged data, which we specified in the drag function:

var dropData = dropEvent.dataTransfer.getData("text/html");

Now split this string on the "|" bar character to retrieve an array with the two data items we passed:

var dropItems = dropData.split("|"); 

The second item in the array (index 1) should be the ID of the current parent element of the item being dragged (at the position before dragging). Get a reference to this parent element now:

var prevElem = document.getElementById(dropItems[1]);

Now set the content of the child div inside this parent to display the word currently displayed in the element being dropped on:

prevElem.getElementsByTagName("div")[0].textContent = dropEvent.target.textContent;

We get the first child div element in the parent (which should be the only one) and set the content to be the text currently displayed inside the drop target. Now we can update the drop target to display the dragged word data, which should be at the first position in the data array (index 0):

dropEvent.target.textContent = dropItems[0];

Finally we need to prevent the default behavior again:

dropEvent.preventDefault();
Conclusion

That's it! Your simple drag and drop component is complete. Open and test your page in a browser, moving the words around to make a sentence. Your entire page should include the following code:

<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
.mover {
width:60px; 
height:4em; 
line-height:4em; 
margin:10px; 
padding:5px; 
float:left; 
background:#ffff99; 
border:1px dotted #333333; 
text-align:center;}
</style>
<script type="text/javascript">
function dragWord(dragEvent){
	dragEvent.dataTransfer.setData("text/html", dragEvent.target.textContent+"|"+dragEvent.target.parentNode.id);
}
function dropWord(dropEvent){
	var dropData = dropEvent.dataTransfer.getData("text/html");
	var dropItems = dropData.split("|"); 
	var prevElem = document.getElementById(dropItems[1]); 
	prevElem.getElementsByTagName("div")[0].textContent = dropEvent.target.textContent;
	dropEvent.target.textContent = dropItems[0];
	dropEvent.preventDefault();
}
</script>
</head>
<body>
<div><em>Move the words around to make a sentence.</em></div>
<div id="box1" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">Page</div>
</div>
<div id="box2" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">This</div>
</div>
<div id="box3" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">Web</div>
</div>
<div id="box4" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">Is</div>
</div>
<div id="box5" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">Nice</div>
</div>
<div id="box6" ondragover="event.preventDefault()" ondrop="dropWord(event)">
<div class="mover" draggable="true" ondragstart="dragWord(event)">A</div>
</div>
</body>
</html>

See if you can think of additional interactive components you could use this functionality for within a Web page and play around with the code to gain a fuller understanding of it.

Need more info about HTML5? Download our HTML5 eBook for free and enjoy its quality.

About the author

Copyright © All Rights Reserved