我遇到的问题是,一个元素的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中都能运行。
下面是另一种基于事件时间的方法。
从子元素分派的dragenter事件可以被父元素捕获,并且它总是发生在dragleave之前。这两个事件之间的时间间隔非常短,比任何可能的人类鼠标操作都要短。所以,这个想法是记住dragenter发生的时间,过滤dragleave事件发生“不是太快”之后…
这个简短的例子适用于Chrome和Firefox:
var node = document.getElementById('someNodeId'),
on = function(elem, evt, fn) { elem.addEventListener(evt, fn, false) },
time = 0;
on(node, 'dragenter', function(e) {
e.preventDefault();
time = (new Date).getTime();
// Drag start
})
on(node, 'dragleave', function(e) {
e.preventDefault();
if ((new Date).getTime() - time > 5) {
// Drag end
}
})
我也有同样的问题,并试图使用pk7s的解决方案。它工作,但它可以做得更好一点,没有任何额外的dom元素。
基本上想法是一样的-在可掉落的区域上添加一个额外的不可见的覆盖。让我们在没有任何额外dom元素的情况下这样做。下面是CSS伪元素开始发挥作用的部分。
Javascript
var dragOver = function (e) {
e.preventDefault();
this.classList.add('overlay');
};
var dragLeave = function (e) {
this.classList.remove('overlay');
};
var dragDrop = function (e) {
this.classList.remove('overlay');
window.alert('Dropped');
};
var dropArea = document.getElementById('box');
dropArea.addEventListener('dragover', dragOver, false);
dropArea.addEventListener('dragleave', dragLeave, false);
dropArea.addEventListener('drop', dragDrop, false);
CSS
这个after规则将为可掉落区域创建一个完全覆盖的覆盖层。
#box.overlay:after {
content:'';
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1;
}
这里是完整的解决方案:http://jsfiddle.net/F6GDq/8/
我希望它能帮助有同样问题的人。
在花了这么多小时后,我得到的建议完全按照预期工作。我只想在文件被拖拽时提供提示,而文档拖拽,拖拽会在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
});