在HTML5中你可以拖拽页面中指定的HTML元素。通过使用javascript事件监听,你可以决定元素在拖拽元素之后所发生的事情。
用于拖放的HTML元素中可以是以下两个角色:
Draggable(可拖动元素)
Drop target / drop zone(放置目标/放置区域)
可拖动的元素是指用户可以在页面中拖动并放置在其它地方的元素。它可以是一个或多个元素。
放置目标或放置区域是可拖动元素被放置的区域。
拖放事件
为了控制HTML元素的拖放,你需要执行3个步骤:
选择一个HTML元素来拖动
为拖动的HTML元素添加事件监听
为放置HTML元素的区域添加事件监听
下图列出了拖放的事件和属性:
首先,你需要在准备进行拖动的元素上设置draggable="true",使它可以被拖动。
接着你需要为拖动元素设置dragstart和dragend事件监听。在这些事件中,你可以设置元素在开始拖动和结束拖动时发生的事情。
然后你需要在放置区域元素上添加事件监听,你可以监听的事件有:dragenter,dragover,dragleave和drop。
dragenter事件在你拖动元素到放置区域上方时被触发。这个事件只有在拖动元素从放置区域外部进入放置区域时被触发,这里通常是由鼠标的位置来决定的。
当拖动元素经过放置区域的时候,dragover事件会被触发。并会在拖动元素在放置区域内移动时持续触发。
如果你将拖动元素移到放置区域之外,dragleave事件将被触发。
如果你将拖动元素放置在放置区域之内,drop事件将被触发。
拖放事件的例子
下面是一个拖放事件的例子。你可以将HTML5的logo拖拽到放置区域中,看看右边的数据统计,还可以打开浏览器的控制台看看拖动元素被放下后的信息。
放置区域
dragstart:
dragend:
dragenter:
dragover:
dragleave:
drop:
元素拖放代码
下面让我们来看一下如何处理拖放事件。我们首先创建一个可以拖拽的图片元素。下面是它的HTML代码:
然后我们需要一个放置的区域。这里使用一个
在完成上面的步骤之后,我们需要为它们添加事件监听。事件监听的代码如下:
var draggable = document.getElementById("draggable1");
draggable.addEventListener('dragstart', dragStart, false);
draggable.addEventListener('dragend' , dragEnd , false);
var droptarget = document.getElementById("droptarget1");
droptarget.addEventListener('dragenter', dragEnter , false);
droptarget.addEventListener('dragover' , dragOver , false);
droptarget.addEventListener('dragleave', dragLeave , false);
droptarget.addEventListener('drop' , drop , false);
/* Draggable event handlers */
function dragStart(event) {
event.dataTransfer.setData('text/html', "You dragged the image!");
}
function dragEnd(event) {
}
/* Drop target event handlers */
function dragEnter(event) {
}
function dragOver(event) {
event.preventDefault();
return false;
}
function dragLeave(event) {
}
function drop(event) {
var data = event.dataTransfer.getData('text/html');
event.preventDefault();
return false;
}
为了在拖放操作时实现数据交换,IE5引入了dataTransfer对象,它是事件对象的一个属性,用于从被拖动元素向放置目标传递字符串格式的数据。因为它是事件对象的属性,所以只能在拖放事件的事件处理程序中访问dataTransfer对象。在事件处理程序中,可以使用这个对象的属性和方法来完善拖放功能。目前,HTML5规范草案也收入了dataTransfer对象。
dataTransfer对象有两个主要方法: getData()和setData()。getData()可以取得由setData()保存的值。setData()方法的第一个参数,也是getDAta()方法唯一的一个参数,是一个字符串,表示保存的数据类型,取值为”text”或“URL”,例如:
//设置和接收文本数据
event.dataTransfer.setDAta("text", "some text");
var text = event.dataTransfer.getData("text");
//设置和接收URL
event.dataTransfer.setData("URL", "HTML://www.htmleaf.com/");
IE浏览器只定义了“text”和“URL”两种有效的数据类型,而HTML5则对此加以扩展,允许指定各种MIME类型。考虑到向后兼容,HTML5也支持“text”和“URL”,但这两种类型会被映射为“text/plain”和“text/uri-list”。
实际上,dataTransfer对象可以为每种MIME类型都保存一个值。换句话说,同时在这个对象中保存了一段文本和一个URL不会有任何问题。不过,保存在dataTransfer对象中的数据只能在drop事件处理程序中读取。如果在ondrop处理程序中没有读到数据,那就是dataTransfer对象已经被销毁,数据也丢失了。
在拖动文本框中的文本时,浏览器会调用setData()方法,将拖动的文本以“text”格式保存在dataTransfer对象中。类似地,在拖放链接或图像时,会调用setData()方法并保存URL。然后,在这些元素被拖放到放置目标时,就可以通过getData()读到这些数据。当然,作为开发人员,你也可以在dragstart事件处理程序中调用setData(),手工保存自己要传输的数据,以便将来使用。
将数据保存为文本和保存为URL是有区别的。如果将数据保存为文本格式,那么数据不会得到任何特殊处理。而如果将数据保存为URL,浏览器会将其当成网页中的链接。换句话说,如果你把它放置到另一个浏览器窗口中,浏览器就会打开该URL。
Firefox在其第5个版本之前不能正确地将“URL”和“text”映射为“text/uri-list”和“text/plain”。但是却能把“Text”映射为“text/plain”。为了更好地在跨浏览器的情况下从dataTransfer对象取得数据,最好在取得URL数据时检测两个值,而在取得文本数据时使用“text”。
var dataTransfer = event.dataTransfer;
//读取URL
var url = dataTransfer.getData("url") || dataTransfer.getData("text/uri-list");
//读取文本
var text = dataTransfer.getData("Text");
注意,一定要把短数据类型放在前面,因为IE10及之前的版本仍然不支持扩展的MIME类型名,而它们在遇到无法识别的数据类型时,会抛出错误。
DataTransfer对象、effectsAllowed、dropEffect和setDragImage()
在上面我们已经介绍了一些关于DataTransfer对象的知识。DataTransfer能够在拖放元素的过程中给用户提供一些视觉效果。DataTransfer对象有两个属性和一个方法可以使用。它们是:
effectsAllowed
dropEffect
setDragImage()
你可以在dragstart和drop事件中访问DataTransfer对象。在下面的例子中,dragstart监听事件中在DataTransfer对象上设置了effectsAllowed属性。
function dragStart(event) {
event.dataTransfer.effectsAllowed = "copy";
event.dataTransfer.setData('text/html', "You dragged the image!");
event.target.style.border = "1px solid #cccccc";
}
effectsAllowed属性用于在元素拖放的过程中显示鼠标的样式。典型的例子是拖动一个元素经过放置区域时,鼠标会发生变化。effectsAllowed属性的可选值有:
none
copy
move
copyMove
link
linkMove
copyLink
all
uninitialized
dropEffect属性是拖动一个元素经过放置区域时,鼠标的样式。(似乎目前的浏览器还不支持这个属性)。它的可选值有:
none
copy
link
move
setDragImage(image, x, y)函数可以在用户拖动元素时显示指定的图片。默认情况下,在拖动元素的时候显示的是一个半透明的元素副本,可以通过这个函数来设置不同的图片。x和y属性用于设置显示图片位置的偏移。
下面是一个使用dragStart()函数的示例代码:
function dragStart(event) {
event.dataTransfer.effectAllowed = "all";
event.dataTransfer.dropEffect = "copy";
var dragImage = document.createElement('img');
dragImage.src = dragImageUrl;
dragImage.width = 75;
event.dataTransfer.setDragImage(dragImage, 0, 0);
event.dataTransfer.setData('text/html', "You dragged the image!");
event.target.style.border = "1px solid #cccccc";
}
拖动文件到浏览器中
我们还可以将操作系统中的文件拖拽到浏览器中,并通过HTML5 File API来查看文件的名称和内容。下面是一个示例代码:
var droptarget2 = document.getElementById("droptarget2");
droptarget2.addEventListener('drop', drop , false);
function drop(event) {
// Files - array of dragged files.
var files = event.dataTransfer.files;
for(var i= 0; i < files.length; i++){
var file = files[i];
console.log("file: " + file.name);
}
event.preventDefault();
return false;
}
注意这里drop()方法中不是调用getData()函数,而是访问DataTransfer的files属性。files属性包含被拖动到浏览器中的文件列表。HTML5 File API将在后面的文章中详细介绍。