我遇到的问题是,一个元素的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中都能运行。
我编写了一个名为drop -drop的拖放模块来修复这种奇怪的行为。如果你正在寻找一个好的低级拖放模块,你可以用作任何事情的基础(文件上传,应用程序内拖放,从或从外部源拖放),你应该检查这个模块:
https://github.com/fresheneesz/drip-drop
这是你在点滴中尝试做的事情:
$('#drop').each(function(node) {
dripDrop.drop(node, {
enter: function() {
$(node).addClass('red')
},
leave: function() {
$(node).removeClass('red')
}
})
})
$('#drag').each(function(node) {
dripDrop.drag(node, {
start: function(setData) {
setData("text", "test") // if you're gonna do text, just do 'text' so its compatible with IE's awful and restrictive API
return "copy"
},
leave: function() {
$(node).removeClass('red')
}
})
})
为了在没有库的情况下做到这一点,我在滴漏中使用了反制技术,尽管评分最高的答案错过了重要的步骤,这将导致除了第一个滴漏之外的所有东西都被打破。以下是正确的做法:
var counter = 0;
$('#drop').bind({
dragenter: function(ev) {
ev.preventDefault()
counter++
if(counter === 1) {
$(this).addClass('red')
}
},
dragleave: function() {
counter--
if (counter === 0) {
$(this).removeClass('red');
}
},
drop: function() {
counter = 0 // reset because a dragleave won't happen in this case
}
});
这里是最简单的跨浏览器解决方案(认真地说):
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的建议——你必须确保蒙版悬浮在整个盒子上,包括边框)
在花了这么多小时后,我得到的建议完全按照预期工作。我只想在文件被拖拽时提供提示,而文档拖拽,拖拽会在Chrome浏览器上引起痛苦的闪烁。
这就是我解决它的方法,也为用户提供了适当的提示。
$(document).on('dragstart dragenter dragover', function(event) {
// Only file drag-n-drops allowed, http://jsfiddle.net/guYWx/16/
if ($.inArray('Files', event.originalEvent.dataTransfer.types) > -1) {
// Needed to allow effectAllowed, dropEffect to take effect
event.stopPropagation();
// Needed to allow effectAllowed, dropEffect to take effect
event.preventDefault();
$('.dropzone').addClass('dropzone-hilight').show(); // Hilight the drop zone
dropZoneVisible= true;
// http://www.html5rocks.com/en/tutorials/dnd/basics/
// http://api.jquery.com/category/events/event-object/
event.originalEvent.dataTransfer.effectAllowed= 'none';
event.originalEvent.dataTransfer.dropEffect= 'none';
// .dropzone .message
if($(event.target).hasClass('dropzone') || $(event.target).hasClass('message')) {
event.originalEvent.dataTransfer.effectAllowed= 'copyMove';
event.originalEvent.dataTransfer.dropEffect= 'move';
}
}
}).on('drop dragleave dragend', function (event) {
dropZoneVisible= false;
clearTimeout(dropZoneTimer);
dropZoneTimer= setTimeout( function(){
if( !dropZoneVisible ) {
$('.dropzone').hide().removeClass('dropzone-hilight');
}
}, dropZoneHideDelay); // dropZoneHideDelay= 70, but anything above 50 is better
});