intro-to-html5-html5-logo-300
Coding - HTML5

Rearranging Web Page Items with HTML5 Drag and Drop

With HTML5, you can allow users to drag and drop Web page items. Using a combination of HTML markup and JavaScript, you can implement drag and drop operations natively in supporting browsers. In this tutorial we will explore how you can use drag and drop functionality to let users rearrange the items in a list – the same principle applies to rearranging any element type.

Create your Page

Use an existing page if you like, or create a new one now using the following outline:

<!DOCTYPE html>
<html>
<head>
<style type="text/css">

</style>
<script type="text/javascript">

</script>
</head>
<body>

</body>
</html>

Let’s add some default CSS to the style section in the page head:

body, html {
background-color:#CCFFCC; 
font-family:sans-serif; 
color:#330033; 
text-align:center;
}

Now add a list to the page body section, preceding it with some explanatory text:

<p>
Sort these into your order of preference:
</p>
<ul>
<li>Apples</li>
<li>Oranges</li>
<li>Bananas</li>
<li>Strawberries</li>
</ul>

Make Elements Draggable

Add the draggable attribute to each item you want users to be able to drag:

<li draggable="true">Apples</li>
<li draggable="true">Oranges</li>
<li draggable="true">Bananas</li>
<li draggable="true">Strawberries</li>

Since the list items contain text strings, the user would normally be able to click and drag their mouse to select the text. We do not want the user to do this, because when they click on a list item and begin dragging it, we want to start dragging the list item to let the user rearrange it. For this reason, we need to add the following declaration to the style section:

[draggable] {
user-select: none;
}

You may need to add vendor-specific versions of this declaration to support older browsers. If you like, use the following code to provide additional styling:

ul {
margin:auto;
width:20%;
text-align:center;
}
li {
list-style-type:none;
padding:5px;
margin:2px;
background-color:#CCCCFF;
border:2px double #CCCCCC;
}

html5-drag-drop-init

Drag and Drop Concepts

Before we start dragging and dropping, it’s important to understand a few concepts first.

When you drag and drop items in a Web page, rather than dragging an element itself, you are actually dragging the data associated with it. When we let the user rearrange the list, they will effectively be dragging the text strings around.

Sometimes you may want to identify certain items in a page as draggable, and certain items in the page as places the dragged items can be dropped – these are drop targets. For example, you could have an empty box you ask users to drag items into from other parts of the page. When you want to let users rearrange a list, the process is a little more complex. This is because the list items can be dragged and can also have other items dropped into them – this means that the list items are all drag candidates and drop targets.

When the user drags one item onto another, as well as copying the dragged data into the drop target, we want to swap the items, copying the text that originally appeared in the drop target into the list item we dragged from.

To implement and configure the various parts in a drag and drop operation, you can set your elements up to detect various events, including dragstart, dragenter, dragover, dragleave, drop and dragend. These allow you to control the detail of what happens when the user drags and drops, as well as what the page looks like while this is going on. In this tutorial we will only need to handle some of these events.

Start Dragging

Let’s start dragging! Add the ondragstart attribute to your draggable items:

<li draggable="true" ondragstart="dragStarted(event)">Apples</li>
<li draggable="true" ondragstart="dragStarted(event)">Oranges</li>
<li draggable="true" ondragstart="dragStarted(event)">Bananas</li>
<li draggable="true" ondragstart="dragStarted(event)">Strawberries</li>

We can respond by adding the specified function to the script section in the page head – first add a variable to keep track of the drag source:

var source;

Now add the function we listed as drag start event attribute:

function dragStarted(evt){
//start drag
}

The function receives the drag event that triggered it, so we can detect information about which item is being dragged. Inside the function, start by setting the variable we declared:

function dragStarted(evt){
//start drag
source=evt.target;
}

Now set the drag data – remember we said that the user will be dragging data around, not elements:

function dragStarted(evt){
//start drag
source=evt.target;
//set data
evt.dataTransfer.setData("text/plain", evt.target.innerHTML);
}

We set the type and content of the data – which will be the content of the list item. Finish the drag start function by specifying which types of data transfer are allowed:

function dragStarted(evt){
//start drag
source=evt.target;
//set data
evt.dataTransfer.setData("text/plain", evt.target.innerHTML);
//specify allowed transfer
evt.dataTransfer.effectAllowed = "move";
}

As you can see already, much of the drag and drop coding involves preventing the browser from carrying out its default behavior. When dragging and dropping, you can implement various types of operation, including moving and copying.

Drag Over

Extend your list item markup again, this time to detect the drag over event:

<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)">Apples</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)">Oranges</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)">Bananas</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)">Strawberries</li>

Now add the new function to the script section:

function draggingOver(evt){
//drag over
}

Inside the function, we again need to prevent the standard browser behavior:

function draggingOver(evt){
//drag over
evt.preventDefault();
}

We can finish the drag over function by specifying what type of operation is occurring:

function draggingOver(evt){
//drag over
evt.preventDefault();
//specify operation
evt.dataTransfer.dropEffect = "move";
}

Notice that we use the dataTransfer object as we did when setting the allowed transfer type.

Drop

Finally we are ready to drop the element data. Extend the list items once more to detect the drop event:

<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)" ondrop="dropped(event)">Apples</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)" ondrop="dropped(event)">Oranges</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)" ondrop="dropped(event)">Bananas</li>
<li draggable="true" ondragstart="dragStarted(event)" ondragover="draggingOver(event)" ondrop="dropped(event)">Strawberries</li>

Add this last function to the script section:

function dropped(evt){
//drop
}

Inside the function, we yet again need to prevent the default behavior:

function dropped(evt){
//drop
evt.preventDefault();
evt.stopPropagation();
}

The stopPropagation line stops certain browsers from redirecting the user when they attempt to drag and drop the elements. Next, update the text displayed in the element being dragged:

function dropped(evt){
//drop
evt.preventDefault();
evt.stopPropagation();
//update text in dragged item
source.innerHTML = evt.target.innerHTML;
}

We use the event target to retrieve the text from the target item. Finally, update the drop target item to include the text from the dragged item:

function dropped(evt){
//drop
evt.preventDefault();
evt.stopPropagation();
//update text in dragged item
source.innerHTML = evt.target.innerHTML;
//update text in drop target
evt.target.innerHTML = evt.dataTransfer.getData("text/plain");
}

This time we use the event dataTransfer object, which we used earlier to set the data being dragged.

Now you can save and open the page! Drag the items on top of one another to rearrange them. When you drop one item on another, their values should be swapped around.

html5-drag-drop-mid

html5-drag-drop-end

The detail of what you see while dragging will vary depending on your browser and operating system. There are many potential applications of the functionality in websites, for example in user surveys.

Conclusion

We have implemented a basic rearranging function using HTML5 and JavaScript drag and drop utilities. See if you can enhance the code, for example by adding some of the other event listeners and controlling the appearance of the list items while the drag and drop operations are executing. You can also use the functionality with other types of element, such as images. As always, make sure your pages do not rely on functions that older browsers will not be able to support.

About the author

I'm a developer and technical writer - see benormal.info for details. Follow me on Twitter @BrainDeadAir or email me at sue@benormal.info.

Share this post

Leave a Comment

Subscribe To Our Newsletter