HTML5 Drag and Drop in IE10 PPB2

Drag and drop is a user interaction model that we all use on a day to day basis,
probably without giving it much thought. We drag files from one folder to another,
text from one area of a document to another, and PowerPoint slides from one place
in the presentation to another.
HTML5 Drag and Drop, available in IE10 Platform Preview 2, brings this natural,
familiar behavior to the Web.
Magnetic Poetry on the IE Test Drive
site is example of a site that uses HTML5 Drag and Drop to create an experience
that previously would have needed a plug-in or JavaScript library.

Screen shot of the "Magnetic Poetry" Test Drive demo.

For an in-depth look at how this demo works,
check out this video.

Before HTML5, drag and drop behavior on the Web only partially worked without JavaScript
frameworks. Now making your site work well with drag and drop is simple.


Making an element draggable

While certain elements can be dragged by default (images, links and selected text),
HTML5 lets you make any element draggable by setting its draggable attribute
to “true.” For example, if you want to make a div draggable you would set its draggable
attribute to “true”; then you can drag that div just like an image. Each magnet
in the Magnetic Poetry demo is a span element with its draggable attribute set to
true.

<span draggable="true"
class="wordMagnet">HTML5</span>

Keep in mind that making an element draggable prevents the user from being able
to select text within that element since any clicks begin a drag.

While you can set the value of the draggable attribute in markup or in script, elements
also have a default draggable state. Images and links default to draggable=true
while all other elements default to draggable=false.


Making an element a drop target

Just like certain elements are draggable by default, certain elements are drop targets
by default. These include text input boxes and contenteditable elements. However,
any element can become a drop target by properly handling the drag events.


Drag Events

When performing a drag operation, you need to consider the element you are dragging
and the element you’re dragging over. Drag events fire on both these elements.

The element being dragged will receive the events:

  • dragstart – the user starts the drag
  • drag – the user is moving the element
  • dragend – the user ends the drag

The element being dragged over will receive the events:

  • dragenter –a drag enters the element’s area
  • dragleave – a drag leaves the element’s area
  • dragover – a drag is moving around the element’s area

The final event – the drop event - fires when the user drops the content. Only input
elements and contenteditable elements receive this event by default. To make other
elements a drop target and receive the drop event, you must call preventDefault()
on the dragenter and dragover events. Here’s an example of making a div a drop target:

<div id="dropTarget">Drop
Here</div>

<script>

function init() {

var dropTarget = document.getElementById("dropTarget");

dropTarget.addEventListener("dragenter",
makeDrop, false);

dropTarget.addEventListener("dragover",
makeDrop, false);

dropTarget.addEventListener("drop",
doSomething, false);

}

 

function makeDrop(e) {

e.preventDefault();

}

</script>

In the Magnetic Poetry demo, when you pick up a magnet (dragstart) the script does
some initial calculations of where within the element the mouse clicked. When you
drop the magnet (dragend) the script calculates a new location for the magnet and
moves it to where you dropped it.

You may also notice that when you drop a magnet, it rotates. The amount of rotation
is based on how close to the middle you grab the magnet. If you grab close to the
middle it will drop fairly flat but if you grab on the edges it will rotate more.
This creates a more natural look.


Accessing Drag Data

When moving the magnets around the fridge, only the magnet, the element being moved,
needed to perform any action so there was no need to exchange data between the element
being dragged and the element being dragged over. Many other drag/drop scenarios,
however, require data exchange between the drag content and the drop target. Consider
a basic kids game where the goal is to drag blocks to the proper holes. When the
hole receives a drop event, it needs to know what was dropped onto it in order to
check if it was the proper shape.

To facilitate exchanging data between the element being dragged and the element
being dropped on, drag events contain a dataTransfer object. Data may be written
to the dataTransfer object only during the dragstart event and it may be read only
during the drop event.

The code for the basic kids block game might look like this:

<div id="circle"
draggable="true"></div>

<div id="triangle"
draggable="true"></div>

<div id="circleHole"></div>

<div id="triangleHole"></div>

 

<script>

function init() {

// register the circle and triangle elements to call
setShape on dragstart

// register circleHole and triangleHole to cancel
the dragenter and dragover events and call checkShape on drop

}

 

function setShape(e) {

e.dataTransfer.setData("text", this.id);

}

 

function checkShape(e) {

var dropped = e.dataTransfer.getData("text");

// check for proper shape...

}

</script>


Drag and drop with files

One last new and really neat part of HTML5 drag and drop is the ability to drag
a file from the desktop to a Web site. When you drop a file on a Web site, it can
read the file contents and use the file within the site. The Magnetic Poetry demo
uses this feature to create small image previews on the refrigerator. Drag an image
file onto the refrigerator and you will get the preview.

Screen shot of the demo showing previews of drag-and-dropped images.

In order to accept file drops, the body of the page has registered for drop events.
When it receives a drop event, it looks at the dataTransfer object to see if there
is content in the files attribute (event.dataTransfer.files). If the drop contained
a file (or multiple files), then the files attribute will contain a
FileList. Each File
in the array can be read through the
FileReader interface. The Magnetic Poetry demo reads the file as a dataURL
and then uses that as the src attribute for a new image that it creates. That way
it can display the image that the user dropped in without ever uploading the file.
Here’s a snippet of the code that gets and reads the file:

function dropHandler(event) {

var filelist = event.dataTransfer.files;

if (!filelist) return;

if (filelist.length > 0) {

var file = filelist[0];

var image = document.createElement('img');

image.src = "";

var filereader = new
FileReader();

filereader.imageElt = image;

filereader.onloadend = handleReaderOnLoadEnd;

filereader.readAsDataURL(file);

}

}

 

function handleReaderOnLoadEnd(event) {

var image = this.imageElt;

image.src = this.result;

document.body.appendChild(image);

}


Accessibility considerations with drag and drop

Drag and drop can be a great interaction mode, however, there are users who can
only use the keyboard and can’t perform a mouse drag and drop operation. If you
create drag and drop experiences, you should always consider how a keyboard user
would be able to complete that task.

The dropzone
attribute
was also added to the HTML5 spec recently in order to identify
areas of the document where items can be dropped. In IE, adding the dropzone attribute
does not automatically make an element a drop target; you still need to handle the
drag events properly as described above. However, using it in your site signals
the drop targets to any accessibility tool that chooses to use it to create more
accessible drag and drop experiences.


Try it out

HTML5 drag and drop is available today in IE10 Platform Preview 2. Try it out for
yourself; you can even share your poem with your friends.

—Sharon Newman, Program Manager, Internet Explorer