问题
I'm having a bit of a problem with html5 drag and drop. I don't see an easy way out of it. Basically i have some "boxes" with some other html elements inside. The parent boxes are draggable and they can be dropped on each other.
I bind dragover event on the body to handle drag-drop on the entire page. Problem is, when you drag over the boxes - the event is sometimes triggered on child elements and the parent doesn't get this event at all.
Is there an easy way to prevent this from happening?
Basically i want the dragover event to fire as soon as the mouse is in the area of the target box. I know of a couple of ways of solving this, but they're really ugly and i was wondering if there maybe is something simple.
Thanks for your thoughts
Short version of what i'm doing in code:
document.addEventListener('dragenter', function(e) {
if (e.target.className == 'candrophere')
// cancel out "e" to allow drop
}, false);
But in my case the child elements are taking up almost the entire '.candrophere' box so the event is almost never fired on the correct target (especially when i move the mouse faster)
回答1:
The css pointer-events rule prevents mouse interaction events from firing on the elements it is applied to, but isn't currently supported by IE (http://caniuse.com/pointer-events).
A workaround I've used for this problem is to add something like
.is-drag-in-progress .child-elements
{
pointer-events:none;
}
to your CSS, and add the is-drag-in-progress class to the body element in your onDragStart handler (and remove it when the drag ends). This will prevent the child elements from interfering with drag events on the parent element.
回答2:
Basically my solution is as follows:
Since e.target and e.currentTarget cannot be matched to the parent box most of the time - all that's left to do is to manually check if the e.target is a child of the parent box. There are many ways to do that, but i'm using a custom function. Can't post it here, since it is based on my own framework and won't work without it anyway, but the pseudo-code is as follows:
// target is a framework object (much like jquery)
closestDroppableParent = function(target)
{
// i know that all children in those boxes will not be any deeper than this
var max_levels = 5;
while (target && max_levels > 0)
{
max_levels--;
// droppable boxes have data-droptype attribute set so only other boxes with the same attribute
// can be dropped on them. This check can be done any way you like. You can have a custom class
// for droppable objects, check for draggable attribute etc...
// .data() is a framework function that returns the value of the data-* attributes
if (target.data('droptype'))
return target;
// .parent() is a framework function to get parent node
target = target.parent();
}
return null;
}
// drag over event
dragOverEventHandler = function(e)
{
// convert the element to its closest droppable parent
// $() is much like jquery
var closest = closestDroppableParent($(e.target));
if (closest)
closest.addClass('draggedOver');
}
来源:https://stackoverflow.com/questions/12509602/html5-is-there-a-way-to-prevent-children-interfering-with-drag-events