拖动文本时,Firefox会触发dragleave

我试图追踪整个屏幕的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事件。


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

    解决方法是检查dragenterdragleave处理程序中的这两种事件,并忽略它们:

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

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

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


    我提出了一种解决方案,但在Chrome和FF以外的其他浏览器上进行测试,但目前仍在运行。 这就是setTimeout现在的样子:

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

    整个代码在这里 - http://jsfiddle.net/tusRy/13/。

    这个想法是检查相关标签是否是身体的一个孩子,在这种情况下,我们仍然在浏览器中,并且不应触发draghoverend事件。 由于这会在移出窗口时抛出错误,我使用了一种尝试方法来避免它。

    那么,也许有更多JS技能的人可以改善这一点:)


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

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

    2)使用这个CSS:

    #dropzone * { pointer-events: none; }
    

    您可能需要在* :before:after包含:before *因为不适用于它们。

    这应该足以让Firefox和Chrome的下载工作。 在你的例子中,它应该足以添加:

    body * { pointer-events: none; }
    

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

  • http://jsfiddle.net/djsbellini/eKttq/
  • 其他例子:

  • http://jsfiddle.net/djsbellini/6yZV6/1/
  • http://jsfiddle.net/djsbellini/yR8t8/
  • 链接地址: http://www.djcxy.com/p/64273.html

    上一篇: Firefox firing dragleave when dragging over text

    下一篇: Firefox won't play .WAV files using the HTML5 <audio> tag?