A Drag and Drop Planning Board with HTML5

The Drag and Drop API is one of the new JavaScript APIs that let us add dynamic effects to our sites. There are two flavors of Drag & Drop:

1. Dragging elements into other elements, as defined in the Drag and Drop W3C spec.

2. Dragging files from your computer and into a webpage, in combination with the File API.

In this article, we’ll be focusing on the former. To learn more about the latter, an excellent guide can be found at the Mozilla Developer Network.

We’ll be building a simple agile planning board. We’ll have three categories: To Do, In Progress, and Done. We can move the items around on the board to mark their progress.

note: Planning Boards

The concept of a Planning Board or a Task Board is a part of the Scrum Agile software development methodology. To learn more, see: http://en.wikipedia.org/wiki/Scrum_(development)

To give you an idea of what we’re going to build, here’s a picture of the finished product. You can see the finished code on github:

Drag and Drop Planning Board

Let’s dive in, starting with the HTML!

<div id="board">
  <div id="todo">
    <div id="item1">
    <div id="item2">
  </div>
  <div id="inprogress"></div>
  <div id="done"></div>
</div>

Our first div, div id=”board” will act as the main container. The board will be divided up into three other divs. Finally, several smaller divs will act as note cards holding our items. The note cards will start in the “To Do” section.

Here are the complete set of steps we’ll need to make our notecards draggable into the other sections of the bulletin board:

  1. Set the draggable attribute on our notecard div HTML elements.
  2. Add an Event Listener for the dragstart event on the notecards.
  3. Add an EventListener for the dragover event on all sections of our bulletin board.
  4. Add an EventListener for the drop event on all sections of our bulletin board.

First, we’ll add the draggable attribute to our two notecards.

<div id="board">
  <div id="todo">
    <div id="item1" draggable="true">
    <div id="item2" draggable="true">
  </div>
  <div id="inprogress"></div>
  <div id="done"></div>
</div>

Next, we need to specify the JavaScript code that will actually make the Drag and Drop magic happen.

First, we’ll bind the dragstart event to our two notecards. We’ll do this via jQuery’s bind method, binding the dragstart event on either of our two notecards to the code inside an anonymous function :

$('#item1, #item2').bind('dragstart', function(event) {
  event.originalEvent.dataTransfer.setData("text/plain", event.target.getAttribute('id'));
});

In our anonymous function, we call the setData method, which is a method on the DataTransfer object. The DataTransfer object is one of the new objects outlined in the Drag and Drop API. This object allows us to store and retrieve data about the objects that are being dragged.

The setData method takes two arguments:

  1. The drag data item kind. This describes what kind of data we’ll be storing
  2. The actual data we want to store. This is either a unicode or binary string.

The setData method adds the data we want to store about the dragged item to what the W3C spec calls the “drag data store“.

Examining the line inside our anonymous function more closely, we can see that we’re calling setData on the dataTransfer object, and specifying both required arguments:

event.originalEvent.dataTransfer.setData("text/plain", event.target.getAttribute('id'));

We set our drag data item kind to be “text/plain”. And for the data itself, we’ll store the id of the notecard that we have begun to drag.

By default, the dragged item is shown to be a ghost-like image of the original element. If you’d like to change the dragged image to a custom one, you can use dataTransfer’s setDragImage() method.

Next, we need to make sure we can drag the notecards over onto the other sections of the bulletin board. To do so, we’ll bind the dragover event on the board sections. Again, we’ll do this via jQuery’s bind method:

$('#todo, #inprogress, #done').bind('dragover', function(event) {
  event.preventDefault();
});

This time, the code inside our anonymous function is considerably more simple. But what is it doing?

By default, none of the all elements on the page will accept a dropped item. In order to override this default behavior, and enable the element to accept dragged items, we must pervent the default behavior from happening. We do this by calling the preventDefault() method on the event.

For our last step, we need to actually do something once our notecards are dropped onto a new section of the bulletin board! As a first step, we’ll bind the drop event to the bulletin board sections, and define what to do once something is dropped onto them. Again, we do this by binding the bulletin board divs to an anonymous function, via jQuery’s bind method:

$('#todo, #inprogress, #done').bind('drop', function(event) {
    // do something!
});

We want to drop the whole div element for the dragged notecard into the new location. To do this, we first grab the notecard element’s id, which we previously stored to the dataTransfer object:

$('#todo, #inprogress, #done').bind('drop', function(event) {

  var notecard = event.originalEvent.dataTransfer.getData("text/plain");

});

Next, we’ll actually add a new element to the target, by using the appendChild method:

$('#todo, #inprogress, #done').bind('drop', function(event) {

  var notecard = event.originalEvent.dataTransfer.getData("text/plain");

  event.target.appendChild(document.getElementById(notecard));
});

Finally, as we did before, we’ll disable the default behavior that disallows any items to be dropped:

$('#todo, #inprogress, #done').bind('drop', function(event) {

  var notecard = event.originalEvent.dataTransfer.getData("text/plain");

  event.target.appendChild(document.getElementById(notecard));

  event.preventDefault();

});

Now, we can move our notecards around into any section we want!

Drag and Drop Planning Board

See the demonstration page. View source for the full code.

