HTML 拖放接口使应用程序能够在Firefox和其他浏览器中使用拖放功能。例如,通过这些功能,用户可以使用鼠标选择可拖动元素,将元素拖动到可放置元素,并通过释放鼠标按钮来放置这些元素。可拖动元素的一个半透明表示在拖动操作期间跟随鼠标指针。
对于网站、扩展以及 XUL 应用程序来说,你可以自定义能够成为可拖拽的元素类型、可拖拽元素产生的反馈类型,以及可放置的元素。
此文档为 HTML 拖放的概述,包含了相关接口的说明、在应用程序中加入拖放支持的基本步骤,以及相关接口的使用简介。
拖拽事件
HTML的drag和drop使用了 DOM event model
以及从mouse events
继承而来的 drag events
。一个典型的drag操作是这样开始的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发(比如drag
和 dragover
事件类型)。
所有的drag event types 有一个对应的 global event handler。每个拖动事件类型和拖动全局属性都有对应的描述文档。下面的表格提供了一个简短的事件类型描述,以及一个相关文档的链接。
Event | On Event Handler | Description |
---|---|---|
drag |
ondrag |
Fired when an element or text selection is being dragged. |
dragend |
ondragend |
Fired when a drag operation is being ended (for example, by releasing a mouse button or hitting the escape key). (See Finishing a Drag.) |
dragenter |
ondragenter |
Fired when a dragged element or text selection enters a valid drop target. (See Specifying Drop Targets.) |
dragexit |
ondragexit |
Fired when an element is no longer the drag operation's immediate selection target. |
dragleave |
ondragleave |
Fired when a dragged element or text selection leaves a valid drop target. |
dragover |
ondragover |
Fired when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds). |
dragstart |
ondragstart |
Fired when the user starts dragging an element or text selection. (See Starting a Drag Operation.) |
drop |
ondrop |
Fired when an element or text selection is dropped on a valid drop target. (See Performing a Drop.) |
注意当从操作系统向浏览器中拖动文件时,不会触发dragstart
和dragend
事件。
接口
HTML的拖拽接口有 DragEvent
, DataTransfer
, DataTransferItem
和DataTransferItemList
。
DragEvent
接口有一个构造函数和一个dataTransfer属性,dataTransfer属性是一个DataTransfer对象。 DataTransfer
对象包含了拖拽事件的状态,例如拖动事件的类型(如拷贝或者移动),拖动的数据(一个或者多个项)和每个拖动项的类型(MIME类型)。 DataTransfer
对象也有一些方法,可以向拖动数据中添加项或者删除项。 DragEvent
和 DataTransfer
接口应该仅有的接口来给应用程序添加html拖放功能。
但是,注意firefox给DataTransfer
添加了可能用到的一些扩展的功能,尽管这些扩展只在firefox上才可用。每个DataTransfer
包含一个items属性,这个属性是一个DataTransferItem
对象的列表。
每一个 DataTransfer
对象代表一个单独的拖动项,每一项有个kind属性,代表数据的kind(string或者file),也有个type属性,代表数据项的type(例如MIME类型),另外,DataTransferItem
对象也包含了得到拖拽项的数据的方法。
DataTransferItemList
对象是DataTransferItem
对象的列表。这个列表对象包含以下方法:向列表中添加拖动项,从列表中移除拖动项和清空列表中所有的拖拽项。
DataTransfer
和DataTransferItem
接口的一个主要的不同在于,前者使用同步的getData()
方法去得到一个拖拽项的数据,然后后者使用异步的getAsString()
方法得到一个拖拽项的数据。
Note: 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-专用接口
Mozilla and Firefox support some features not in the standard drag and drop model. These are convenience functions to facilitate dragging multiple items and dragging non-string data (such as files). For more information, see Dragging and Dropping Multiple Items. Additionally, see the DataTransfer
reference page for all of the Gecko-specific properties and Gecko-specific methods.
基础
This section provides a summary of the basic steps to add drag and drop functionality to an application. Each section includes a description of the step, a short code example, and links to additional information.
确定什么是可拖动的
To make an element draggable requires adding the draggable
attribute plus the ondragstart
global event handler, as shown in the following code sample
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.
定义拖动数据
The application is free to include any number of data items in a drag operation. Each data item is a string
of a particular type
, typically a MIME type such as text/html
.
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.
定义拖动图像
By default, the browser supplies an image that appears beside the mouse pointer during a drag operation. However, an application may define a custom image by using the setDragImage()
method as shown in the following example.
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.
定义拖动效果
The dropEffect
property is used to control the feedback (typically visual) the user is given during a drag and drop operation. It affects which cursor the browser displays while dragging. For example, when the user hovers over a target drop element, the browser's cursor may indicate the type of operation that will occur.
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.
定义一个放置区
By default, the browser prevents anything from happening when dropping something onto the HTML element. To change that behavior so that an element becomes a drop zone or is droppable, the element must have both ondragover
and ondrop
event handler attributes. The following example shows how to use those attributes and includes basic event handlers for each attribute.
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 handler for the drop
event is free to process the drag data in an application specific way. Typically, an application will use the getData()
method to retrieve drag items and process them accordingly. Additionally, application semantics may differ depending on the value of the dropEffect
and/or the state of modifier keys.
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) { // Add the target element's id to the data transfer object ev.dataTransfer.setData("text/plain", ev.target.id); ev.dropEffect = "move"; } 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> <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.
拖动结束
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.
互操性
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.
示例和演示
- Copying and moving elements with the
DataTransfer
interface - Copying and moving elements with the
DataTransferListItem
interface - Dragging and dropping files; Firefox only: http://jsfiddle.net/9C2EF/
- Dragging and dropping files; All browsers: https://jsbin.com/hiqasek/