html5 drag and drop,Native Drag and Drop

Along with an army of JavaScript APIs, HTML 5 comes with a Drag and Drop (DnD) API that brings native DnD support to the browser making it much easier to code up.

HTML 5 DnD is based on Microsoft’s original implementation which was available as early as Internet Explorer 5! Now currently supported in IE, Firefox 3.5 and Safari 4.

We’re going to look how to implement DnD and review some of the issues (or hoops we have to jump through) with the current implementations now.

My First Drag and Drop

DnD requires only a few things to work:

Something to drag

A drop target

JavaScript event handlers on the target to tell the browser it can drop

The following elements are draggable by default: elements and elements (with an href).

If you want to drag a different element, you need to set the draggable attribute to true. That’s according to the spec, but to get it to work in Safari and Firefox there’s a little more that you need to do, which we’ll come on to.

If you want to skip the code walk through, here’s the simple drag and drop (source code)

Here’s our example markup:

Basic Drag and Drop

#drop {

min-height: 100px;

width: 200px;

border: 3px dashed #ccc;

margin: 10px;

padding: 10px;

}

p {

margin: 3px 0;

}

Remy Sharp

Bruce Lawson

Rich Clark

Note: the included h5utils.js script is a small library to trigger HTML 5 elements and to give me cross browser event binding.

Currently the elements can be dragged, but they can’t be dropped (this is the browser’s default).

To drop elements we need to:

Tell the browser that the element can be dragged over a specific point

Handle the drop event

To tell the browser we can drop in this element, all we have to do is cancel the dragover event. However, since IE behaves differently, we need to do the same thing for the dragenter event.

Here’s the code for basic drop handling:

var drop = document.querySelector('#drop');

// Tells the browser that we *can* drop on this target

addEvent(drop, 'dragover', cancel);

addEvent(drop, 'dragenter', cancel);

addEvent(drop, 'drop', function (event) {

// stops the browser from redirecting off to the text.

if (event.preventDefault) {

event.preventDefault();

}

this.innerHTML += '

' + event.dataTransfer.getData('Text') + '

';

return false;

});

function cancel(event) {

if (event.preventDefault) {

event.preventDefault();

}

return false;

}

Note for this code, I’m using addEvent where you’d normally see element.addEventListener, it’s from the h5utils.js library to support IE.

In the JavaScript we are:

Searching for the drop target in the DOM using document.querySelector (which returns the first result only)

When dragover event is fired (when the user drags the element over another), it will trigger the function called ‘cancel’ (at the bottom of the code above) which will prevent the default browser action

Do the same for dragenter to support IE

Bind the drop event, and within there grab some data about what was dropped.

dragover & dragenter

By cancelling this event, we’re telling the browser this element that we’re over is the one you can release and drop upon.

I’m still not entirely sure why there’s a difference here, but Firefox and friends needs preventDefault on the event, and IE requires the return false. Note that the examples out in the wild that use inline JavaScript (yuk, bad), the preventDefault is supposed to be implicit, so you won’t see it in the code.

drop

To show what was dropped, we need to do two things:

Cancel the default browser action. This is to ensure that if we drop a link, the browser doesn’t go off and surf to that location

Get the contents out of the dataTransfer object

The cancelling of the browser default is, again, done using the preventDefault and return false.

If we don’t set the dataTransfer data manually (which I’ll show you later), the default key is set to Text. So this might be the value of an href of an element, or it might be src address.

Doing More with Drag’n Drop

There’s a number of extra bits in the spec other than just dragging images.

Here’s a few bits that I can see being useful:

Being able to drag any element

More complex data types, other than text

Set a different drag icon/image when dragging the element

Dragging Anything

If we change the to

tags with background images, I still want to be able to drag them around the page, and drop them in to my container.

The HTML 5 spec says it should be as simple as adding the following attributes to the markup of the elements in question:

draggable="true"

However, this doesn’t work completely for Safari or Firefox.

For Safari you need to add the following style to the element:

[draggable=true] {

-khtml-user-drag: element;

}

This will start working in Safari, and as you drag it will set a default, empty value with the dataTransfer object. However, Firefox won’t allow you to drag the element unless you manually set some data to go with it.

To solve this, we need a dragstart event handler, and we’ll give it some data to be dragged around with:

var dragItems = document.querySelectorAll('[draggable=true]');

for (var i = 0; i < dragItems.length; i++) {

addEvent(dragItems[i], 'dragstart', function (event) {

// store the ID of the element, and collect it on the drop later on

event.dataTransfer.setData('Text', this.id);

});

}

More Complex Data Types

You’ve already seen how we can use dataTransfer.setData(format, string) to associate some data in the example above.

You can also use this key/value pair to store more data, but you’re limited to storing strings only.

One way I would get around this is to have a data lookup, where the key of the lookup may be the ID of the element, and then I can de-reference the data on the drop event.

For example:

var people = {

rem : {

name : "Remy Sharp",

blog : "http://remysharp.com"

},

brucel : {

name : "Bruce Lawson",

blog : "http://brucelawson.co.uk"

}

// etc...

}

var dragItems = document.querySelectorAll('[draggable=true]');

for (var i = 0; i < dragItems.length; i++) {

addEvent(dragItems[i], 'dragstart', function (event) {

// store the ID of the element, and collect it on the drop later on

event.dataTransfer.setData('Text', this.id);

});

}

addEvent(drop, 'drop', function (event) {

// stops the browser from redirecting off to the text.

if (event.preventDefault) {

event.preventDefault();

}

var person = people[event.dataTransfer.getData('Text')];

this.innerHTML += '

' + person.name + '

';

return false;

});

Obviously this isn’t the most ideal situation, but there’s also the possibility to set other content types in the drag data, which should produce some interesting apps in the future.

Drag Icon

Along with several other options with the dragstart event, you can also set a drag image, i.e. what you see under your cursor.

You can create a DOM fragment, and then associate the fragment with the dataTransfer using setDragImage(element, x, y).

So we can add the following to our example to use a custom drag image:

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

dragIcon.src = 'http://twitter.com/api/users/profile_image/twitter?size=mini';

Which creates an image element, and how within the dragstart event, we’ll set the drag image:

addEvent(dragItems[i], 'dragstart', function (event) {

// store the ID of the element, and collect it on the drop later on

event.dataTransfer.setData('Text', this.id);

event.dataTransfer.setDragImage(dragIcon, -10, -10);

return false;

});

This sets the custom drag icon 10 pixels below the cursor, as seen in this example: drag and drop with custom image (source code)

Native Drag

There’s lots of Drag and Drop JavaScript libraries available, but what I’d like to see, is native DnD support falling back to library based. However, I know for a fact that some libraries, including jQuery, construct a custom event when passed in to the event handler which means, currently, you can’t use the dataTransfer object, so you’ll have to rely on binding the events yourself. I’m sure this will change soon.

There’s lots more in Drag and Drop but this should be enough to go and play with now!

As for me, I'll be updating the Drag and Drop demos on HTML5demos.com to see if I can add ARIA support and capture a screencast of it running. Watch this space!

Further Reader

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值