Gmail以一些聪明的方式处理其拖放文件附件上传:
1)将文件拖到浏览器中会导致出现dropzone。光标显示反馈,指示您是否在dropzone中(在窗口中,如果在dropzone之外,则使用红色的直通圆圈)。如果你掉落在窗口内但在dropzone之外,则拦截掉落以防止浏览器的默认行为(通常导航以显示拖动的文件)。
尝试这种方法最明显的方法是在BODY上设置dragover处理程序以显示dropzone和preventDefault,但是光标更改呢?有没有办法使用dataTransfer.effectAllowed ='none'?
2)将文本从窗口的一部分拖动到另一部分不会触发拖放处理(即 - 不显示掉区) - 并且#1中提到的preventDefault没有启动。< / p>
如果我在BODY上捕获dragover事件(来自#1),则阻止窗口内文本拖动。他们如何同时完成这两个方面?看起来这比最初看起来要复杂得多。
更新:
我在尝试完全解决这个问题时学到了两个相关的事情:
1)如果dropEffect ='none',IE似乎甚至不会触发drop事件处理程序...所以如果存在e.dataTransfer.types,我决定只将它设置为none(在Chrome&amp; FF,但不是IE)。缺点是光标没有红色交叉,但至少我可以截取下降以防止navaway。确定它是否是IE中的文件丢弃的最佳猜测是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;
});
答案 0 :(得分:3)
我认为他们在dragover上设置dataTransfer.effectAllowed
,具体取决于dataTransfer.types
属性。
编辑:我第一次出错了,这里是类型的实际值(至少在Chrome中):
- 拖动文字["text/html","text","text/plain"]
- 拖动文件["Files"]
这是一个简短的jsFiddle example来玩。
编辑:我设法在Chrome和FF上实现了确切的行为(see here)