转自:http://www.cnblogs.com/fsjohnhuang/p/3961066.html

一、前言                                   

在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5的DnD API觉得那些痛苦的日子将一去不复返,但事实又是怎样的呢?下面我们一起来看看DnD API的真面目吧!

二、由于篇幅较长,特设目录一陀                      

三、HTML4下实现简单拖拽

四、HTML5下实现简单拖拽

五、如何启用DnD效果

六、draggable属性详解

七、DnD的生命周期

八、DnD中最重要的数据传递对象──DataTransfer对象

九、[object DataTransferItemList]类型

十、[object DataTransferItem]类型

十一、浏览器支持

十二、特征检测是否支持HTML5的DnD API

十三、总结

十四、参考

十五、勘误

十六、书评

三、HTML4下实现简单拖拽                          

功能:实现在div#title上按下鼠标左键并移动鼠标时,拖拽整个div#dialog,但释放鼠标时停止拖拽。

html代码片断

<div id="dialog">
<div id="title">
Hi there!
</div>
<div id="content">
Welcome here every one. We would learn the HTML5 feature DnD API now!
<div>
</div>

js代码片断

DnD && DnD(document.getElementById('title'), document.getElementById('dialog'));

DnD.js工具库

 

contains.js工具库

 

具体代码地址:https://github.com/fsjohnhuang/DnD-polyfill/blob/master/sample/sample3/

四、HTML5实现简单拖拽                          

功能:实现在div#title上按下鼠标左键并移动鼠标时,拖拽整个div#dialog,但释放鼠标时停止拖拽。下面的例子仅能在FF下运行

html代码片段

<div id="dialog">
<div id="title" draggable="true">
Hi there!
</div>
<div id="content">
Welcome here every one. We would learn the HTML5 feature DnD API now!
<div>
</div>

js代码片段

DnD && DnD(document.getElementById('title'), document.getElementById('dialog'));

DnD.js工具库

 

contains.js工具库与上一节的相同

具体代码地址:https://github.com/fsjohnhuang/DnD-polyfill/blob/master/sample/sample4/

五、如何启用DnD效果                            

html片段

<div id="drag" draggable="true" style="width:100px;height:50px;">
test
</div>

js片段

var drag = document.getElementById('drag');
drag.onselectstart = function(){return false;};
// FF下拖拽时,默认不会生成一个被拖拽元素的阴影并跟随鼠标移动
// 需通过e.dataTransfer.setData来启动该效果
drag.ondragstart = function(e){
e.dataTransfer.setData('text', e.target.innerHTML);
};

关键点:

1. 为触发拖拽的元素添加 draggable="true" 特性,用于启动HTML5的DnD功能(即元素的 dragstart 事件可被触发);

2. 在FF下即使添加 draggable="true" 特性,但仅仅会触发 dragstart 事件,但DnD功能并没有被完全打开(拖拽元素时没有任何视觉效果),需要调用 event.dataTransfer.setData('Text','') 彻底开启DnD功能。

3. 在Safari4下则需要借助CSS规则来启动DnD功能, [draggable=true]{ -webkit-user-drag: element; }

六、draggable属性详解                              

作用:用于指定标签是否可被拖拽

属性值范围如下:

1.  true ,表示可被拖拽

2.  false ,表示不可被拖拽

3.  auto ,默认值,img和带href属性的a标签则表示可拖拽,其他标签表示不可被拖拽

4. 其他值,表示不可被拖拽

七、DnD生命周期                                  

1. 被拖拽元素的生命周期

dragstart :当被拖拽元素开始被拖拽时触发

 注意:

[a]. event.dataTransfer的大部分设置均在这里配置

[b]. 若调用event.preventDefault()则会阻止拖拽行为,导致后续的拖拽事件不被触发

[c]. 触发dragstart事件后,其他元素的mousemove,mouseover,mouseenter,mouseleave,mouseout事件均不会被触发了

 drag :当被拖拽元素被拖拽时触发

 dragend :当拖拽行为结束后触发

2. 目标元素的生命周期

dragenter :当被拖拽元素进入目标元素时触发

dragover :当被拖拽元素在目标元素上移动时触发

    注意:

[a]. 可以在这里设置dropEffect的值,事件的默认行为是将dropEffect设置为none

[b]. 该事件是被拖拽元素在目标元素上移动一段时间后才触发

[c]. 事件的默认行为是不允许被拖拽元素在其他元素上释放或放置(即无法触发 drop 事件),需要通过 event.preventDefault() 来阻止默认行为才能触发后续的 drop 事件。

