1. 6.11 拖放
      1. 6.11.1 简介
      2. 6.11.2 拖放数据存储
      3. 6.11.3 DataTransfer 接口
        1. 6.11.3.1 DataTransferItemList 接口
        2. 6.11.3.2 DataTransferItem 接口
      4. 6.11.4 DragEvent 接口
      5. 6.11.5 事件汇总
      6. 6.11.6 draggable 属性

6.11 拖放

HTML_Drag_and_Drop_API

所有当前引擎都支持。

Firefox3.5+Safari3.1+Chrome4+
Opera12+Edge79+
Edge (旧版)18Internet Explorer5.5+
Firefox Android4+Safari iOS2+Chrome Android18+WebView Android4.4+Samsung Internet1.5+Opera Android14+

本节定义了一种基于事件的拖放机制。

本规范没有定义拖放操作究竟是什么。

在具有指向设备的可视媒体上,拖动操作可能是mousedown事件的默认操作,后面跟着一系列mousemove事件,释放鼠标可以触发放下操作。

当使用除指向设备以外的输入模式时,用户可能需要明确指示其执行拖放操作的意图,分别说明他们希望拖动什么以及希望将其放在哪里。

6.11.1 简介

要使元素可拖动,请为元素提供一个draggable属性,并为dragstart设置一个事件监听器,以存储正在拖动的的数据。

事件处理程序通常需要检查它是否不是正在拖动的文本选择,然后需要将数据存储到DataTransfer对象中并设置允许的效果(复制、移动、链接或某些组合)。

例如

<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>

要接受放下操作,放下目标必须监听以下事件

  1. dragenter事件处理程序通过取消事件来报告放下目标是否可能愿意接受放下操作。
  2. dragover事件处理程序通过设置与事件关联的DataTransferdropEffect属性来指定将向用户显示什么反馈。此事件也需要被取消。
  3. drop事件处理程序最后有机会接受或拒绝放下操作。如果接受放下操作,则事件处理程序必须在目标上执行放下操作。此事件需要被取消,以便dropEffect属性的值可以被源使用。否则,放下操作将被拒绝。

例如

<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>

要从显示中删除原始元素(即被拖动的元素),可以使用dragend事件。

对于我们这里的示例,这意味着更新原始标记以处理该事件

<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>

6.11.2 拖放数据存储

构成拖放操作基础的数据,称为拖放数据存储,包含以下信息

拖放数据存储创建时,必须对其进行初始化,使其拖放数据存储项列表为空,没有拖放数据存储默认反馈,没有拖放数据存储位图拖放数据存储热点坐标,其拖放数据存储模式保护模式,其拖放数据存储允许效果状态为字符串“uninitialized”。

6.11.3 DataTransfer 接口

DataTransfer

所有当前引擎都支持。

Firefox3.5+Safari4+Chrome3+
Opera12+Edge79+
Edge (旧版)12+Internet Explorer8+
Firefox Android?Safari iOS?Chrome Android?WebView Android37+Samsung Internet?Opera Android12+

DataTransfer对象用于公开构成拖放操作基础的拖放数据存储

dataTransfer = new DataTransfer()

创建一个新的DataTransfer对象,并带有一个空的拖放数据存储

dataTransfer.dropEffect [ = value ]

返回当前选定的操作类型。如果操作类型不是effectAllowed属性允许的操作类型之一,则操作将失败。

可以设置,以更改选定的操作。

可能的值为“none”、“copy”、“link”和“move”。

dataTransfer.effectAllowed [ = value ]

返回要允许的操作类型。

可以设置(在dragstart事件期间),以更改允许的操作。

可能的值为“none”、“copy”、“copyLink”、“copyMove”、“link”、“linkMove”、“move”、“all”和“uninitialized”,

dataTransfer.items

返回一个DataTransferItemList对象,其中包含拖放数据。

dataTransfer.setDragImage(element, x, y)

使用给定的元素更新拖动反馈,替换任何先前指定的反馈。

dataTransfer.types

返回一个冻结数组,其中列出了在dragstart事件中设置的格式。此外,如果正在拖动任何文件,则其中一个类型将是字符串“Files”。

data = dataTransfer.getData(format)

返回指定的数据。如果没有此类数据,则返回空字符串。

dataTransfer.setData(format, data)

添加指定的数据。

dataTransfer.clearData([ format ])

删除指定格式的数据。如果省略参数,则删除所有数据。

dataTransfer.files

