23
votes

I have a <div> drop target that I have attached 'drop' and 'dragover' events to. The <div> contains an image inside an anchor tag (simplistically: <div><a><img /></a></div>). The child elements of the target seem to block the 'drop' or 'dragover' events from being triggered. Only when the dragged element is over the target, but NOT over its child elements, are both events triggered as expected.

The behavior I would like to achieve is that the 'dragover' and 'drop' events are triggered anywhere over the target <div>, regardless of the existence of child elements.

5
what happens if you attach the events to the <a> or <img>? - derekcohen
It works as expected in that case, but I need to be able to attach the events to the whole container. I don't see any reason why this shouldn't work. - RMD Developer
See my workaround for this problem here: stackoverflow.com/a/15216514/865467 - Simon Robb

5 Answers

7
votes

You can disable the pointer-events in CSS for all children.

.targetDiv * {
    pointer-events: none;
}
2
votes

Somewhat oblique to the original question, but I googled my way here wondering the following:

How do I make an <img />, which is the child of a <div draggable="true">...</div> container, behave correctly as a handle with which to move that container?

Simple: <img src="jake.jpg" draggable="false" />

2
votes

Bastiaan's answer is technically correct though it was specific to the OP. This is a much cleaner and universal approach:

[draggable] * {pointer-events: none;}
1
votes

The drag & drop spec is seriously flawed and quite hard to work with.

By tracking child elements it's possible to achieve the expected behaviour (of child-elements not interfering).

Below is a short example of how to do this (with jQuery):

jQuery.fn.dndhover = function(options) {
  return this.each(function() {
    var self = jQuery(this);
    var collection = jQuery();

    self.on('dragenter', function(event) {
      if (collection.size() === 0) {
        self.trigger('dndHoverStart');
      }

      collection = collection.add(event.target);
    });

    self.on('dragleave', function(event) {
      collection = collection.not(event.target);

      if (collection.size() === 0) {
        self.trigger('dndHoverEnd');
      }
    });
  });
};

jQuery('#my-dropzone').dndhover().on({
  'dndHoverStart': function(event) {
    jQuery('#my-dropzone').addClass('dnd-hover');

    event.stopPropagation();
    event.preventDefault();
    return false;
  },
  'dndHoverEnd': function(event) {
    jQuery('#my-dropzone').removeClass('dnd-hover');

    event.stopPropagation();
    event.preventDefault();
    return false;
  }
});

Credits: 'dragleave' of parent element fires when dragging over children elements

0
votes

Something else must be going on with your code. I mocked up a simple example here:

http://jsfiddle.net/M59j6/6/

and you can see that child elements don't interfere with the events.