2011-05-17 36 views
3

Gmail的处理在几个巧妙的方法其拖放和拖放文件附件上传:拖动文件到浏览器JavaScript的拖放与局部的preventDefault

1)使悬浮窗出现。光标显示反馈,指示您是否在dropzone中(在窗口中,如果在dropzone之外,则使用红色的crossthrough圈)。如果您在窗口内而外的悬浮窗的下降,下降被拦截,使得浏览器的默认行为被阻止(通常导航离开显示已拖动文件)。

尝试这种最明显的方法是设置的dragover处理器在身上,使悬浮窗出现,的preventDefault,但什么光标变化?有没有办法使用dataTransfer.effectAllowed ='无'? 2)将文本从窗口的一部分拖动到另一部分不会触发拖放处理(即,不显示拖放区域) - 并且#1中提到的preventDefault不起作用。

如果我捕获在主体DragOver事件(从#1),则窗口内文本拖动被防止。他们如何同时完成这两项任务?看起来这比起初可能出现的更复杂。

UPDATE:

我学到了两个相关的事情,而试图彻底解决这个问题:

1)看来,IE浏览器甚至不会触发drop事件处理程序,如果dropEffect来=“无” ......所以我决定,如果e.dataTransfer.types存在,只把它设置为none(它确实在Chrome & FF,但不是在IE)。缺点是光标没有红色的交叉,但至少我可以拦截掉,以防止导航。确定它是否在IE中放置文件的最佳猜测是如果e.dataTransfer.getData('Text')== null。 (在我的情况下,我希望能够接收文件或文本,所以这是我如何分辨IE的差异。)

2)Gmail隐藏dropzone的方式并不明显当你离开浏览器时。如果您在页面上使用纯粹的dragleave事件,则即使您没有真正离开页面,拖入任何孩子也会触发dragleave处理程序。然后我注意到,有一个在Gmail中的延迟悬浮窗消失之前,所以我猜他们用一个定时器来隐藏悬浮窗(其大干快上类似的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; 
}); 

回答

3

我相信他们是在设定的dragover dataTransfer.effectAllowed,取决于dataTransfer.types属性。

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

下面是一个简短jsFiddle example到玩弄。

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

编辑:我设法落实Chrome和FF(see here

+0

我几乎没有看到最后的编辑......挺漂亮的确切行为!这完美地处理了我所问的问题。我现在正在查看两个相关的详细信息: (1)如何在不在页面时使dropzone消失(只需在文档的dragleave中进行操作会导致dropzone在输入时消失)。 (2)如何防止IE浏览器丢失文件,而不会破坏所有其他内容。 我怀疑你会更快,但是如果/当我解决这些问题时我会更新 – dlo 2011-05-18 16:38:00