返回一个FileList,其中包含正在拖动的文件(如果有)。

作为拖放事件的一部分创建的DataTransfer对象仅在触发这些事件时有效。

6.11.3.1 DataTransferItemList 接口

DataTransferItemList

所有当前引擎都支持。

Firefox50+Safari6+Chrome13+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android14+

每个 DataTransfer 对象都关联着一个 DataTransferItemList 对象。

items.length

返回拖放数据存储区中的项目数量。

items[index]

返回表示拖放数据存储区中第 index 个条目的 DataTransferItem 对象。

items.remove(index)

移除拖放数据存储区中的第 index 个条目。

items.clear()

移除拖放数据存储区中的所有条目。

items.add(data)
items.add(data, type)

为给定的数据添加一个新条目到拖放数据存储区。如果数据是纯文本,则还需要提供一个 type 字符串。

6.11.3.2 DataTransferItem 接口

DataTransferItem

所有当前引擎都支持。

Firefox50+Safari5.1+Chrome11+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer不支持
Firefox Android?Safari iOS?Chrome Android?WebView Android4+Samsung Internet?Opera Android14+

每个 DataTransferItem 对象都关联着一个 DataTransfer 对象。

item.kind

返回拖放数据项类型,其中之一:“string”,“file”。

item.type

返回拖放数据项类型字符串。

item.getAsString(callback)

如果拖放数据项类型为“text”,则使用字符串数据作为参数调用回调函数。

file = item.getAsFile()

返回一个 File 对象,如果拖放数据项类型为“File”。

6.11.4 DragEvent 接口

DragEvent/DragEvent

所有当前引擎都支持。

Firefox3.5+Safari14+Chrome46+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer不支持
Firefox Android?Safari iOS不支持Chrome Android不支持WebView Android?Samsung Internet?Opera Android?

DragEvent

所有当前引擎都支持。

Firefox3.5+Safari14+Chrome46+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS不支持Chrome Android不支持WebView Android?Samsung Internet?Opera Android?

拖放处理模型涉及多个事件。它们都使用 DragEvent 接口。

event.dataTransfer

返回事件的 DataTransfer 对象。

尽管为了与其他事件接口保持一致,DragEvent 接口有一个构造函数,但它并不是特别有用。特别是,无法从脚本创建有用的 DataTransfer 对象,因为 DataTransfer 对象具有由浏览器在拖放过程中协调的处理和安全模型。

6.11.5 事件摘要

以下事件参与拖放模型。

事件名称目标可取消? 拖放数据存储模式 dropEffect 默认操作
dragstart

HTMLElement/dragstart_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
源节点✓ 可取消读写模式 "none"启动拖放操作
drag

HTMLElement/drag_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
源节点✓ 可取消保护模式 "none"继续拖放操作
dragenter

HTMLElement/dragenter_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
用户立即选择body 元素✓ 可取消保护模式 基于 effectAllowed拒绝 用户立即选择 作为潜在的 目标元素
dragleave

HTMLElement/dragleave_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
上一个目标元素保护模式 "none"
dragover

HTMLElement/dragover_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
当前目标元素✓ 可取消保护模式 基于 effectAllowed当前拖放操作 重置为“none”
drop

HTMLElement/drop_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
当前目标元素✓ 可取消只读模式 当前拖放操作变化
dragend

HTMLElement/dragend_event

所有当前引擎都支持。

Firefox9+Safari3.1+Chrome1+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+
源节点保护模式 当前拖放操作变化

所有这些事件都会冒泡,并且是组合的,并且 effectAllowed 属性始终具有在 dragstart 事件之后具有的值,在 dragstart 事件中默认为“uninitialized”。

6.11.6 draggable 属性

Global_attributes/draggable

所有当前引擎都支持。

Firefox2+Safari5+Chrome4+
Opera12+Edge79+
Edge (遗留)12+Internet Explorer支持
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android?

所有 HTML 元素 都可以设置 draggable 内容属性。 draggable 属性是一个 枚举属性,具有以下关键字和状态

关键字状态简要描述
true true 元素可拖动。
false false 元素不可拖动。

属性的 缺失值默认值无效值默认值 均为 auto 状态。auto 状态使用用户代理的默认行为。

具有 draggable 属性的元素也应该具有一个 title 属性,该属性以非视觉交互的目的命名元素。

element.draggable [ = value ]

如果元素可拖动,则返回 true;否则,返回 false。

可以设置,以覆盖默认值并设置 draggable 内容属性。