drop :当被拖拽元素在目标元素上,而且释放鼠标左键时触发

 注意:

[a]. 对于外来的被拖拽元素(超链接、文件、图片源), drop 事件的默认行为是浏览器将当前页面重定向到被拖拽元素所指向的资源上

[b]. 对文档内部的被拖拽元素,IE10+和Chrome下的默认行为是不作为,而FF得默认行为是新打开一个文档用于访问被拖拽元素所指向的资源

dragleave :当被拖拽元素离开目标元素时触发。

示例代码:

<div id="drag" style="width:50px;height:50px;">Test</div>
<div id="drop" style="width:100px;height:100px;border:solid 1px red;"></div>
<script type="text/javascript">
var drag = document.getElementById('drag'), drop = document.getElementById('drop');
drag.ondragstart = function(evt){
evt.dataTransfer.setData('Text', 'www.baidu.com');
};
drop.ondragover = function(evt){
evt.preventDefault(); // 这样才能触发drop的drop事件
};
</script>

3. 整体生命周期

dragstart -> drag -> dragenter -> dragover ->  dragleave  -> drop -> dragend

八、DnD中最重要的数据传递对象──DataTransfer对象          

DataTransfer对象用于在配置拖拽行为效果,并且在拖拽过程的各事件间传递数据信息。它存储在事件对象当中,下面我们逐步了解它吧。

1. [object DragEvent]对象

继承自 [object MouseEvent] 对象,其实就多了个 {DataTransfer} dataTransfer 属性

2. [object DataTransfer]对象详解

上文说到DataTransfer对象可用于传递数据信息,而数据信息的数据类型被限定为字符串文件类型

  2.1.  effectAllowed 和 dropEffect 属性

这个两个属性对于初次接触DnD的朋友来说,可谓最令人摸不着头脑的,网上和各书籍上对这两个属性的解释均不全面,下面我试图尽量把它们讲明白。

effectAllowed 和 dropEffect 最主要的作用是,用于配置拖拽操作过程中鼠标指针的类型以便提示用户后续可执行怎样的操作;其次的作用是,控制 drop 事件的触发与否。

     [a] effectAllowed 

作用:用于设置被拖拽元素可执行的操作。

取值范围:

   copy ,限定dropEffect的属性值为copy,否则会鼠标指针为禁止样式

       link ,限定dropEffect的属性值为link,否则会鼠标指针为禁止样式

move ,限定dropEffect的属性值为move,否则会鼠标指针为禁止样式

copyLink ,限定dropEffect的属性值为copy和link,否则会鼠标指针为禁止样式

copyMove ,限定dropEffect的属性值为copy和move,否则会鼠标指针为禁止样式

linkMove ,限定dropEffect的属性值为link和move,否则会鼠标指针为禁止样式

       all ,允许dropEffect的属性值为任意值

none ,鼠标指针一直为禁止样式,不管dropEffect的属性值是什么

uninitialized ,没有限定dropEffect属性的值,效果和 all 一样。

注意:仅能在 dragstart 事件中设置该属性,其他事件中设置均无效。

 [b].  dropEffect 

     作用:用于设置目标元素将执行的操作,若属性值属于 effectAllowed 范围内,则鼠标指针将显示对应的指针样式,否则则显示禁止的指针样式。

   取值范围:

copy :被拖拽元素将被复制到目标元素内,若属于 effectAllowed 范围内时,则鼠标指针显示复制的样式,否则则显示禁止的指针样式。

    link :被拖拽元素将以超链接的形式打开资源(具体是否打开资源请参考七、2),若属于 effectAllowed  范围内时,则鼠标指针显示超链接的样式,否则则显示禁止的指针样式。

move :被拖拽元素将被移动到目标元素内,若属于 effectAllowed   范围内时,则鼠标指针显示移动的样式,否则则显示禁止的指针样式。

none :被拖拽元素不能在目标元素上作任何操作,一直显示禁止的指针样式。除了文本框外其他元素的默认值均为none

 注意:   

  1. 仅能在 dragover 事件中设置该属性值,其他事件中设置均无效

  2. 当显示禁止的指针样式时,将无法触发目标元素的 drop 事件。

[c]. 在真实浏览器中的测试结果

浏览器 effectAllowed默认值 effectAllowed值

dropEffect默认值

默认使用鼠标指针的效果

IE10+ uninitialized uninitialized copy copy
copyLink none link
copyMove none copy
linkMove none link
all copy link
none    
move move move
link link link
copy copy copy
备注:

