我正在尝试跟踪整个屏幕上的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/的小提示,以减少混乱。解释小提琴的预期行为:
在firefox中,当您将文件拖到文本上时会触发LEAVE事件。
答案 0 :(得分:8)
从版本22.0开始,Firefox仍在执行此操作。当您拖动文本节点时,它会触发两种dragenter
和dragleave
事件:一个事件目标和relatedTarget是文本节点的父元素,另一个目标是父节点element和relatedTarget是实际的文本节点(甚至不是正确的DOM元素)。
解决方法只是检查dragenter
和dragleave
处理程序中的这两种事件并忽略它们:
try {
if(event.relatedTarget.nodeType == 3) return;
} catch(err) {}
if(event.target === event.relatedTarget) return;
我使用try / catch块来检查nodeType,因为有时事件从文档外部(例如在其他iframe中)触发(莫名其妙)并尝试访问其nodeType会引发权限错误。
答案 1 :(得分:1)
我提出了一种解决方案,但是要测试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
事件。因为这可能会在移出窗口时抛出错误,所以我使用了try方法来避免它。
好吧,也许有一些掌握JS技能的人可以改善这一点:)
答案 2 :(得分:1)
1)你的dropzone应该只有一个子元素,这可能包含你需要的其他所有元素。像
这样的东西<div id="#dropzone">
<div><!--Your contents here--></div>
</div>
2)使用这个CSS:
#dropzone * { pointer-events: none; }
您可能需要加入:before
和:after
,因为*
不适用于他们。
这应该足以让drop在Firefox和Chrome中运行。在您的示例中,添加:
应该足够了body * { pointer-events: none; }
CSS的结尾。我在这里做到了:
其他例子:
答案 3 :(得分:1)
我在这个问题的未选择答案中找到答案,询问dragleave firing on child elements。我有一个<div>
,它有很多子元素。只要页面上有<span>
,就会在<div>
上看到半透明覆盖dragenter
。正如您所发现的,'dragover'与mouseover
不同。只要将鼠标悬停在子元素上,它就会触发dragleave
。
解决方案? Dragout它使dragover
的工作更像mouseover
。很短。