【问题标题】:HTML5 native Drag 'n' Drop - Detect cancellationHTML5 原生拖放 - 检测取消
【发布时间】:2016-02-11 09:02:20
【问题描述】:

我需要在浏览器窗口之间实现拖放 HTML 元素。

当一个元素从窗口 A 拖放到窗口 B 时,它必须从窗口 A 中移除(并添加到窗口 B)。

当取消拖放时(发生在用户按下“esc”键时,或者有时当拖放功能似乎出现错误时),元素必须回到原来的位置。

目前我正在做的是保留一个“hasBeenDropped”标志,该标志在 Dragstart 中设置为 false,在 drop 中设置为 true。在 dragend 中,我检查了我的标志,如果它没有设置为 true,则意味着 drop 已在另一个窗口中触发,或者操作已被取消。我需要区分这两种情况(放入另一个窗口与取消),以便采取相应的行动(例如删除窗口或将其替换到原来的位置)。

TL;DR:我需要能够检测原生 HTML5 拖放操作何时被取消(例如,当用户按下“esc”键时)。

有什么办法吗?

【问题讨论】:

  • 运气好吗?我自己也遇到了这个。我有您保留用于跟踪成功丢弃的确切类型的内务标记,但我们的应用程序同样需要区分不同的取消模式。我试图仔细检查事件以寻找可以关闭的内容,但到目前为止,我只在 firefox 上遇到了运气。
  • 抱歉,目前好像没有办法。从那以后我换了工作,所以我不再做这个了,但我没有设法让它按我的意愿工作。 IIRC 我所做的是复制而不是移动(这样做,原始窗口不需要放置事件)。

标签: html drag-and-drop detection cancellation


【解决方案1】:

和你一样,我使用了一个标志来确定其他地方是否成功发生了下降,这或多或少意味着它没有被取消。但是,如 MDN 中所述,似乎有一种更合适的方法:

完成拖拽

一旦拖动完成,就会在源头触发一个 dragend 事件 拖动(接收到 dragstart 事件的同一元素)。这 如果拖动成功[1] 或取消,事件将触发。 但是,您可以使用 dropEffect 属性来确定放置什么 操作发生。

如果在拖动过程中 dropEffect 属性的值为 none,则拖动被取消。否则,效果指定哪个 进行了操作。来源可以在经过 移动操作以从旧位置删除拖动的项目。这 如果用户取消,mozUserCancelled 属性将设置为 true 拖动(通过按 Escape),如果拖动被取消,则返回 false 其他原因,例如无效的放置目标,或者是否成功。

mozilla 特有的属性显然是不可取的,但是 dropEffect 属性本身对于大多数用途来说应该足够了。我自己对其进行了测试(将磁贴拖入 iframe 中的放置区),它似乎按预期工作。

这直接取自当前 MDN 页面上的主题:

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#dragend

可能因为你换了工作对你没那么有用,但是关于这个主题的信息很难找到,所以希望下一个搜索的人会受益。

【讨论】:

  • 感谢您抽出宝贵时间回答,看来确实是要走的路。我赞成你的回答。
  • 谢谢,真的很有帮助。
  • 对于那些(像我一样)懒得关注链接的人:dropEffectDataTransfer 的属性,而不是事件的属性,即使用ev.dataTransfer(或使用jQuery 时使用ev.originalEvent.dataTransfer )。
【解决方案2】:

dragend 事件在拖动操作结束时触发(通过释放鼠标按钮或按下退出键)。 您可以检查事件属性“ctrlKey”。如果为真,则按下 Esc 按钮。如有必要,您还可以检查其他属性。 看看参考资料,例如这里:https://developer.mozilla.org/en-US/docs/Web/Events/dragend

最好的,亚历克斯

【讨论】:

  • 谢谢,但是使用 esc 键取消操作时 ctrlKey 为 false(至少对我来说,在 Firefox、Chrome 和 Safari 上),这是正常的。
  • 嗨,蒂姆,是的,没错。看来我搞混了,不好意思。因此,我将使用 drop 事件并查看是否可以通过使用 drop 事件的 target 或 view 属性来检测窗口。我希望您可以使用它们来获取要放置的元素或要放置的窗口。你已经看过了吗?
  • 好主意,我没有检查。但不幸的是它也不起作用,目标元素始终是拖动的 HTML 元素,视图始终是当前窗口(如果我从窗口 A 拖动到窗口 B,我在窗口 A 中拖动窗口 A 并在窗口 B窗口 B 下降。我需要在窗口 A 中拖动窗口 B)。
  • 好的,您能否提供一个在线示例或 jsfiddle 让我可以检查并详细说明问题?