← 7 User interactionTable of contents8 The HTML syntax →
    1. 7.9 Drag and drop
      1. 7.9.1 Introduction
      2. 7.9.2 The DragEvent and DataTransfer interfaces
      3. 7.9.3 Events fired during a drag-and-drop action
      4. 7.9.4 The draggable attribute
    2. 7.10 Undo history
      1. 7.10.1 The UndoManager interface
      2. 7.10.2 The UndoManagerEvent interface and the undo and redo events
    3. 7.11 Editing APIs

7.9 Drag and drop

Status: Last call for comments

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.

On media without a pointing device, the user would probably have to explicitly indicate his intention to perform a drag-and-drop operation, stating what he wishes to drag and what he wishes to drop, respectively.

7.9.1 Introduction

Status: Last call for comments

This section is non-normative.

To make an element draggable is simple: 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 data-value="fruit-apple">Apples</li>
 <li draggable data-value="fruit-orange">Oranges</li>
 <li draggable 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.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 at least three events. First, the dragenter event, which is used to determine whether or not the drop target is to accept the drop. If the drop is to be accepted, then this event has to be canceled. Second, the dragover event, which is used to determine what feedback is to be shown to the user. If the event is canceled, then the feedback (typically the cursor) is updated based on the dropEffect attribute's value, as set by the event handler; otherwise, the default behavior (typically to do nothing) is used instead. Finally, the drop event, which allows the actual drop to be performed. This event also needs to be canceled, so that the dropEffect attribute's value can be used by the source (otherwise it's reset).

For example:

<p>Drop your favorite fruits below:</p>
<ol class="dropzone"
    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) {
    // cancel the event if the drag contains data of our type
    if (event.dataTransfer.types.contains(internalDNDType))
      event.preventDefault();
  }
  function dragOverHandler(event) {
    event.dataTransfer.dropEffect = 'move';
    event.preventDefault();
  }
  function dropHandler(event) {
    // drop the data
    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) {
    // remove the dragged element
    event.target.parentNode.removeChild(event.target);
  }
</script>

7.9.2 The DragEvent and DataTransfer interfaces

Status: Last call for comments

The drag-and-drop processing model involves several events. They all use the DragEvent interface.

interface DragEvent : MouseEvent {
  readonly attribute DataTransfer dataTransfer;

  void initDragEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in any dummyArg, in long detailArg, in long screenXArg, in long screenYArg, in long clientXArg, in long clientYArg, in boolean ctrlKeyArg, in boolean altKeyArg, in boolean shiftKeyArg, in boolean metaKeyArg, in unsigned short buttonArg, in EventTarget relatedTargetArg, in DataTransfer dataTransferArg);
};
event . dataTransfer

Returns the DataTransfer object for the event.

interface DataTransfer {
           attribute DOMString dropEffect;
           attribute DOMString effectAllowed;

  readonly attribute DOMStringList types;
  void clearData(in optional DOMString format);
  void setData(in DOMString format, in DOMString data);
  DOMString getData(in DOMString format);
  readonly attribute FileList files;

  void setDragImage(in Element image, in long x, in long y);
  void addElement(in Element element);
};

DataTransfer objects can hold pieces of data, each associated with a unique format. Formats are generally given by MIME types, with some values special-cased for legacy reasons. However, the API does not enforce this; non-MIME-type values can be added as well. All formats are identified by strings that are converted to ASCII lowercase by the API.

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, to change the allowed operations.

The possible values are none, copy, copyLink, copyMove, link, linkMove, move, all, and uninitialized,

dataTransfer . types

Returns a DOMStringList 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".

dataTransfer . clearData( [ format ] )

Removes the data of the specified formats. Removes all data if the argument is omitted.

dataTransfer . setData(format, data)

Adds the specified data.

data = dataTransfer . getData(format)

Returns the specified data. If there is no such data, returns the empty string.

dataTransfer . files

Returns a FileList of the files being dragged, if any.

dataTransfer . setDragImage(element, x, y)

Uses the given element to update the drag feedback, replacing any previously specified feedback.

dataTransfer . addElement(element)

Adds the given element to the list of elements used to render the drag feedback.

7.9.3 Events fired during a drag-and-drop action

Status: Last call for comments

The following events are involved in the drag-and-drop model.

Event Name Target Bubbles? Cancelable? dataTransfer effectAllowed dropEffect Default Action
dragstart Source node ✓ Bubbles ✓ Cancelable Contains source node unless a selection is being dragged, in which case it is empty; files returns any files included in the drag operation uninitialized none Initiate the drag-and-drop operation
drag Source node ✓ Bubbles ✓ Cancelable Empty Same as last event none Continue the drag-and-drop operation
dragenter Immediate user selection or the body element ✓ Bubbles ✓ Cancelable Empty Same as last event Based on effectAllowed value Reject immediate user selection as potential target element
dragleave Previous target element ✓ Bubbles Empty Same as last event none None
dragover Current target element ✓ Bubbles ✓ Cancelable Empty Same as last event Based on effectAllowed value Reset the current drag operation to "none"
drop Current target element ✓ Bubbles ✓ Cancelable getData() returns data set in dragstart event; files returns any files included in the drag operation Same as last event Current drag operation Varies
dragend Source node ✓ Bubbles Empty Same as last event Current drag operation Varies

"Empty" in the table above means that the getData() and files attributes act as if there is no data being dragged.

