Gmail以一些聪明的方式处理其拖放文件附件上传:
1)将文件拖到浏览器中会导致出现dropzone . 光标显示反馈,指示您是否在dropzone中(在窗口中,如果在dropzone之外,则使用红色的直通圆圈) . 如果您放入窗口内但在dropzone之外,则会拦截放置,以防止浏览器的默认行为(通常导航以显示拖动的文件) .
尝试这种方法最明显的方法是在BODY上设置dragover处理程序以显示dropzone并阻止默认,但是光标更改呢?有没有办法使用dataTransfer.effectAllowed ='none'?
2)将文本从窗口的一部分拖动到另一部分不会触发拖放处理(即 - 不显示掉区) - 并且#1中提到的preventDefault没有启动 .
如果我在BODY上捕获dragover事件(来自#1),则阻止窗口内文本拖动 . 他们如何同时完成这两个方面?看起来这比最初看起来更复杂 .
更新:
我在尝试完全解决这个问题时学到了两个相关的东西:
1)似乎IE甚至不会触发drop事件处理程序如果dropEffect = 'none' ...所以我决定只在e.dataTransfer.types存在的情况下将其设置为none(它在Chrome&FF中有效,但在IE中不能) . 缺点是光标没有't have the red crossthrough, but at least I can intercept the drop to prevent a navaway. Your best guess for determining whether it was a file drop in IE is if e.dataTransfer.getData(' Text')== null . (在我的情况下,我希望能够接收文件或文本的丢弃,所以这就是我在IE中区分的方法 . )
2)当您离开浏览器时,Gmail隐藏dropzone的方式并不明显 . 如果您在页面上使用纯dragleave事件,则拖动到任何子项将触发dragleave处理程序,即使您没有真正离开页面 . 然后我注意到在dropzone消失之前Gmail中存在延迟,所以我猜他们会使用计时器来隐藏dropzone(它会像dragover一样重置) . 但我想出了一个似乎有效的替代解决方案:
function areXYInside(e){
var w=e.target.offsetWidth;
var h=e.target.offsetHeight;
var x=e.offsetX;
var y=e.offsetY;
return !(x<0 || x>=w || y<0 || y>=h);
}
然后:
$("#page").bind('dragleave', function(e){
if(this!=e.target) return false;
if(!areXYInside(e)){
hideBox();
}
return false;
});
1 回答
我相信他们在dragover上设置
dataTransfer.effectAllowed
,具体取决于dataTransfer.types属性 .编辑:我第一次错了,这是类型的实际值(至少在Chrome中):
["text/html","text","text/plain"]
["Files"]
这是一个简短的jsFiddle example来玩 .
您可以在w3c或mdc查看有关拖放的更多信息 .
编辑:我设法在Chrome和FF上实现了确切的行为(see here)