如何像 Gmail 一样检测进入和离开窗口的 HTML5 拖动事件?
我希望能够在带有文件的光标进入浏览器窗口后立即突出显示放置区域,这与 Gmail 的做法完全一样.但我无法让它发挥作用,我觉得我只是错过了一些非常明显的东西.
I'd like to be able to highlight the drop area as soon as the cursor carrying a file enters the browser window, exactly the way Gmail does it. But I can't make it work, and I feel like I'm just missing something really obvious.
我一直在尝试做这样的事情:
I keep trying to do something like this:
this.body = $('body').get(0)
this.body.addEventListener("dragenter", this.dragenter, true)
this.body.addEventListener("dragleave", this.dragleave, true)`
但是,只要光标移出和移出 BODY 以外的元素,就会触发事件,这是有道理的,但绝对行不通.我可以在所有东西上放置一个元素,覆盖整个窗口并对其进行检测,但这将是一种可怕的方式.
But that fires the events whenever the cursor moves over and out of elements other than BODY, which makes sense, but absolutely doesn't work. I could place an element on top of everything, covering the entire window and detect on that, but that'd be a horrible way to go about it.
我错过了什么?
推荐答案
我用超时解决了它(不是很干净,但可以):
I solved it with a timeout (not squeaky-clean, but works):
var dropTarget = $('.dropTarget'),
html = $('html'),
showDrag = false,
timeout = -1;
html.bind('dragenter', function () {
dropTarget.addClass('dragging');
showDrag = true;
});
html.bind('dragover', function(){
showDrag = true;
});
html.bind('dragleave', function (e) {
showDrag = false;
clearTimeout( timeout );
timeout = setTimeout( function(){
if( !showDrag ){ dropTarget.removeClass('dragging'); }
}, 200 );
});
我的示例使用 jQuery,但这不是必需的.以下是正在发生的事情的摘要:
My example uses jQuery, but it's not necessary. Here's a summary of what's going on:
- 在
dragenter
和 html(或正文)的dragover
上将标志 (showDrag
) 设置为true
元素. - 在
dragleave
上将标志设置为false
.然后设置一个短暂的超时来检查标志是否仍然为假. - 理想情况下,在设置下一个超时之前跟踪并清除它.
- Set a flag (
showDrag
) totrue
ondragenter
anddragover
of the html (or body) element. - On
dragleave
set the flag tofalse
. Then set a brief timeout to check if the flag is still false. - Ideally, keep track of the timeout and clear it before setting the next one.
这样,每个 dragleave
事件都会给 DOM 足够的时间让新的 dragover
事件重置标志.我们关心的真正的,最终的 dragleave
会看到标志仍然是假的.
This way, each dragleave
event gives the DOM enough time for a new dragover
event to reset the flag. The real, final dragleave
that we care about will see that the flag is still false.
相关文章