最早引入JS拖放功能的是IE4,當時,網頁中只有兩種對象可以拖放:圖像和某些文本。拖動圖像時,把鼠標放在圖像上,按住鼠標不放就可以拖動它。拖動文本時,需要選中文本,然後可以像拖動圖像一樣拖動被選中的文本。在IE4中,唯一有效的放置目標是文本框,到了IE5拖放功能得到擴展,添加了新的事件,而且網頁中任何元素都可以作為放置目標,IE5.5更進一步,讓網頁中的任何元素都可以拖放,IE,Firfox3.5,Safari3+,Chrome都實現了原生拖放功能。
一、可拖放屬性draggable
默認情況下,圖像、鏈接、文本是可以拖動的,文本只有在被選中的情況下才能拖動,而圖像和鏈接在任何時候都可以拖動,這是因為圖像和鏈接 的draggable屬性自動被設置成true,而其他元素這個屬性的默認值都是false,所以要想讓其他元素可拖動,或者讓圖像或鏈接不能拖動,都可以設置draggable這個屬性來改變他們的可拖動狀態。
例如: <!--讓這個圖像不可以拖動-->
<img src="test.jpg" draggable="false" >
<!--讓這個元素可以拖動-->
<div draggable="true"></div>
支持draggable屬性的浏覽器有IE10+,Firfox4+,Safari5+,Chrome,另外為了讓Firfox支持可拖放屬性,還必須添加一個ondragstart事件處理程序,並在dataTransfer對象中保存一些信息。
二、事件對象dataTransfer
dataTransfer是事件對象的一個屬性,用於從被拖動元素向放置目標傳遞字符串格式的數據,因為它是事件對象的屬性,所以只能在拖放事件的事件處理程序中訪問dataTransfer對象。在事件處理程序中,可以使用這個對象的屬性和方法,來完善拖放功能,
dataTransfer對象主要有兩個方法:setData() 和 getData(),getData()可以取得由setData()保存的值,setData()方法的第一個參數,也是getData()方法的唯一一個參數,是一個字符串,表示保存的數據類型,取值為"text"或"URL"。
例如:
//設置和接收文本數據
event.dataTransfer.setData("text","some text");
var text=event.dataTransfer.getData("text");
//設置和接收URL
event.dataTransfer.setData("URL","http://www.blog.com/");
event.dataTransfer.getData("URL");
IE只定義了"text"和"URL"兩種有效的數據類型,而HTML5則對此加以擴展,允許指定各種MIME類型,考慮到向後兼容,H5也支持"text"和"URL",但這兩種類型會被映射為"text/plain"和"text/uri-list"。實際上,dataTransfer對象可以為每種MIME類型都保存一個值,保存在dataTransfer對象中的數據只能在drop事件處理程序中讀取,如果沒有在onDrop處理程序中讀到數據,那就是dataTransfer對象已被銷毀,數據也丟失了。
將數據保存為文本和保存為URL是有區別的,如果將數據保存為文本格式,那麼數據不會得到任何特殊處理,而如果將數據保存為URL,浏覽器會將其當成網頁中的鏈接,,也就是如果你把它放置到另一個浏覽器窗口中,浏覽器就會打開該URL。
由於Firfox在其第5個版本之前不能正確的將"url"和"text"映射為"text/uri-list"和"text/plain",但是卻能把"Text"(T大寫)映射為"text/plain",為了更好的在跨浏覽器的情況下從dataTransfer對象取得數據,最好在取得URL數據是檢測兩個值,而在取得文本數據時使用"Text"。
//讀取URL
var url=event.dataTransfer.getData("url")||event.dataTransfer.getData("text/uri-list");
//讀取文本
vat text=dataTransfer.getData("Text");
注意。一定要把端數據類型放在前面,因為IE10及之前的版本仍然不支持擴展的MIME類型名。在遇到無法識別的數據類型時,會報錯。
三、dropEffect 和 effectAllowed屬性
dataTranfer 對象的兩個屬性:dropEffect 和 effectAllowed,這兩個屬性用來確定被拖動元素以及作為放置目標的元素能夠接收什麼操作。
通過dropEffect屬性可以知道被拖動元素能夠執行哪種放置行為,這個屬性有4個可能的值:
(1)"none":不能把拖動的元素放在這裡,這是除文本框之外所有元素的默認值
(2)"move":應該把拖動的元素移動到放置目標
(3)"copy":應該把拖動的元素復制到放置目標
(4)"link":表示放置目標會打開拖動的元素(但拖動的元素必須是一個鏈接,有URL)
把元素拖動到放置目標上時,以上每一個值都會導致光標顯示為不同的符號。要使用dropEffect屬性,必須在ondragenter事件處理程序中針對放置目標來設置它。
dropEffect屬性只有搭配effectAllowed屬性才有用。effectAllowed屬性表示允許拖動的元素的哪種dropEffect,effectAllowed屬性可能的值有:
(1)"uninitialized":沒有給被拖動元素設置任何放置行為
(2)"none":被拖動的元素不能有任何行為
(3)"copy":只允許值為"copy"的dropEffect
(4)"link":只允許值為"link"的dropEffect
(5)"move":只允許值為"move"的dropEffect
(6)"copyLink":只允許值為"copy"和"link"的dropEffect
(7)"copyMove":只允許值為"copy"和"move"的dropEffect
(8)"linkMove":只允許值為"link"和"move"的dropEffect
(9)"all":允許任意dropEffect
注意,必須在ondragstart事件處理程序中設置effectAllowed屬性。
四、拖放事件
1.拖動某元素時,將依次觸發下列事件:
(1)dragstart:按下鼠標並開始移動時,會在被拖放的元素上觸發dragstart事件
(2)drag:觸發dragstart事件後,隨即就會觸發drag事件,而且愛元素被拖動期間會持續觸發該事件
(3)dragend:當拖動停止時(無論是把該元素放到了有效的放置目標上還是放到了無效的放置目標上),會觸發dragend事件
上面這三個事件的目標都是被拖動元素,大多數浏覽器會為正在被拖動的元素創建一個半透明的副本,這個副本始終跟隨著光標移動。
2.當某個元素被拖動到一個有效的放置目標上時,下列事件會依次觸發:
(1)dragenter:只要有拖動元素被拖動到放置目標上,就會觸發dragenter事件
(2)dragover:在被拖動元素愛放置目標的范圍內移動時,就會持續觸發改事件
(3)dragleave 或drop:當被拖動元素拖出了放置目標,將觸發dragleave事件,如果元素被放到了放置目標中,則會觸發drop,而不會觸發dragleave事件。
什麼是有效的的放置目標呢?在拖動元素經過某些無效放置目標時,可以看到一種特殊的光標(圓環中有一條反斜槓),表示不能放置。雖然所有元素都支持放置目標事件,但這些元素默認是不允許放置的,所有要想把任何元素變成有效的放置目標,方法是重寫dragenter 和dragover事件的默認行為,也就是event.preventDefault()。這樣,當被拖動元素移動到放置目標上時,光標變成了允許放置的符號,釋放鼠標時,也會觸發drop事件。但是drop事件的默認行為是打開被放盜放置目標上的URL,當吧文本拖放到放置目標上,則會導致無效的URL錯誤,因此為了讓Firfox致辭正常的拖放,還要取消drop事件的默認行為。