1. 无法通过 shift键 切换copyLink,copyMove和linkMove的样式;

2. 若effectAllowed设置为copyLink、copyMove或linkMove,且dropEffect与之对应,则鼠标样式将为dropEffect所设置的样式

Chrome37 all copyLink none copy
copyMove none move
linkMove none move
move move move
link link link
copy copy copy
all copy move
备注:

1. 无法通过 shift键 切换copyLink,copyMove和linkMove的样式;

2. 若effectAllowed设置为copyLink、copyMove或linkMove,且dropEffect与之对应,则鼠标样式将为dropEffect所设置的样式

FF31 for Windows uninitialized copyLink copy copy
copyMove move move
linkMove move move
move move move
link link link
copy copy copy
uninitialized move move
备注:

1. 可通过 shift键 切换copyLink,copyMove和linkMove的样式;

2. 若effectAllowed设置为copyLink、copyMove或linkMove,且dropEffect与之对应,则鼠标样式将为dropEffect所设置的样式

FF33 for Linux 仅能触发dragstart事件,其他事件一律无效,因此不用理会

  2.2. 其他属性

   items :数据类型为DataTransferItemList,存储DataTransfer对象中所有的数据项

 注意:1. FF33 for Linux下没有该属性

2. IE10+没有该属性

   files :数据类型为FileList(IE5~9没有该属性)

types :数据类型为DOMStringList,存储DataTransfer对象中所有数据项的数据类型

  注意:1. IE5~9下没有该属性

       2. 仅能在dragenter,dragover和drop中获取该属性

 2.3. 方法

void addElement({HTMLElement} element) :添加一起跟随鼠标移动的元素。仅在 dragstart 事件中调用,Chrome37和IE10+不支持该方法;

void setDragImage({Element} image, {long} x, {long} y) :设置拖动时跟随鼠标移动的图片,用来替代默认的元素,若image不是图片元素则会元素临时转换为图片;x用于设置图标与鼠标在水平方向上的距离,y设置图标与鼠标在垂直方向上的距离。仅在 dragstart 事件中调用。IE10+不支持该方法;

  注意:

   1. {Element} image必须在DOM树中,而且在渲染树中(即display不为none)为有效元素,否则会导致没有元素跟随鼠标移动;

   2. Chrome37下,若{Element} image为无效元素时,将不会触发dragstart事件后的其他事件。

boolean setData({DOMString} format, {DOMString} data) :将指定格式的数据赋值给dataTransfer或clipboardData,format值范围为URL、Text(或text)和各种MIME类型,其实Text会被自动映射为text/plain,URL会被自动映射为text/uri-list类型。仅在 dragstart 事件中调用。

注意:

   1. FF5-是不会将text映射为text/plain,而仅仅支持Text映射为text/plain,因此使用Text或直接使用text/plain

   2. IE10+仅支持Text和URL两种类型,不支持text/plain、text/uri-list等类型

   3.  text/plain类型则不会对数据进行额外处理,而text/uri-list类型则会将数据视为url来使用(体现在当将元素拖拽到OS桌面释放时)

   4.  Chrome和FF支持任意的非空字符串作为format

   5. 当没有填写第二个入参时,则会根据format来删除相应的数据项

   6. 当设置text/uri-list类型的数据时,数据必须带协议名,如http://fsjohnhuang.cnblogs.com;若仅写为fsjohnhuang.cnblogs.com,那么dataTransfer将自动弃除,在`dragstart`事件还能获取到,但在drop事件中将无法获

DOMString getData({DOMString} format) :从DataTransfer对象或ClipboardData对象中获取指定格式的数据

void clearData([{DOMString} format]) :从DataTransfer对象或ClipboardData对象中删除指定格式或全部kind值为string的数据。仅在 dragstart 事件中调用,在其他事件中调用会抛InvalidStateError。

 2.4. 数据存储模式

  Read/Write mode:在 dragstart 事件为该模式,可读写数据

  Read-only mode:在 drop 事件为该模式,仅能读取数据

  Protected mode:在其他事件为该模式,仅能枚举数据

九、[object DataTransferItemList]类型                  

readonly unsigined long length

getter DataTransferItem(unsigned long index) ,使用方式:items[1]

deleter void(unsigned long index) ,使用方式:delete items[1],在非Read/Write mode下会报InvalidStateError,而添加数据则不会有问题

void clear()

DataTransferItem add(DOMString data, DOMString type)

DataTransferItem add(File data)

