這幾天做了一些drag&drop操作方面的工作,在這里把一些注意事項(xiàng)記錄下來(lái),算是給自己備個(gè)忘,也給需要做類(lèi)似工作的人留個(gè)樹(shù)陰。這里要討論的drag&drop是指使用IE提供的內(nèi)置機(jī)制,而不是使用鼠標(biāo)模擬的那種"假"drag&drop,比如移動(dòng)一個(gè)div或span的效果那種。
要實(shí)現(xiàn)和控制drag&drop操作,那么首先第一點(diǎn)要弄清楚的是,到底哪些元素是可以在Web上被drag的?實(shí)際上IE默認(rèn)給我們并讓我們drag的元素并不多,它們是:
圖片、
選中的文字(包括頁(yè)面文字和文字控件(input, textarea)中的文字)和
連接(普通連接和錨點(diǎn))。除此之外,別的Web元素默認(rèn)都不支持drag操作(在這些元素上面drag其實(shí)就是選擇操作了),所以要實(shí)現(xiàn)對(duì)元素默認(rèn)的drag&drop控制,只能選這3類(lèi)元素來(lái)操作。
在BizStruct同學(xué)的斧正中提到,其實(shí)幾乎所有的Html元素都是支持drag&drop的(見(jiàn)其回復(fù)),在此表示由衷的感謝。
接下來(lái),那么哪些元素又是可以接受drop操作呢?任何頁(yè)面上的可見(jiàn)元素都是可以接受drop操作的,而它們之間的不同只是在于默認(rèn)的drop事件不一樣。比如,文字控件(input, textarea)的默認(rèn)drop事件就是獲取drag操作傳過(guò)來(lái)的文字內(nèi)容;iframe元素的默認(rèn)drop操作是到航道drag操作傳過(guò)來(lái)的URL地址。當(dāng)然絕大多數(shù)的Web元素的默認(rèn)是操作是do nothing,什么也不做。
那么當(dāng)進(jìn)行drag&drop操作時(shí),有那些是可控制和定制的內(nèi)容呢?這里關(guān)于drag&drop提供了以下一些事件(我們把它們分為作用于
來(lái)源對(duì)象和
目的對(duì)象來(lái)分別討論),先討論主要作用于
來(lái)源對(duì)象的事件:
·ondrag —— 在整個(gè)從drag動(dòng)作開(kāi)始,直道drop動(dòng)作結(jié)束的過(guò)程中,都會(huì)觸發(fā)的一個(gè)事件。
·ondragstart —— 在drag動(dòng)作開(kāi)始時(shí),在來(lái)源對(duì)象上觸發(fā)的一個(gè)事件。
·ondragend —— 在drop動(dòng)作結(jié)束的時(shí)候,在來(lái)源對(duì)象上出發(fā)的一個(gè)事件。
而主要做要在目的對(duì)象上的事件:
·ondragenter —— 在drag動(dòng)作進(jìn)入某一有效目的元素時(shí),在該目的元素上觸發(fā)的一個(gè)事件。
·ondragover —— 在drag動(dòng)作進(jìn)入某一有效目的元素后,在該目的元素上觸發(fā)的一個(gè)事件。
·ondragleave —— 在drag動(dòng)作離開(kāi)某一有效目的元素時(shí),在該目的元素上觸發(fā)的一個(gè)事件。
·ondrop —— 在任何有效目的元素上進(jìn)行drop操作時(shí),在該目的元素上觸發(fā)的一個(gè)事件。
這里的來(lái)源和目的的劃分不是絕對(duì)的,比如ondragover事件,在drag操作過(guò)程中,如果鼠標(biāo)進(jìn)入了來(lái)源對(duì)象中,同樣的也會(huì)觸發(fā)這個(gè)事件。這些事件觸發(fā)的順序是:來(lái)源對(duì)象 --> ondragstart --> ondrag --> ondragend;目的對(duì)象 --> ondragenter --> ondragover --> ( ondragleave | ondrap )。由于是分別在同一個(gè)對(duì)象上觸發(fā)的事件,所以這個(gè)順序很簡(jiǎn)單。那么對(duì)于一個(gè)完整的從來(lái)源對(duì)象到目的對(duì)象的drag&drop操作來(lái)說(shuō),事件的觸發(fā)序列又是怎樣呢?如果src表示來(lái)源對(duì)象,des表示目的對(duì)象,那么事件觸發(fā)序列為:
src:ondragstart --> src:ondrag --> des:ondragenter --> des:ondragover --> ( des:ondragleave | des:ondrop ) --> src:ondragend.
示例為:Drag Source Drop Destination // 如果alert窗口不響應(yīng)鼠標(biāo)點(diǎn)擊可以使用鍵盤(pán)的space鍵來(lái)確定窗口
了解了事件觸發(fā)順序后,定制drag&drop過(guò)程中鼠標(biāo)的光標(biāo)形狀也是非常重要的一個(gè)內(nèi)容。因?yàn)橛脩?hù)的drag&drop的整個(gè)過(guò)程都需要靠鼠標(biāo)光標(biāo)的形狀指導(dǎo)其進(jìn)行操作,如果不能實(shí)時(shí)的調(diào)整光標(biāo)為適合的型狀,drag&drop操作對(duì)用戶(hù)來(lái)說(shuō)將無(wú)異于朦眼尋物。IE提供了用來(lái)控制的drag&drop過(guò)程中光標(biāo)形狀的兩個(gè)屬性,它們是:effectAllowed和dropEffect。
其屬性分別為:
·effectAllowed: copy, link, move, copyLink, copyMove, all, none & uninitialized.
·dropEffect: copy, link, move, none.
前者effectAllowed是用來(lái)控制允許drag&drop操作類(lèi)型的,所以這里的effect不是顯示的"效果",而是是否可以執(zhí)行的"操作",并且該屬性只能在ondragstart事件中進(jìn)行初始化,之后再對(duì)其賦值將無(wú)效。當(dāng)然如果只使用effectAllowed屬性,就已經(jīng)可以達(dá)到控制光標(biāo)形狀的作用了。只是effectAllowed屬性在處理復(fù)合操作時(shí),比如copyLink, copyMove和all,會(huì)默認(rèn)顯示靠前那個(gè)操作類(lèi)型的鼠標(biāo)類(lèi)型。也就是說(shuō)如果effectAllowed是copyMove,那么這是鼠標(biāo)光標(biāo)就是copy形狀。這下就知道為什么還要弄個(gè)dropEffect屬性了吧?不過(guò)這個(gè)dropEffect屬性中指定的effect,只能是之前effectAllowed允許的操作類(lèi)型范圍中的值,否則沒(méi)有效果(顯示no-drop鼠標(biāo)光標(biāo))。
示例為: Drag Source Drop Destination
如果查看代碼,會(huì)發(fā)現(xiàn)在src和des的對(duì)象元素中,在ondragover事件里除了對(duì)dropEffect賦以適當(dāng)?shù)闹低猓€有兩句話(huà): event.returnValue=false;
event.cancelBubble=true;
只是由于頁(yè)面元素在接受dragover的時(shí)候,本身都有其默認(rèn)的鼠標(biāo)光標(biāo)顯示型狀,所以為了讓用戶(hù)自定義的鼠標(biāo)光標(biāo)生效,就需要使事件event的returenValue為false值并停止當(dāng)事件的冒泡(event.cancelBubble=true)。
到目前為止,一個(gè)完整的drag&drop過(guò)程就差數(shù)據(jù)傳遞了,其實(shí)忙活了半天,這才是藏在所有交互操作和顯示效果下面最重要的步驟。這個(gè)過(guò)程需要借助于IE提供的DHTML Data Transfer對(duì)象來(lái)完成,在window對(duì)象的屬性event對(duì)象中,分別有兩個(gè)Data Transfer對(duì)象各自的一個(gè)實(shí)例:一個(gè)叫dataTransfer,另一個(gè)叫clipboardData。這兩個(gè)對(duì)象實(shí)例的行為非常相似,但又有一些區(qū)別,clipboardData顧名思義,它使用操作系統(tǒng)的剪貼板來(lái)存取數(shù)據(jù),并有3個(gè)方法;而dataTransfer通過(guò)操作一個(gè)自己的內(nèi)部剪貼板來(lái)存取數(shù)據(jù)(每次ondragend事件觸發(fā)后就自動(dòng)清空了),除了有和clipboardData相同的3個(gè)方法外,還有兩個(gè)屬性(就是前面介紹的那兩個(gè)effectAllowed和dropEffect)。
我們這里不對(duì)clipboardData作更多的討論,繼續(xù)來(lái)看dataTransfer對(duì)象。它包含3個(gè)方法,它們是:setData(sDataFormat, sText), getData(sDataFormat)和clearData([sDataFormat])。它們更詳細(xì)的使用和參數(shù)請(qǐng)參閱MSDN,這里我只用它們來(lái)實(shí)現(xiàn)drag&drop的數(shù)據(jù)傳遞。
示例為:Drag Source Drop Destination
其實(shí)很簡(jiǎn)單,就是在src的ondragstart中,調(diào)用event.dataTransfer.setData(‘TEXT‘, this.innerText),然后再des的ondrop事件中,調(diào)用this.innerText = event.dataTransfer.getData(‘TEXT‘)就行了。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。