HTML5 Drop API
轉(zhuǎn)自:http://www.cnblogs.com/fsjohnhuang/p/3961066.html
一、前言 ??
? 在HTML4的時代,各前端工程師為了實現(xiàn)拖拽功能可說是煞費(fèi)苦心,初聽HTML5的DnD API覺得那些痛苦的日子將一去不復(fù)返,但事實又是怎樣的呢?下面我們一起來看看DnD API的真面目吧!
?
二、由于篇幅較長,特設(shè)目錄一陀
三、HTML4下實現(xiàn)簡單拖拽
四、HTML5下實現(xiàn)簡單拖拽
五、如何啟用DnD效果
六、draggable屬性詳解
七、DnD的生命周期
八、DnD中最重要的數(shù)據(jù)傳遞對象──DataTransfer對象
九、[object DataTransferItemList]類型
十、[object DataTransferItem]類型
十一、瀏覽器支持
十二、特征檢測是否支持HTML5的DnD API
十三、總結(jié)
十四、參考
十五、勘誤
十六、書評
?
三、HTML4下實現(xiàn)簡單拖拽
功能:實現(xiàn)在div#title上按下鼠標(biāo)左鍵并移動鼠標(biāo)時,拖拽整個div#dialog,但釋放鼠標(biāo)時停止拖拽。
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工具庫
?View Codecontains.js工具庫
?View Code具體代碼地址:https://github.com/fsjohnhuang/DnD-polyfill/blob/master/sample/sample3/
?
四、HTML5實現(xiàn)簡單拖拽
功能:實現(xiàn)在div#title上按下鼠標(biāo)左鍵并移動鼠標(biāo)時,拖拽整個div#dialog,但釋放鼠標(biāo)時停止拖拽。下面的例子僅能在FF下運(yùn)行
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工具庫
?View Codecontains.js工具庫與上一節(jié)的相同
具體代碼地址: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下拖拽時,默認(rèn)不會生成一個被拖拽元素的陰影并跟隨鼠標(biāo)移動 // 需通過e.dataTransfer.setData來啟動該效果 drag.ondragstart = function(e){e.dataTransfer.setData('text', e.target.innerHTML); };關(guān)鍵點:
1. 為觸發(fā)拖拽的元素添加?draggable="true"?特性,用于啟動HTML5的DnD功能(即元素的?dragstart?事件可被觸發(fā));
2. 在FF下即使添加?draggable="true"?特性,但僅僅會觸發(fā)?dragstart?事件,但DnD功能并沒有被完全打開(拖拽元素時沒有任何視覺效果),需要調(diào)用?event.dataTransfer.setData('Text','')?徹底開啟DnD功能。
3. 在Safari4下則需要借助CSS規(guī)則來啟動DnD功能,?[draggable=true]{ -webkit-user-drag: element; }?
?
六、draggable屬性詳解
作用:用于指定標(biāo)簽是否可被拖拽
屬性值范圍如下:
1. ?true?,表示可被拖拽
2. ?false?,表示不可被拖拽
3. ?auto?,默認(rèn)值,img和帶href屬性的a標(biāo)簽則表示可拖拽,其他標(biāo)簽表示不可被拖拽
4. 其他值,表示不可被拖拽
?
七、DnD生命周期
1. 被拖拽元素的生命周期
?dragstart?:當(dāng)被拖拽元素開始被拖拽時觸發(fā)
???注意:
? ? [a]. event.dataTransfer的大部分設(shè)置均在這里配置
? ? [b]. 若調(diào)用event.preventDefault()則會阻止拖拽行為,導(dǎo)致后續(xù)的拖拽事件不被觸發(fā)
? ? [c]. 觸發(fā)dragstart事件后,其他元素的mousemove,mouseover,mouseenter,mouseleave,mouseout事件均不會被觸發(fā)了
?drag?:當(dāng)被拖拽元素被拖拽時觸發(fā)
?dragend?:當(dāng)拖拽行為結(jié)束后觸發(fā)
2. 目標(biāo)元素的生命周期
??dragenter?:當(dāng)被拖拽元素進(jìn)入目標(biāo)元素時觸發(fā)
??dragover?:當(dāng)被拖拽元素在目標(biāo)元素上移動時觸發(fā)
? ? 注意:
? ? ?[a]. 可以在這里設(shè)置dropEffect的值,事件的默認(rèn)行為是將dropEffect設(shè)置為none
? ? ?[b]. 該事件是被拖拽元素在目標(biāo)元素上移動一段時間后才觸發(fā)
? ? ?[c]. 事件的默認(rèn)行為是不允許被拖拽元素在其他元素上釋放或放置(即無法觸發(fā)?drop?事件),需要通過?event.preventDefault()?來阻止默認(rèn)行為才能觸發(fā)后續(xù)的?drop?事件。
???drop?:當(dāng)被拖拽元素在目標(biāo)元素上,而且釋放鼠標(biāo)左鍵時觸發(fā)
? ??注意:
? ? [a]. 對于外來的被拖拽元素(超鏈接、文件、圖片源),?drop?事件的默認(rèn)行為是瀏覽器將當(dāng)前頁面重定向到被拖拽元素所指向的資源上
? ? [b]. 對文檔內(nèi)部的被拖拽元素,IE10+和Chrome下的默認(rèn)行為是不作為,而FF得默認(rèn)行為是新打開一個文檔用于訪問被拖拽元素所指向的資源
???dragleave?:當(dāng)被拖拽元素離開目標(biāo)元素時觸發(fā)。
示例代碼:
<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(); // 這樣才能觸發(fā)drop的drop事件}; </script>3. 整體生命周期
?dragstart?->?drag?->?dragenter?->?dragover?->??dragleave? ->?drop?->?dragend?
?
八、DnD中最重要的數(shù)據(jù)傳遞對象──DataTransfer對象
? DataTransfer對象用于在配置拖拽行為效果,并且在拖拽過程的各事件間傳遞數(shù)據(jù)信息。它存儲在事件對象當(dāng)中,下面我們逐步了解它吧。
1. [object DragEvent]對象
? 繼承自?[object?MouseEvent]?對象,其實就多了個?{DataTransfer} dataTransfer?屬性
2. [object DataTransfer]對象詳解
? 上文說到DataTransfer對象可用于傳遞數(shù)據(jù)信息,而數(shù)據(jù)信息的數(shù)據(jù)類型被限定為字符串和文件類型
??2.1. ?effectAllowed?和?dropEffect?屬性
? ? ?這個兩個屬性對于初次接觸DnD的朋友來說,可謂最令人摸不著頭腦的,網(wǎng)上和各書籍上對這兩個屬性的解釋均不全面,下面我試圖盡量把它們講明白。
? ???effectAllowed?和?dropEffect?最主要的作用是,用于配置拖拽操作過程中鼠標(biāo)指針的類型以便提示用戶后續(xù)可執(zhí)行怎樣的操作;其次的作用是,控制?drop?事件的觸發(fā)與否。
? ? ?[a]?effectAllowed?
? ? ? ??作用:用于設(shè)置被拖拽元素可執(zhí)行的操作。
? ? ? ??取值范圍:
? ? ?copy?,限定dropEffect的屬性值為copy,否則會鼠標(biāo)指針為禁止樣式
? ??link?,限定dropEffect的屬性值為link,否則會鼠標(biāo)指針為禁止樣式
? ? ? ? ? ?move?,限定dropEffect的屬性值為move,否則會鼠標(biāo)指針為禁止樣式
? ? ? ? ???copyLink?,限定dropEffect的屬性值為copy和link,否則會鼠標(biāo)指針為禁止樣式
? ? ? ? ???copyMove?,限定dropEffect的屬性值為copy和move,否則會鼠標(biāo)指針為禁止樣式
? ? ? ? ???linkMove?,限定dropEffect的屬性值為link和move,否則會鼠標(biāo)指針為禁止樣式
? ??all?,允許dropEffect的屬性值為任意值
? ? ? ? ???none?,鼠標(biāo)指針一直為禁止樣式,不管dropEffect的屬性值是什么
? ? ? ? ???uninitialized?,沒有限定dropEffect屬性的值,效果和?all?一樣。
? ? ??注意:僅能在?dragstart?事件中設(shè)置該屬性,其他事件中設(shè)置均無效。
? ? ??[b].??dropEffect?
??作用:用于設(shè)置目標(biāo)元素將執(zhí)行的操作,若屬性值屬于?effectAllowed?范圍內(nèi),則鼠標(biāo)指針將顯示對應(yīng)的指針樣式,否則則顯示禁止的指針樣式。
?? ?取值范圍:
? ? ? ? ? ???copy?:被拖拽元素將被復(fù)制到目標(biāo)元素內(nèi),若屬于?effectAllowed?范圍內(nèi)時,則鼠標(biāo)指針顯示復(fù)制的樣式,否則則顯示禁止的指針樣式。
? link?:被拖拽元素將以超鏈接的形式打開資源(具體是否打開資源請參考七、2),若屬于?effectAllowed??范圍內(nèi)時,則鼠標(biāo)指針顯示超鏈接的樣式,否則則顯示禁止的指針樣式。
? ? ? ? ? ? ?move?:被拖拽元素將被移動到目標(biāo)元素內(nèi),若屬于?effectAllowed???范圍內(nèi)時,則鼠標(biāo)指針顯示移動的樣式,否則則顯示禁止的指針樣式。
? ? ? ? ? ???none?:被拖拽元素不能在目標(biāo)元素上作任何操作,一直顯示禁止的指針樣式。除了文本框外其他元素的默認(rèn)值均為none
注意:
1.?僅能在?dragover?事件中設(shè)置該屬性值,其他事件中設(shè)置均無效
2. 當(dāng)顯示禁止的指針樣式時,將無法觸發(fā)目標(biāo)元素的?drop?事件。
? ? ?[c]. 在真實瀏覽器中的測試結(jié)果
? ? ?
| 瀏覽器 | effectAllowed默認(rèn)值 | effectAllowed值 | dropEffect默認(rèn)值 | 默認(rèn)使用鼠標(biāo)指針的效果 |
| 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設(shè)置為copyLink、copyMove或linkMove,且dropEffect與之對應(yīng),則鼠標(biāo)樣式將為dropEffect所設(shè)置的樣式 | |||
| 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設(shè)置為copyLink、copyMove或linkMove,且dropEffect與之對應(yīng),則鼠標(biāo)樣式將為dropEffect所設(shè)置的樣式 | |||
| 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設(shè)置為copyLink、copyMove或linkMove,且dropEffect與之對應(yīng),則鼠標(biāo)樣式將為dropEffect所設(shè)置的樣式 | |||
| FF33 for Linux | 僅能觸發(fā)dragstart事件,其他事件一律無效,因此不用理會 | |||
? ? ?
? 2.2. 其他屬性
?items?:數(shù)據(jù)類型為DataTransferItemList,存儲DataTransfer對象中所有的數(shù)據(jù)項
? ? ???注意:1. FF33 for Linux下沒有該屬性
? ? ? ? ? ? ? ?2. IE10+沒有該屬性
? ??files?:數(shù)據(jù)類型為FileList(IE5~9沒有該屬性)
? ? ???types?:數(shù)據(jù)類型為DOMStringList,存儲DataTransfer對象中所有數(shù)據(jù)項的數(shù)據(jù)類型
注意:1. IE5~9下沒有該屬性
? 2. 僅能在dragenter,dragover和drop中獲取該屬性
?2.3. 方法
? ? ?void addElement({HTMLElement} element)?:添加一起跟隨鼠標(biāo)移動的元素。僅在?dragstart?事件中調(diào)用,Chrome37和IE10+不支持該方法;
? ? ?void?setDragImage({Element} image, {long} x, {long} y)?:設(shè)置拖動時跟隨鼠標(biāo)移動的圖片,用來替代默認(rèn)的元素,若image不是圖片元素則會元素臨時轉(zhuǎn)換為圖片;x用于設(shè)置圖標(biāo)與鼠標(biāo)在水平方向上的距離,y設(shè)置圖標(biāo)與鼠標(biāo)在垂直方向上的距離。僅在?dragstart?事件中調(diào)用。IE10+不支持該方法;
? ?注意:
1. {Element} image必須在DOM樹中,而且在渲染樹中(即display不為none)為有效元素,否則會導(dǎo)致沒有元素跟隨鼠標(biāo)移動;
2. Chrome37下,若{Element} image為無效元素時,將不會觸發(fā)dragstart事件后的其他事件。
? ? ? ???boolean setData({DOMString} format, {DOMString} data)?:將指定格式的數(shù)據(jù)賦值給dataTransfer或clipboardData,format值范圍為URL、Text(或text)和各種MIME類型,其實Text會被自動映射為text/plain,URL會被自動映射為text/uri-list類型。僅在?dragstart?事件中調(diào)用。
? ? ?注意:
1.?FF5-是不會將text映射為text/plain,而僅僅支持Text映射為text/plain,因此使用Text或直接使用text/plain
2.?IE10+僅支持Text和URL兩種類型,不支持text/plain、text/uri-list等類型
3.??text/plain類型則不會對數(shù)據(jù)進(jìn)行額外處理,而text/uri-list類型則會將數(shù)據(jù)視為url來使用(體現(xiàn)在當(dāng)將元素拖拽到OS桌面釋放時)
4.??Chrome和FF支持任意的非空字符串作為format
5.?當(dāng)沒有填寫第二個入?yún)r,則會根據(jù)format來刪除相應(yīng)的數(shù)據(jù)項
6.?當(dāng)設(shè)置text/uri-list類型的數(shù)據(jù)時,數(shù)據(jù)必須帶協(xié)議名,如http://fsjohnhuang.cnblogs.com;若僅寫為fsjohnhuang.cnblogs.com,那么dataTransfer將自動棄除,在`dragstart`事件還能獲取到,但在drop事件中將無法獲
? ? ? ? ??DOMString getData({DOMString} format)?:從DataTransfer對象或ClipboardData對象中獲取指定格式的數(shù)據(jù)
? ? ? ? ??void?clearData([{DOMString} format])?:從DataTransfer對象或ClipboardData對象中刪除指定格式或全部kind值為string的數(shù)據(jù)。僅在?dragstart?事件中調(diào)用,在其他事件中調(diào)用會拋InvalidStateError。
?2.4. 數(shù)據(jù)存儲模式
Read/Write mode:在?dragstart?事件為該模式,可讀寫數(shù)據(jù)
Read-only mode:在?drop?事件為該模式,僅能讀取數(shù)據(jù)
Protected mode:在其他事件為該模式,僅能枚舉數(shù)據(jù)
?
九、[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,而添加數(shù)據(jù)則不會有問題
?void?clear()?
?DataTransferItem add(DOMString data, DOMString type)?
?DataTransferItem add(File data)?
?
十、[object DataTransferItem]類型
?readonly?attribute DOMString kind?,表示數(shù)據(jù)的大類型,值范圍string和file
?readonly?attribute DOMString type?,表示數(shù)據(jù)的小類型,一般使用mimetype表示,但在Chrome和FF下可以是任意非空字符串
?void?getAsString(FunctionStringCallback cb)?,當(dāng)kind為string時,則只能在Read-only mode和Read/Write mode下才可用。其中cb僅有一個類型為{DOMString}的入?yún)?/span>
?File getAsFile()?,當(dāng)kind為file時,則只能在Read-only mode和Read/Write mode下才可用,沒有數(shù)據(jù)時返回null
?
十一、瀏覽器支持
?IE5~9部分標(biāo)簽支持;
?IE10+、FF、Chrome支持。
?也許大家會好驚訝IE5已經(jīng)開始支持DnD API啦??其實DnD API的最初是由IE提出來的,只是后來被HTML5納入草案而已。大家也許會問在IE5~9上運(yùn)行上文的代碼沒有效果,是不是我寫錯了,下一篇《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標(biāo)準(zhǔn)的有差異,因此特征檢測變得尤為必要了。下面的代碼參考了Modernizr.draganddrop的實現(xiàn)(地址: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);};?
十三、總結(jié)
? 回到文章最開頭的兩個示例,會發(fā)現(xiàn)使用HTML5 DnD API實現(xiàn)拖拽效果的代碼量并不比HTML4中的少,效果也并不理想(個人水平有限優(yōu)化也沒做好),最讓人心酸的是各瀏覽器在細(xì)節(jié)上還是有差異的(兼容性是前端工程師一直的痛啊)。也許大家會說那么DnD API是不是就僅僅好看而不實用呢?其實不然,只是示例把這個特性用到不適合的地方而已。
? HTML5 DnD API最常見的用法就是文件拖拽上傳,或把文檔內(nèi)某元素拖到其他元素內(nèi)或OS桌面上等。這些都是HTML4時代的js很難處理,或者無法處理的。
? 尊重原創(chuàng),轉(zhuǎn)載請注明來自: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實戰(zhàn)》第11章、HTML5中元素的拖放
《HTML5用戶指南》第8章、拖放
http://msdn.microsoft.com/en-us/library/ff974353(v=vs.85).aspx
《HTML5與CSS3權(quán)威指南》4.5.拖放
《論道HTML5》3.3.Drag & Drop API
?
十五、勘誤
《HTML5實戰(zhàn)》P292 setData的format參數(shù)格式包含text/url-list,應(yīng)更正為text/uri-list
?
十六、書評
《HTML5實戰(zhàn)》第11章、HTML5中元素的拖放,這一章感覺就一筆帶過,純屬印象派。
《HTML5用戶指南》第8章、拖放,除了簡單介紹HTML5 DnD API外,還介紹起源和IE上DnD的特點和作者對DnD API不完美的抱怨,比《HTML5實戰(zhàn)》更值得拜讀。
《HTML5與CSS3權(quán)威指南》4.5.拖放,內(nèi)容,深度與《HTML5實戰(zhàn)》相似
《論道HTML5》3.3.Drag & Drop API,對比上述三本書,它提及到使用Modernizr作DnD特征檢測,其他基本相似
轉(zhuǎn)載于:https://www.cnblogs.com/mauricechans/p/5855953.html
總結(jié)
以上是生活随笔為你收集整理的HTML5 Drop API的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 错题纠正
- 下一篇: 微信开发接口调用(前端+.net服务端)