十、[object DataTransferItem]类型                    

readonly attribute DOMString kind ,表示数据的大类型,值范围string和file

readonly attribute DOMString type ,表示数据的小类型,一般使用mimetype表示,但在Chrome和FF下可以是任意非空字符串

void getAsString(FunctionStringCallback cb) ,当kind为string时,则只能在Read-only mode和Read/Write mode下才可用。其中cb仅有一个类型为{DOMString}的入参

File getAsFile() ,当kind为file时,则只能在Read-only mode和Read/Write mode下才可用,没有数据时返回null

十一、浏览器支持                               

IE5~9部分标签支持;

IE10+、FF、Chrome支持。

也许大家会好惊讶IE5已经开始支持DnD API啦??其实DnD API的最初是由IE提出来的,只是后来被HTML5纳入草案而已。大家也许会问在IE5~9上运行上文的代码没有效果,是不是我写错了,下一篇《JS魔法堂:IE5~9的Drag & Drop API(http://www.cnblogs.com/fsjohnhuang/p/3980563.html)》我们将一起探讨IE5~9的DnD API。

十二、特征检测是否支持HTML5的DnD API                  

由于IE5~9的DnD API与HTML5标准的有差异,因此特征检测变得尤为必要了。下面的代码参考了Modernizr.draganddrop的实现(地址:https://github.com/Modernizr/Modernizr/blob/master/feature-detects/draganddrop.js)

var supportDnD = function(){
var div = document.createElement('div');
return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
};

十三、总结                                  

回到文章最开头的两个示例,会发现使用HTML5 DnD API实现拖拽效果的代码量并不比HTML4中的少,效果也并不理想(个人水平有限优化也没做好),最让人心酸的是各浏览器在细节上还是有差异的(兼容性是前端工程师一直的痛啊)。也许大家会说那么DnD API是不是就仅仅好看而不实用呢?其实不然,只是示例把这个特性用到不适合的地方而已。

HTML5 DnD API最常见的用法就是文件拖拽上传,或把文档内某元素拖到其他元素内或OS桌面上等。这些都是HTML4时代的js很难处理,或者无法处理的。

尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/3961066.html  ^_^肥仔John

十四、参考                                  

http://www.w3school.com.cn/html5/html_5_draganddrop.asp
http://www.cnblogs.com/wpfpizicai/archive/2012/04/07/2436454.html
http://www.kankanews.com/ICkengine/archives/82862.shtml
http://jingyan.baidu.com/article/6dad5075cf6e62a123e36e11.html
http://www.zhangxinxu.com/wordpress/2011/02/html5-drag-drop-%E6%8B%96%E6%8B%BD%E4%B8%8E%E6%8B%96%E6%94%BE%E7%AE%80%E4%BB%8B/
http://my.oschina.net/caixw/blog/102845
http://www.cnblogs.com/birdshome/archive/2006/07/22/Drag_Drop.html
《HTML5实战》第11章、HTML5中元素的拖放
《HTML5用户指南》第8章、拖放
http://msdn.microsoft.com/en-us/library/ff974353(v=vs.85).aspx
《HTML5与CSS3权威指南》4.5.拖放
《论道HTML5》3.3.Drag & Drop API

十五、勘误                                  

《HTML5实战》P292 setData的format参数格式包含text/url-list,应更正为text/uri-list

十六、书评                                  

《HTML5实战》第11章、HTML5中元素的拖放,这一章感觉就一笔带过,纯属印象派。
《HTML5用户指南》第8章、拖放,除了简单介绍HTML5 DnD API外,还介绍起源和IE上DnD的特点和作者对DnD API不完美的抱怨,比《HTML5实战》更值得拜读。
《HTML5与CSS3权威指南》4.5.拖放,内容,深度与《HTML5实战》相似
《论道HTML5》3.3.Drag & Drop API,对比上述三本书,它提及到使用Modernizr作DnD特征检测,其他基本相似

HTML5 Drop API的更多相关文章

  1. HTML5魔法堂:全面理解Drag & Drop API

    一.前言    在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5的DnD API觉得那些痛苦的日子将一去不复返,但事实又是怎样的呢?下面我们一起来看看DnD API的真面 ...

  2. HTML5 File API — 让前端操作文件变的可能

    前言 在 HTML5 File API 出现之前,前端对于文件的操作是非常有局限性的,大多需要配合后端实现.出于安全角度考虑,从本地上传文件时,代码不可能获取文件在用户本地的地址,所以纯前端不可能完成 ...

  3. 开大你的音响,感受HTML5 Audio API带来的视听盛宴

    话说HTML5的炫酷真的是让我爱不释手,即使在这个提到IE就伤心不完的年代.但话又说回来,追求卓越Web创造更美世界这样高的追求什么时候又与IE沾过边儿呢?所以当你在看本文并且我们开始讨论HTML5等 ...

  4. JS魔法堂:IE5~9的Drag&Drop API

    一.前言     < HTML5魔法堂:全面理解Drag & Drop API>中提到从IE5开始已经支持DnD API,但IE5~9与HTML5的API有所不同,下面我们来了解一 ...

  5. html5 drag api详解

    可以夸张点说,如果你不会拖拽,你不是一个合格的前端开发. 回想下,以前我们是怎么实现拖拽的,主要有以下几步: 1.目标元素绑定mousedown事件,记录下此时鼠标位置和拖拽元素的位置差,分别是 di ...

  6. HTML5 File api 实现断点续传

    目前市场上大多数的网站的断点上传都是需要安装浏览器插件的,本文就针对高级浏览器的环境下,通过HTML5 File api实现断点上传进行说明 一.实现文件多选 HTML5的<input>新 ...

  7. HTML5 程序设计 - 使用HTML5 Canvas API

    请你跟着本篇示例代码实现每个示例,30分钟后,你会高喊:“HTML5 Canvas?!在哥面前,那都不是事儿!” 呵呵.不要被滚动条吓到,很多都是代码和图片.我没有分开写,不过上面给大家提供了目录,方 ...

  8. Three.js + HTML5 Audio API 打造3D音乐频谱,Let’s ROCK!

    继续玩味之前写的音乐频谱作品,将原来在Canvas标签上的 作图利用Three.js让它通过WebGL呈现,这样就打造出了一个全立体感的频谱效果了. 项目详情及源码 项目GitHub地址:https: ...

  9. html5 history api

    1.html5 history api适用场景,个人理解最大的用处是配合ajax使用,使ajax拥有回退.前进的用户体验. 2.代码(dive into html5中的一个小例子) 1)fer.htm ...

随机推荐

  1. MySQL解压版配置步骤

    mysql-5.7.14-winx64\bin配置到Path中 在解压路径下复制my-default.ini,修改名称为my.ini 在my.ini添加如下 [mysqld] basedir=C:\\ ...

  2. 在DBeaver中phoenix查询报错:org.apache.phoenix.exception.PhoenixIOException: The system cannot find the path specified

    环境:Phoenix:4.4,win7系统 问题:Phoenix在查询hbase时,报"系统找不到指定路径". 解决: 请参见 https://distcp.quora.com/C ...

  3. Linux工具快速教程

    看到一linux中常用工具使用教程,非常好.猛击下面的地址 github:https://github.com/me115/linuxtools_rst 在线文档:http://linuxtools- ...

  4. 关于Jmeter分布式测试在公司内的使用

    首先非常感谢虫师的文章受益匪浅 http://www.cnblogs.com/fnng/category/345478.html 今天,花了半天时间进行分布式的测试,真是纠结啊!! RT 1.在公司用 ...

  5. 添加WoSign根证书到JDK

    由于某些“众所周知”的原因,Azure中国版使用了国内的WoSign证书——和臭名昭著的CNNIC有的一拼.Apple是不信任WoSign证书的,这也是为什么用Mac OS中访问www.azure.c ...

  6. JMeter常见问题集合

    前言 本文内容仅仅是针对Jmeter的部分功能名词的介绍和解释,以及初学者不易理解的问题的整理.部分内容来自别人做的整理,为了更好地整理自己的思路,所以可耻的整理一下发到博客上. 标题[1-6]和[参 ...

  7. 实例:对2个Makefile的备注

    实例1:Makefile编译链接简单.c函数 example.c Makefile exe: example.c gcc example.c -o exe clean: rm exe 执行效果: 实例 ...

  8. struts2中Ajax校验

    Ajax(Asynchronous JavaScript and Xml),整合了JavaScript,XML,CSS,DOM,Ajax引擎(XMLHttpRequest). JavaScript语言 ...

  9. 谈c++ pb_ds库(二) 红黑树大法好

    厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...

  10. GO语言总结(4)——映射(Map)

    上一篇博客介绍了Go语言的数组和切片——GO语言总结(3)——数组和切片,本篇博客介绍Go语言的映射(Map) 映射是一种内置的数据结构,用来保存键值对的无序集合. (1)映射的创建 make ( m ...