HTML5 DnD dataTransfer setData 或 getData 不能在除 Firefox 之外的所有浏览器中工作
考虑一下这个JSFiddle.它在 Firefox (14.0.1) 中运行良好,但在 Windows (7) 和 OS X (10.8) 上的 Chrome (21.0.1180.75)、Safari (?) 和 Opera(12.01?) 中失败.据我所知,问题在于 dataTransfer
对象上的 setData()
或 getData()
方法.这是来自 JSFiddle 的相关代码.
Consider this JSFiddle. It works fine in Firefox (14.0.1), but fails in Chrome (21.0.1180.75), Safari (?) and Opera(12.01?) on both Windows (7) and OS X (10.8). As far as I can tell the issue is with either the setData()
or getData()
methods on the dataTransfer
object. Here's the relevant code from the JSFiddle.
var dragStartHandler = function (e) {
e.originalEvent.dataTransfer.effectAllowed = "move";
e.originalEvent.dataTransfer.setData("text/plain", this.id);
};
var dragEnterHandler = function (e) {
// dataTransferValue is a global variable declared higher up.
// No, I don't want to hear about why global variables are evil,
// that's not my issue.
dataTransferValue = e.originalEvent.dataTransfer.getData("text/plain");
console.log(dataTransferValue);
};
据我所知,这应该可以正常工作,如果您在拖动项目时查看控制台,您会看到写出的 id,这意味着它可以很好地找到元素并获取它的 id 属性.问题是,是不设置数据还是不获取数据?
As far as I can tell this should work perfectly fine and if you look at the console while dragging an item you will see the id written out, which means that it's finding the element just fine and grabbing it's id attribute. The question is, is it just not setting the data or not getting the data?
我非常感谢您的建议,因为经过一周的努力,经过 3 次尝试和大约 200 多个版本,我开始失去理智.我所知道的是它曾经在 60 版左右可以工作,并且特定的代码根本没有改变......
I'd appreciate suggestions because after a week of working on this with three attempts and some 200+ versions, I'm starting to loose my mind. All I know is it used to work back in version 60 or so and that specific code hasn't changed at all...
实际上,6X 和 124 之间的主要区别之一是我将事件绑定从 这已被揭穿.事件绑定方法对问题没有影响.live()
更改为 on()
.我不认为这是问题所在,但在处理此问题时,我发现 Chrome 在 DnD 方面出现了几次失败.
Actually, one of the major differences between 6X and 124 is that I changed the event binding from This has been debunked. The event binding method has no effect on the issue.live()
to on()
. I don't think that's the issue, but I've come to see a couple failures from Chrome when it comes to DnD while working on this.
更新
我创建了一个新的 JSFiddle,它完全去除了所有内容,只留下了事件绑定和处理程序.我使用 jQuery 1.7.2 和 1.8 对它进行了测试,同时使用了 on()
和 live()
.问题仍然存在,所以我降低了一个级别并删除了所有框架并使用纯 JavaScript.问题仍然仍然存在,因此根据我的测试,不是我的代码失败了.相反,Chrome、Safari 和 Opera 似乎都在实施不符合规范的 setData()
或 getData()
,或者只是由于某种原因而失败.如果我错了,请纠正我.
I've created a new JSFiddle that strips out absolutely everything and just leaves the event binding and handlers. I tested it with jQuery 1.7.2 and 1.8 with both on()
and live()
. The issue persisted so I dropped down a level and removed all frameworks and used pure JavaScript. The issue still persisted, so based on my testing it's not my code that's failing. Instead it appears that Chrome, Safari and Opera are all implementing either setData()
or getData()
off spec or just failing for some reason or another. Please correct me if I'm wrong.
无论如何,如果您查看新的 JSFiddle,您应该能够复制该问题,只需在您拖动指定接受放置的元素时查看控制台.我已经用 Chromium 开了一张票.最后我可能仍然做错了什么,但我现在根本不知道如何做 DnD.新的 JSFiddle 被尽可能地精简了......
Anyway, if you take a look at the new JSFiddle you should be able to replicate the issue, just look at the console when you're dragging over an element designated to accept a drop. I've gone ahead and opened a ticket with Chromium. In the end I may still be doing something wrong, but I simply don't know how else to do DnD at this point. The new JSFiddle is as stripped down as it can get...
推荐答案
好的,经过一番挖掘,我发现问题实际上不在于 Chrome、Safari 和 Opera.泄露的是 Firefox 支持它,我不能说其他浏览器都失败了,因为我通常会接受 IE.
Ok, so after a bit more digging around, I found that the problem actually isn't with Chrome, Safari, and Opera. What gave it away was that Firefox was supporting it and I just couldn't say the other browsers are failing, since that's something I'd normally accept for IE.
问题的真正原因是 DnD 规范本身.根据 drag
、dragenter
、dragleave
、dragover
和 dragend
的规范事件拖动数据存储模式是保护模式.你问什么是保护模式?它是:
The real cause of the issue is the DnD specification itself. According to the spec for the drag
, dragenter
, dragleave
, dragover
and dragend
events the drag data store mode is protected mode. What is protected mode you ask? It is:
对于所有其他事件.拖动数据存储中的格式和种类可以枚举表示拖动数据的项目列表,但数据本身不可用,无法添加新数据.
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.
这意味着,您无权访问您设置的数据,即使在只读模式下也不行!您自己去 f@&#.".真的吗?想出这个的天才是谁?
That translates to, "you have no access to the data that you set, not even in read only mode! Go f@&# yourself.". Really? Who'se the genius that came up with this?
现在,要绕过这个限制,您几乎没有选择,我只会概述我想出的两个.您的第一个是使用邪恶的全局变量并污染全局命名空间.您的第二个选择是使用 HTML5 localStorage API 来执行与 DnD API 应该提供的完全相同的功能!
Now, to get around that limitation you have few choices, and I'm only going to outline two that I've come up with. Your first one is to use an evil global variable and pollute the global namespace. Your second choice is to use the HTML5 localStorage API to perform the EXACT same functionality that the DnD API should have provided to begin with!
如果你沿着这条路线走,我有,你现在实现两个 HTML5 API 不是因为你想要,而是因为你不得不.现在我开始欣赏 PPK 关于灾难的咆哮 HTML5 DnD API 是.
If you go down this route, which I have, you're now implementing two HTML5 APIs not because you want to, but because you have to. Now I'm starting to appreciate PPK's rant about the disaster that the HTML5 DnD API is.
最重要的是,需要更改规范以允许访问存储的数据,即使它仅处于只读模式.在我的情况下,使用这个 JSFiddle,我实际上是在使用 dragenter
作为一种查看方式在放置区前面并确认我是否应该允许放置.
The bottom line is this, the spec needs to be changed to allow for access to the stored data even if it's only in read only mode. In my case, with this JSFiddle, I'm actually using the dragenter
as a way to look ahead at the drop zone and verify that I should allow a drop to occur or not.
在这种情况下,Mozilla 显然选择不完全遵守规范,这就是我的 JSFiddle 在其中运行良好的原因.碰巧这是我完全支持不支持完整规范的一次.
In this case Mozilla apparently opted out of full compliance with the spec which is why my JSFiddle was working just fine in it. It just so happens that this is the one time I fully support not supporting the full specification.
相关文章