javascript拖放与部分preventDefault

时间:2011-05-17 22:37:46

标签: javascript drag-and-drop gmail

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;
});

1 个答案:

答案 0 :(得分:3)

我认为他们在dragover上设置dataTransfer.effectAllowed,具体取决于dataTransfer.types属性。

编辑:我第一次出错了,这里是类型的实际值(至少在Chrome中):
  - 拖动文字["text/html","text","text/plain"]
  - 拖动文件["Files"]

这是一个简短的jsFiddle example来玩。

您可以在w3cmdc上查看有关拖放的更多信息。

编辑:我设法在Chrome和FF上实现了确切的行为(see here

相关问题