To learn more about HTML5′s Drag and Drop, check out my forthcoming book, HTML5 and CSS3 for the Real World. You may also find the following sites useful:

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • dkl3in

    Well, the code isn’t working for me, maybe the code is a litte bit more buggy then i’m inspect ( example: “<div id="item1" >”).
    and where is the CSS ? have i missed a second page ?
    maybe a demo page would be nice.

  • Virak Sun

    Very nice article, a link to a demo page would be even better.

  • y3max

    very good article!

  • Webnet

    I would’ve enjoyed a sample ^_^

  • Drazen Mokic

    Demo!

    • http://www.onsman.com Ricky Onsman

      Alrighty then. We’ve put up a demo page. Sheesh.

      You’d think none of you had ever copied a slab of code into a text file, saved it as HTML and viewed it yourself. The link is at the foot of the article, or you can copy and paste this:

      http://www.sitepoint.com/examples/planning-board-with-html5/

      You’ll be wanting napkins and a comfy sofa next ;-)

      • http://www.brothercake.com/ James Edwards

        You’d think you had never written a practical blog post before :P People always want demos.

        btw – you need to edit your first code example; WP doesn’t like STRONG inside PRE, it turns it into markup

        fyi – it’s a neat idea, but I hope the book will have more semantic HTML in it — every single element is a DIV!!

      • http://www.onsman.com Ricky Onsman

        Very good point about the code problem, James: fixed now.

  • http://www.brothercake.com/ James Edwards

    It’d be nice if you could show how to do this without jQuery.

    I mean it’s particularly ironic, that you’re importing a library to control drag and drop, when the library itself already implements drag and drop! Kinda like buying a laptop when you’re only using it as a monitor for another computer.

    Since you’re only targetting compliant browsers with a modern API (and therefore there’s no code forking for IE or stuff like that), the scripting you’ve got there could be expressed in the same amount of code without jQuery as you’ve used with it. End result — a ~30k import that serves no benefit at all.

    • http://www.optimalworks.net/ Craig Buckler

      I agree, although you should be aware that the core jQuery library does not include drag and drop. You can, however, use a small plugin or write your own code.

      My main issue is browser support. If you use the HTML5 drag-and-drop API, you have to accept that some browsers don’t implement it. You can write a JavaScript-based fallback shim but, since that’d work in newer browsers, you’d be doing the same thing twice.

      I suspect most developers will stick with JavaScript solutions until IE6/7/8 usage becomes inconsequential.

      • http://www.brothercake.com/ James Edwards

        What is the current browser support for this API?

      • Rob Crowther

        Why wait? With a few modifications HTML5 drag-and-drop works just fine in IE8 (and even 6 & 7, though I didn’t test):

        https://github.com/robertc/DragNDrop_PlanningBoard

        As far as I know it’s only Opera that has no support.

    • Alexis Goldstein

      Hi James,

      To your earlier comment: please rest assured that the book covers the new semantic elements in depth! And our sample site that we build throughout the text makes very little use of divs.

      In this example, I was aiming to make the non drag and drop code as easy and familiar as possible, in order to make a simple and straightforward example. I thought it was best to avoid the new semantic elements in the event we had readers not yet familiar with them, and to limit the scope of the article to just drag and drop.

      I take your point on jQuery, and when I have a free moment I will update the code on github in order to not use jQuery and thus make the code more performant. That said, if you’d like to dive in and fork the code and make those changes and any others you think would improve the sample, I would welcome it!

      • Chaz Scholton (iDude.net)

        Alexis,
        You’ve stumble into the fact that this example is or would be rather popular. You’re hear-by appointed the Kanban Ninja girl. While you were trying to show off and demonstrate the powerful new API’s little were you expecting for people to be wanting so much more from the code so soon. (Great room for follow up material and articles).

  • Alexis Goldstein

    Hi James, Rob,

    Yes, Drag and Drop is supported in all browsers except Opera and Mobile Safari. Drag and Drop is unsupported by design in iOS, as Apple directs you to use the DOM Touch API instead (you can read more about how they’d prefer you handle touches in mobile Safari here: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html).

    • http://www.optimalworks.net/ Craig Buckler

      That’s surprising. According to caniuse.com, HTML5 Drag and Drop support’s available in IE6, 7 and 8.
      As you say, the big omission appears to be Opera (mobile and desktop).

      • Rob Crowther

        The HTML5 API is based on the IE5.5 implementation.

  • http://www.brothercake.com/ James Edwards

    Interesting. What about keyboard support?

  • Chaz Scholton (iDude.net)

    Hi, I just wanted to point out that this is known as a “Kanban” board. If you wanted to get real crafty you can set a limit to the cards in “the progress” sections. This would be known as setting the WIP (Work In Progress) limit. The code Alexis came up with was intended to show off some of the new Javascript API stuff.

    If you’re really love this kind of User Interface, be certain to do some research and reading up on Kanban. You can create interfaces for a variety of uses, such as in eCommerce systems. Management of Order fulfillment or Shipping and other things. The mighty Kanban interface is one of the most under utilized overlooked interfaces there is in my opinion. (food for thought)

  • http://www.onsman.com Ricky Onsman

    We’ve just published a further post by Alexis in which she adds Local Storage to the planning board: A Better Cookie: HTML5 and Web Storage.

  • ian morton

    Be good if I could use this for the iPad/Android as well….could it be extended?

  • Robert Hartung

    Nice, but you shouldn’t be able to drop a task in a task ;)

  • Andreas Ek

    An easy board http://hb.tum.nu/ but without HTML5 and drop-zones :-)

  • Anonymous

    Thank u for posting