Edition for Web Developers — Last Updated 21 November 2024
Support in all current engines.
This section defines an event-based drag-and-drop mechanism.
This specification does not define exactly what a drag-and-drop operation actually is.
On a visual medium with a pointing device, a drag operation could be the default action of a
mousedown
event that is followed by a series of mousemove
events, and the drop could be triggered by the mouse
being released.
When using an input modality other than a pointing device, users would probably have to explicitly indicate their intention to perform a drag-and-drop operation, stating what they wish to drag and where they wish to drop it, respectively.
To make an element draggable, give the element a draggable
attribute, and set an event listener for dragstart
that
stores the data being dragged.
The event handler typically needs to check that it's not a text selection that is being
dragged, and then needs to store data into the DataTransfer
object and set the
allowed effects (copy, move, link, or some combination).
For example:
< p > What fruits do you like?</ p >
< ol ondragstart = "dragStartHandler(event)" >
< li draggable = "true" data-value = "fruit-apple" > Apples</ li >
< li draggable = "true" data-value = "fruit-orange" > Oranges</ li >
< li draggable = "true" data-value = "fruit-pear" > Pears</ li >
</ ol >
< script >
var internalDNDType = 'text/x-example' ; // set this to something specific to your site
function dragStartHandler( event) {
if ( event. target instanceof HTMLLIElement) {
// use the element's data-value="" attribute as the value to be moving:
event. dataTransfer. setData( internalDNDType, event. target. dataset. value);
event. dataTransfer. effectAllowed = 'move' ; // only allow moves
} else {
event. preventDefault(); // don't allow selection to be dragged
}
}
</ script >
To accept a drop, the drop target has to listen to the following events:
dragenter
event handler reports
whether or not the drop target is potentially willing to accept the drop, by canceling the
event.dragover
event handler specifies what feedback
will be shown to the user, by setting the dropEffect
attribute of the
DataTransfer
associated with the event. This event also needs to be canceled.drop
event handler has a final chance to accept or
reject the drop. If the drop is accepted, the event handler must perform the drop operation on
the target. This event needs to be canceled, so that the dropEffect
attribute's value can be used by the
source. Otherwise, the drop operation is rejected.For example:
< p > Drop your favorite fruits below:</ p >
< ol ondragenter = "dragEnterHandler(event)" ondragover = "dragOverHandler(event)"
ondrop = "dropHandler(event)" >
</ ol >
< script >
var internalDNDType = 'text/x-example' ; // set this to something specific to your site
function dragEnterHandler( event) {
var items = event. dataTransfer. items;
for ( var i = 0 ; i < items. length; ++ i) {
var item = items[ i];
if ( item. kind == 'string' && item. type == internalDNDType) {
event. preventDefault();
return ;
}
}
}
function dragOverHandler( event) {
event. dataTransfer. dropEffect = 'move' ;
event. preventDefault();
}
function dropHandler( event) {
var li = document. createElement( 'li' );
var data = event. dataTransfer. getData( internalDNDType);
if ( data == 'fruit-apple' ) {
li. textContent = 'Apples' ;
} else if ( data == 'fruit-orange' ) {
li. textContent = 'Oranges' ;
} else if ( data == 'fruit-pear' ) {
li. textContent = 'Pears' ;
} else {
li. textContent = 'Unknown Fruit' ;
}
event. target. appendChild( li);
}
</ script >
To remove the original element (the one that was dragged) from the display, the dragend
event can be used.
For our example here, that means updating the original markup to handle that event:
< p > What fruits do you like?</ p >
< ol ondragstart = "dragStartHandler(event)" ondragend = "dragEndHandler(event)" >
...as before...
</ ol >
< script >
function dragStartHandler( event) {
// ...as before...
}
function dragEndHandler( event) {
if ( event. dataTransfer. dropEffect == 'move' ) {
// remove the dragged element
event. target. parentNode. removeChild( event. target);
}
}
</ script >
The data that underlies a drag-and-drop operation, known as the drag data store, consists of the following information:
A drag data store item list, which is a list of items representing the dragged data, each consisting of the following information:
The kind of data:
Text.
Binary data with a filename.
A Unicode string giving the type or format of the data, generally given by a MIME type. Some values that are not MIME types are special-cased for legacy reasons. The API does not enforce the use of MIME types; other values can be used as well. In all cases, however, the values are all converted to ASCII lowercase by the API.
There is a limit of one text item per item type string.
A Unicode or binary string, in some cases with a filename (itself a Unicode string), as per the drag data item kind.
The drag data store item list is ordered in the order that the items were added to the list; most recently added last.
The following information, used to generate the UI feedback during the drag:
A drag data store mode, which is one of the following:
For the dragstart
event. New data can be added to the
drag data store.
For the drop
event. The list of items representing dragged
data can be read, including the data. No new data can be added.
For all other events. The formats and kinds in the drag data store list of items representing dragged data can be enumerated, but the data itself is unavailable and no new data can be added.
A drag data store allowed effects state, which is a string.
When a drag data store is created, it
must be initialized such that its drag data store item list is empty, it has no
drag data store default feedback, it has no drag data store bitmap and
drag data store hot spot coordinate, its drag data store mode is protected mode, and its drag data store allowed effects
state is the string "uninitialized
".
DataTransfer
interfaceSupport in all current engines.
DataTransfer
objects are used to expose the drag data store that
underlies a drag-and-drop operation.
dataTransfer = new DataTransfer()
Creates a new DataTransfer
object with an empty drag data
store.
dataTransfer.dropEffect [ = value ]
Returns the kind of operation that is currently selected. If the kind of operation isn't one
of those that is allowed by the effectAllowed
attribute, then the operation will
fail.
Can be set, to change the selected operation.
The possible values are "none
", "copy
", "link
", and "move
".
dataTransfer.effectAllowed [ = value ]
Returns the kinds of operations that are to be allowed.
Can be set (during the dragstart
event), to change
the allowed operations.
The possible values are "none
",
"copy
", "copyLink
", "copyMove
", "link
", "linkMove
", "move
", "all
", and "uninitialized
",
dataTransfer.items
Returns a DataTransferItemList
object, with the drag data.
dataTransfer.setDragImage(element, x, y)
Uses the given element to update the drag feedback, replacing any previously specified feedback.
dataTransfer.types
Returns a frozen array listing the formats that were set in the dragstart
event. In addition, if any files are being
dragged, then one of the types will be the string "Files
".
data = dataTransfer.getData(format)
Returns the specified data. If there is no such data, returns the empty string.
dataTransfer.setData(format, data)
Adds the specified data.
dataTransfer.clearData([ format ])
Removes the data of the specified formats. Removes all data if the argument is omitted.
dataTransfer.files
Returns a FileList
of the files being dragged, if any.
DataTransfer
objects that are created as part of drag-and-drop events are only valid while those events are being fired.
DataTransferItemList
interfaceSupport in all current engines.
Each DataTransfer
object is associated with a DataTransferItemList
object.
items.length
Returns the number of items in the drag data store.
items[index]
Returns the DataTransferItem
object representing the indexth entry in
the drag data store.
items.remove(index)
Removes the indexth entry in the drag data store.
items.clear()
Removes all the entries in the drag data store.
items.add(data)
items.add(data, type)
Adds a new entry for the given data to the drag data store. If the data is plain text then a type string has to be provided also.
DataTransferItem
interfaceSupport in all current engines.
Each DataTransferItem
object is associated with a DataTransfer
object.
item.kind
Returns the drag data item kind, one of: "string", "file".
item.type
Returns the drag data item type string.
item.getAsString(callback)
Invokes the callback with the string data as the argument, if the drag data item kind is text.
file = item.getAsFile()
Returns a File
object, if the drag data item kind is
File.
DragEvent
interfaceSupport in all current engines.
Support in all current engines.
The drag-and-drop processing model involves several events. They all use the
DragEvent
interface.
event.dataTransfer
Returns the DataTransfer
object for the event.
Although, for consistency with other event interfaces, the DragEvent
interface has a constructor, it is not particularly useful. In particular, there's no way to
create a useful DataTransfer
object from script, as DataTransfer
objects
have a processing and security model that is coordinated by the browser during drag-and-drops.
The following events are involved in the drag-and-drop model.
Event name | Target | Cancelable? | Drag data store mode | dropEffect | Default Action |
---|---|---|---|---|---|
dragstart Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Source node | ✓ Cancelable | Read/write mode | "none " | Initiate the drag-and-drop operation |
drag Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Source node | ✓ Cancelable | Protected mode | "none " | Continue the drag-and-drop operation |
dragenter Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Immediate user selection or the body element | ✓ Cancelable | Protected mode | Based on effectAllowed value | Reject immediate user selection as potential target element |
dragleave Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Previous target element | — | Protected mode | "none " | None |
dragover Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Current target element | ✓ Cancelable | Protected mode | Based on effectAllowed value | Reset the current drag operation to "none" |
drop Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Current target element | ✓ Cancelable | Read-only mode | Current drag operation | Varies |
dragend Support in all current engines. Firefox9+Safari3.1+Chrome1+ Opera12+Edge79+ Edge (Legacy)12+Internet Explorer9+ Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+ | Source node | — | Protected mode | Current drag operation | Varies |
All of these events bubble, are composed, and the effectAllowed
attribute always has the value it had
after the dragstart
event, defaulting to "uninitialized
" in the dragstart
event.
draggable
attributeSupport in all current engines.
All HTML elements may have the draggable
content attribute set. The draggable
attribute is an enumerated attribute with
the following keywords and states:
Keyword | State | Brief description |
---|---|---|
true
| true | The element will be draggable. |
false
| false | The element will not be draggable. |
The attribute's missing value default and invalid value default are both the auto state. The auto state uses the default behavior of the user agent.
An element with a draggable
attribute should also have a
title
attribute that names the element for the purpose of
non-visual interactions.
element.draggable [ = value ]
Returns true if the element is draggable; otherwise, returns false.
Can be set, to override the default and set the draggable
content attribute.