HTML 拖放操作 API

Firefox和其他Mozilla應用程式支援一系列拖拉特色功能,這讓使用者可以用滑鼠拖曳某一個元素到另一塊地方,當拖曳時,使用者可以看到一個半透明的物件代表被拖曳的元素,然後用滑鼠拖曳這個半透明元件丟入到目標區域,拖曳目標區可以是另一個應用程式。網站、外掛和XUL應用可以利用這個特色功能來自定義拖拉元素、拖曳回饋以及拖曳目標區。

本文適用Firefox 3.5 (Gecko 1.9.1)版本以後的拖拉功能,對於Firefox 3.0之前的版本請參考舊版API文件

拖拉事件

在拖拉操作不同階段會有一連串事件觸發,另外請注意在拖拉時滑鼠相關事件、如mousemove事件、不會觸發,而且當從OS拖拉檔案進入瀏覽器時,dragstart和dragend也不會觸發。

All of the drag event types have an associated global event handler. Each drag event type and drag global attribute has a reference document that describes the event. The following table provides a short description of the event types and a link to the reference documents.

Event On Event Handler Description
drag ondrag 當元素被拖曳當下觸發。
dragend ondragend 不論結果如何,拖拉作業結束當下,被拖拉元素都會收到一個dragend事件,但當從OS拖拉檔案進入瀏覽器時不會觸發,詳細請參考結束拖拉
dragenter ondragenter 當拖拉當下滑鼠移動進入一個元素時觸發;此時的事件處理器應該要明白確認是否允許在這個元素上進行拖放操作,假設沒有事件處理器或事件處理器沒有對應行動,那麼拖放操作預設不被允許。這個事件也是用來提示使用者甚麼元素是拖拉目標區,例如改變拖拉目標區元素的UI,詳細請參考指定拖拉目標區
dragexit ondragexit Fired when an element is no longer the drag operation's immediate selection target.
dragleave ondragleave 當拖拉當下滑鼠離開一個元素時觸發;此時事件處理器應該要復原之前用作為拖拉提示的特殊效果。
dragover ondragover 當拖拉當下滑鼠在一個元素上移動時觸發;絕大多數時間,這個事件的處理器所進行的作業和dragenter的事件處理器一樣,詳細請參考指定拖拉目標區
dragstart ondragstart 當拖拉開始時觸發;這個時候的事件處理器會設定拖拉資料和拖拉用的影像,且當從OS拖拉檔案進入瀏覽器時不會觸發,詳細請參考開始拖拉
drop ondrop 當丟放拖曳元素到拖拉目標區時觸發;此時事件處理器可能會需要取出拖拉資料並處理之,這個事件只有在被允許下才會觸發,如果在使用者取消拖拉操作時,如按ESC鍵或滑鼠不是在拖拉目標元素上,此事件不會觸發,詳細請參考執行丟放

介面

The HTML drag and drop interfaces are DragEvent, DataTransfer, DataTransferItem and DataTransferItemList.

The DragEvent interface has a constructor and one property, the dataTransfer property which is a DataTransfer object. DataTransfer objects include the drag event's state such as the type of drag being done (for example copy or move), the drag's data (one or more items) and the type of each drag item (a MIME type). DataTransfer objects also have methods to add items to the drag's data and to remove a drag item. The DragEvent and DataTransfer interfaces should be the only ones needed to add HTML drag and drop capabilities to an application. However, note Firefox supports some Gecko-specific extensions to the DataTransfer object that may be used, although those extensions will only work on Firefox.

Each DataTransfer object contains an items property which is a list of DataTransferItem objects. Each DataTransferItem object represents a single drag item and each item has a kind property which is the kind of data (either string or file) and a type property which is the data item's type (i.e. MIME type). The DataTransferItem object also has methods to get the drag item's data.

The DataTransferItemList object is a list of DataTransferItem objects. The list object has methods to: add a drag item to the list, remove a drag item from the list and clear the list of all drag items.

A key difference between the DataTransfer and DataTransferItem interfaces is that the former uses the synchronous getData() method to access a drag item's data, whereas the later uses the asynchronous getAsString() method to access a drag item's data.

註:the DragEvent and DataTransfer interfaces are broadly interoperable with desktop browsers. However, the DataTransferItem and DataTransferItemList interfaces have limited browser support. See Interoperability for more information about drag and drop interoperability.

Gecko-specific interfaces

Mozilla和Firefox支援一些非標準的拖拉特色功能,允許使用者拖拉多個物件和非字串資料,關於這些非標準特色請參考拖拉多個物件

關於常見的拖拉之資料型態請參考推薦拖拉資料型態,關於存取拖拉資料會用到的DataTransfer物件請參考DataTransfer

拖拉基礎

達成拖曳和丟放功能,只需要遵照幾個設定步驟:

定義欲可拖曳的目標

在想要拖曳的元素上設定draggable屬性為true,詳情請見Draggable屬性

