首页 文章

javascript拖放与部分preventDefault

提问于
浏览
3

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 回答

  • 3

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

    编辑:我第一次错了,这是类型的实际值(至少在Chrome中):

    • 拖动文字 ["text/html","text","text/plain"]
    • 拖动文件 ["Files"]

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

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

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

相关问题