我遇到的问题是,一个元素的dragleave事件是在悬停该元素的子元素时触发的。同样,当再次悬停回父元素时,dragenter不会被触发。
我做了一个简化的小提琴:http://jsfiddle.net/pimvdb/HU6Mk/1/。
HTML:
<div id="drag" draggable="true">drag me</div>
<hr>
<div id="drop">
drop here
<p>child</p>
parent
</div>
使用以下JavaScript:
$('#drop').bind({
dragenter: function() {
$(this).addClass('red');
},
dragleave: function() {
$(this).removeClass('red');
}
});
$('#drag').bind({
dragstart: function(e) {
e.allowedEffect = "copy";
e.setData("text/plain", "test");
}
});
它应该做的是,当拖拽一些东西时,通过将drop div设置为红色来通知用户。这是可行的,但是如果你拖动到p子元素中,拖动键就会触发,div就不再是红色了。移动回下拉div也不会使它再次变红。有必要完全移出拖放div,并再次拖回它,使其变为红色。
是否有可能阻止dragleave在拖动到子元素时发射?
2017年更新:TL;DR,查找CSS指针事件:无;如@ h.d.所述。在现代浏览器和IE11中都能运行。
解决这个问题的“正确”方法是禁用拖放目标的子元素上的指针事件(如@ h.d.。的回答)。下面是我创建的演示这种技术的jsFiddle。不幸的是,这在IE11之前的ie版本中不起作用,因为它们不支持指针事件。
Luckily, I was able to come up with a workaround which does work in old versions of IE. Basically, it involves identifying and ignoring dragleave events which occur when dragging over child elements. Because the dragenter event is fired on child nodes before the dragleave event on the parent, separate event listeners can be added to each child node which add or remove an "ignore-drag-leave" class from the drop target. Then the drop target's dragleave event listener can simply ignore calls which occur when this class exists. Here's a jsFiddle demonstrating this workaround. It is tested and working in Chrome, Firefox, and IE8+.
更新:
我创建了一个jsFiddle,演示了一个使用特性检测的组合解决方案,其中如果支持指针事件,则使用指针事件(目前是Chrome、Firefox和IE11),如果指针事件支持不可用,则浏览器退回到向子节点添加事件(IE8-10)。
这里是最简单的跨浏览器解决方案(认真地说):
Jsfiddle <——尝试将一些文件拖到框中
你可以这样做:
var dropZone= document.getElementById('box');
var dropMask = document.getElementById('drop-mask');
dropZone.addEventListener('dragover', drag_over, false);
dropMask.addEventListener('dragleave', drag_leave, false);
dropMask.addEventListener('drop', drag_drop, false);
简单地说,你在拖拽区域内创建了一个“蒙版”,宽度和高度是继承的,位置是绝对的,这将显示拖拽开始的时间。
因此,在显示该蒙版之后,您可以通过附加其他拖放事件来实现这一技巧。
离开或掉落后,你只需将面具再次隐藏起来。
简单,无并发症。
(奥林匹克广播服务公司。: Greg Pettit的建议——你必须确保蒙版悬浮在整个盒子上,包括边框)
我找到了一个简单的解决方法,所以分享吧。这对我来说很有效。
试试吧。
你实际上可以通过dragenter事件来实现这一点,你甚至不需要注册一个dragleave。你所需要的就是在你的掉落区周围有一个不掉落的区域,就是这样。
你也可以有嵌套的dropzone,这是完美的。检查这个以及嵌套dropzones。
$('.dropzone').on("dragenter", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).addClass("over");
$(".over").not(this).removeClass("over"); // in case of multiple dropzones
});
$('.dropzone-leave').on("dragenter", function(e) {
e.preventDefault();
e.stopPropagation();
$(".over").removeClass("over");
});
// UPDATE
// As mar10 pointed out, the "Esc" key needs to be managed,
// the easiest approach is to detect the key and clean things up.
$(document).on('keyup', function(e){
if (e.key === "Escape") {
$(".over").removeClass("over");
}
});