function dragstart_handler(ev) {
 console.log("dragStart");
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("text/plain", ev.target.id);
}

<body>
 <p id="p1" draggable="true" ondragstart="dragstart_handler(event);">This element is draggable.</p>
</body>

See the draggable attribute reference and the Drag operations guide for more information.

定義拖曳時所要攜帶的資料

這些資料可以是多個不同格式的資料,比如說,文字資料,詳情請見拖曳資料

Each drag event has a dataTransfer property that holds the event's data. This property (which is a DataTransfer object) also has methods to manage drag data. The setData() method is used to add an item to the drag data, as shown in the following example.

function dragstart_handler(ev) {
  // Add the drag data
  ev.dataTransfer.setData("text/plain", ev.target.id);
  ev.dataTransfer.setData("text/html", "<p>Example paragraph</p>");
  ev.dataTransfer.setData("text/uri-list", "http://developer.mozilla.org");
}

For a list of common data types used for drag and drop (such as text, HTML, links, and files), see Recommended Drag Types and for more information about drag data, see Drag Data.

Define the drag image

當滑鼠拖曳時,用來作為拖曳效果回饋的影像;這個影像有時可以客製,但絕大多數時候只能沿用預設從被拖曳元素所產生的影像,詳情請見設定拖曳圖片

function dragstart_handler(ev) {
  // Create an image and then use it for the drag image.
  // NOTE: change "example.gif" to an existing image or the image 
  // will not be created and the default drag image will be used.
  var img = new Image(); 
  img.src = 'example.gif'; 
  ev.dataTransfer.setDragImage(img, 10, 10);
}

To learn more about drag feedback images, see Setting the Drag Feedback Image.

定義拖曳效果

共有三個效果,一是copy,copy代表拖曳的資料會被複製到拖曳目標區;二是move,move代表拖曳的資料會被移動;三是link,link代表拖曳來源區和拖曳目標區之間會建立起某種關係或關聯。拖曳進行中時,可以修改拖曳效果以表示某個效果在某個地方是被允許的,如果允許,丟放便可以在該地方發生,詳情請見拖曳效果

Three effects may be defined: 

copy indicates that the data being dragged will be copied from its present location to the drop location. 

move indicates that the data being dragged will be moved

link indicates that some form of relationship or connection will be created between the source and drop locations. 

During the drag operation, the drag effects may be modified to indicate that certain effects are allowed at certain locations. If allowed, a drop may occur at that location.

The following example shows how to use this property.

function dragstart_handler(ev) {
  // Set the drag effect to copy
  ev.dataTransfer.dropEffect = "copy";
}

See Drag Effects for more details.

定義拖曳目標

瀏覽器預設不允許拖曳物件,然後丟放到HTML元素上,所以要註冊ondragover事件來阻止瀏覽器的預設行為,詳情請見設定拖曳目標

function dragover_handler(ev) {
 ev.preventDefault();
 // Set the dropEffect to move
 ev.dataTransfer.dropEffect = "move"
}
function drop_handler(ev) {
 ev.preventDefault();
 // Get the id of the target and add the moved element to the target's DOM
 var data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
}
<body>
 <div id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">Drop Zone</div>
</body>

Note each handler calls preventDefault() to prevent additional event processing for this prevent (such as touch events or pointer events).

For more information, see Specifying Drop Targets.

處理拖曳丟放事件

當物件被拖曳、丟放後,你可能會想要取得其中的資料並且做些事情,請參考丟放物件

The following example shows a drop handler getting the source element's id from the drag data and then using the id to move the source element to the drop element.

function dragstart_handler(ev) {
 ev.preventDefault();
 // Add the target element's id to the data transfer object
 ev.dataTransfer.setData("text/plain", ev.target.id);
 ev.dropEffect = "move";
}
function drop_handler(ev) {
 ev.preventDefault();
 // Get the id of the target and add the moved element to the target's DOM
 var data = ev.dataTransfer.getData("text");
 ev.target.appendChild(document.getElementById(data));
}
<body>
 <p id="p1" draggable="true" ondragstart="dragstart_handler(event);">This element is draggable.</p>
 <div id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">Drop Zone</div>
</body>

For more information, see Performing a Drop.

Drag end

At the end of a drag operation, the dragend event fires at the source element - the element that was the target of the drag start. This event fires whether the drag completed or was canceled. The dragend event handler can check the value of the dropEffect property to determine if the drag operation succeeded or not.

For more information about handling the end of a drag operation, see Finishing a Drag.

Interoperability

As can be seen in the DataTransferItem interface's Browser Compatibility table, drag-and-drop interoperability is relatively broad among desktop browsers (except the DataTransferItem and DataTransferItemList interfaces have less support). This data also indicates drag and drop support among mobile browsers is very low.

例範和 Demo

參見

文件標籤與貢獻者

 此頁面的貢獻者: jackblackevo, teoli, foxbrush
 最近更新: jackblackevo,