7

我正在尝试跟踪整个屏幕的 dragenter/leave,到目前为止,它在 Chrome/Safari 中运行良好,由https://stackoverflow.com/a/10310815/698289中的 draghover 插件提供,如下所示:

$.fn.draghover = function(options) {
    return this.each(function() {

        var collection = $(),
            self = $(this);

        self.on('dragenter', function(e) {
            if (collection.size() === 0) {
                self.trigger('draghoverstart');
            }
            collection = collection.add(e.target);
        });

        self.on('dragleave drop', function(e) {
            // timeout is needed because Firefox 3.6 fires the dragleave event on
            // the previous element before firing dragenter on the next one
            setTimeout( function() {
                collection = collection.not(e.target);
                if (collection.size() === 0) {
                    self.trigger('draghoverend');
                }
            }, 1);
        });
    });
};

function setText(text) {
    $('p.target').text(text);
}

$(document).ready(function() {
    $(window).draghover().on({
        'draghoverstart': function() {
            setText('enter');
        },
        'draghoverend': function() {
            setText('leave');
        }
    });
});

但是,当我拖动文本项时,Firefox 仍然给我带来问题,这里有一个小提琴来演示:http: //jsfiddle.net/tusRy/6/

这是 Firefox 的错误还是可以用 JS 来驯服?或者是否有更强大的方法来执行所有这些?

谢谢!

更新:将小提琴更新为http://jsfiddle.net/tusRy/6/以减少混乱。解释小提琴的预期行为:

  • 将文件拖到窗口中,p.target 应该是黄色的“ENTER”。
  • 将文件拖出窗口,p.target 应该是红色的“LEAVE”。
  • 在窗口中放置一个文件,p.target 应该是红色的“LEAVE”。

在 Firefox 中,当您将文件拖到文本上时会触发 LEAVE 事件。

4

4 回答 4

9

从 22.0 版开始,Firefox 仍在执行此操作。当您拖动文本节点时,它会触发两种事件:一种是事件目标dragenterdragleave相关目标都是文本节点的父元素,另一种是目标是父元素,而相关目标是实际的文本节点(甚至不是正确的 DOM 元素)。

dragenter解决方法只是检查您的和处理程序中的这两种事件dragleave并忽略它们:

try {
    if(event.relatedTarget.nodeType == 3) return;
} catch(err) {}
if(event.target === event.relatedTarget) return;

我使用 try/catch 块来检查 nodeType,因为偶尔会从文档外部(例如在其他 iframe 中)触发事件(莫名其妙地),并且尝试访问它们的 nodeType 会引发权限错误。

这是实现:http: //jsfiddle.net/9A7te/

于 2013-07-17T05:59:09.530 回答
2

1) 你的 dropzone 应该只有一个子元素,它可能有你需要的一切。就像是

<div id="#dropzone">
    <div><!--Your contents here--></div>
</div>

2)使用这个CSS:

#dropzone * { pointer-events: none; }

您可能需要包括:beforeand:after因为*不适用于它们。

这应该足以让 drop 在 Firefox 和 Chrome 中工作。在您的示例中,添加以下内容就足够了:

body * { pointer-events: none; }

在 CSS 的末尾。我已经在这里完成了:

其他示例:

于 2013-09-01T00:36:33.967 回答
1

I came up with kind of a solution, yet to test on other browsers other than Chrome and FF but working so far. This is how the setTimeout looks now:

setTimeout( function() {
    var isChild = false;

    // in order to get permission errors, use the try-catch
    // to check if the relatedTarget is a child of the body
    try {
        isChild = $('body').find(e.relatedTarget).length ? true : isChild;
    }
    catch(err){} // do nothing

    collection = collection.not(e.target);
    if (collection.size() === 0 && !isChild) {
        self.trigger('draghoverend');
    }
}, 1);

The entire code here - http://jsfiddle.net/tusRy/13/.

The idea is to check if the related tag is a child of the body, in which case we are still in the Browsers and the draghoverend event should be not triggered. As this can throw errors when moving out of the windows, I used a try method to avoid it.

Well, perhaps somebody with more skills on JS could improve this :)

于 2013-03-31T18:05:00.587 回答
1

我在这个 SO question 的非选定答案中找到了答案,询问关于在子元素上的 dragleave 触发。我有一个<div>有很多子元素的。只要页面上有 a ,半透明的覆盖<span>就会在 上可见。正如你所发现的,'dragover' 不像. 每当您将鼠标悬停在子元素上时都会触发。<div>dragentermouseoverdragleave

解决方案? Dragoutdragover工作更像mouseover. 很短。

于 2013-12-15T15:48:19.770 回答