7.9.4 The draggable attribute

Status: Last call for comments

All HTML elements may have the draggable content attribute set. The draggable attribute is an enumerated attribute. It has three states. The first state is true and it has the keyword true. The second state is false and it has the keyword false. The third state is auto; it has no keywords but it is the missing value default.

The true state means the element is draggable; the false state means that it is not. The auto state uses the default behavior of the user agent.

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.

7.10 Undo history

Status: Last call for comments

7.10.1 The UndoManager interface

Status: Last call for comments

To manage undo object entries in the undo transaction history, the UndoManager interface can be used:

interface UndoManager {
  readonly attribute unsigned long length;
  getter any item(in unsigned long index);
  readonly attribute unsigned long position;
  unsigned long add(in any data, in DOMString title);
  void remove(in unsigned long index);
  void clearUndo();
  void clearRedo();
};
window . undoManager

Returns the UndoManager object.

undoManager . length

Returns the number of entries in the undo history.

data = undoManager . item(index)
undoManager[index]

Returns the entry with index index in the undo history.

Returns null if index is out of range.

undoManager . position

Returns the number of the current entry in the undo history. (Entries at and past this point are redo entries.)

undoManager . add(data, title)

Adds the specified entry to the undo history.

undoManager . remove(index)

Removes the specified entry to the undo history.

Throws an INDEX_SIZE_ERR exception if the given index is out of range.

undoManager . clearUndo()

Removes all entries before the current position in the undo history.

undoManager . clearRedo()

Removes all entries at and after the current position in the undo history.

7.10.2 The UndoManagerEvent interface and the undo and redo events

Status: Last call for comments

interface UndoManagerEvent : Event {
  readonly attribute any data;
  void initUndoManagerEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in any dataArg);
};
event . data

Returns the data that was passed to the add() method.

7.11 Editing APIs

Status: Last call for comments

document . execCommand(commandId [, showUI [, value ] ] )

Runs the action specified by the first argument, as described in the list below. The second and third arguments sometimes affect the action. (If they don't they are ignored.)

document . queryCommandEnabled(commandId)

Returns whether the given command is enabled, as described in the list below.

document . queryCommandIndeterm(commandId)

Returns whether the given command is indeterminate, as described in the list below.

document . queryCommandState(commandId)

Returns the state of the command, as described in the list below.

document . queryCommandSupported(commandId)

Returns true if the command is supported; otherwise, returns false.

document . queryCommandValue(commandId)

Returns the value of the command, as described in the list below.

A document is ready for editing host commands if it has a selection that is entirely within an editing host, or if it has no selection but its caret is inside an editing host.

The possible values for commandId, and their corresponding meanings, are as follows.

bold
Summary: Toggles whether the selection is bold.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: True if the selection, or the caret, if there is no selection, is, or is contained within, a b element. False otherwise.
Value: The string "true" if the expression given for the "State" above is true, the string "false" otherwise.
createLink
Summary: Toggles whether the selection is a link or not. If the second argument is true, and a link is to be added, the user agent will ask the user for the address. Otherwise, the third argument will be used as the address.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
delete
Summary: Deletes the selection or the character before the cursor.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
formatBlock
Summary: Wraps the selection in the element given by the second argument. If the second argument doesn't specify an element that is a formatBlock candidate, does nothing.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
forwardDelete
Summary: Deletes the selection or the character after the cursor.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertImage
Summary: Toggles whether the selection is an image or not. If the second argument is true, and an image is to be added, the user agent will ask the user for the address. Otherwise, the third argument will be used as the address.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertHTML
Summary: Replaces the selection with the value of the third argument parsed as HTML.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertLineBreak
Summary: Inserts a line break.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertOrderedList
Summary: Toggles whether the selection is an ordered list.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertUnorderedList
Summary: Toggles whether the selection is an unordered list.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertParagraph
Summary: Inserts a paragraph break.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
insertText
Summary: Inserts the text given in the third parameter.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
italic
Summary: Toggles whether the selection is italic.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: True if the selection, or the caret, if there is no selection, is, or is contained within, a i element. False otherwise.
Value: The string "true" if the expression given for the "State" above is true, the string "false" otherwise.
redo
Summary: Acts as if the user had requested a redo.
Enabled When: The undo position is not at the end of the undo transaction history.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
selectAll
Summary: Selects all the editable content.
Enabled When: Always.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
subscript
Summary: Toggles whether the selection is subscripted.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: True if the selection, or the caret, if there is no selection, is, or is contained within, a sub element. False otherwise.
Value: The string "true" if the expression given for the "State" above is true, the string "false" otherwise.
superscript
Summary: Toggles whether the selection is superscripted.
Enabled When: The document is ready for editing host commands.
Indeterminate When: Never.
State: True if the selection, or the caret, if there is no selection, is, or is contained within, a sup element. False otherwise.
Value: The string "true" if the expression given for the "State" above is true, the string "false" otherwise.
undo
Summary: Acts as if the user had requested an undo.
Enabled When: The undo position is not at the start of the undo transaction history.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
unlink
Summary: Removes all links from the selection.
Enabled When: The document has a selection that is entirely within an editing host and that contains (either partially or completely) at least one a element that has an href attribute.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".
unselect
Summary: Unselects everything.
Enabled When: Always.
Indeterminate When: Never.
State: Always false.
Value: Always the string "false".