25

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.

Yi Jiang
  • 49,435
  • 16
  • 136
  • 136
RMD Developer
  • 336
  • 1
  • 4
  • 7

5 Answers5

9

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

.targetDiv * {
    pointer-events: none;
}
Bastiaan
  • 686
  • 1
  • 8
  • 20
2

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" />

chbrown
  • 11,865
  • 2
  • 52
  • 60
  • 3
    'A' for the idea, but this didn't work in Chrome. I've noticed the draggable attribute seems to be almost completely ignored. – mwilcox Jun 19 '13 at 13:53
2

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;}
John
  • 1
  • 13
  • 98
  • 177
1

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

Community
  • 1
  • 1
sandstrom
  • 14,554
  • 7
  • 65
  • 62
0

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.

dlo
  • 1,580
  • 15
  • 24
  • 1
    This is jQuery DnD, not HTML5. – mwilcox Jun 19 '13 at 13:48
  • 1
    Huh? I used jquery for shorter code, but dragover/dragleave/drop are standard HTML5 events. – dlo Jun 19 '13 at 16:39
  • You can see the same problem, dargleave is firing sometimes in your example when hovering between the parent and child elements – Borja Alvarez Nov 10 '16 at 08:29
  • 2
    listen here - if the question's tags refer to JavaScript, then please, for the love of all that is sane, don't answer in jQuery - and no jQuery is not JavaScript - yes it works with JavaScript but it's not the same thing so don't pretend that it is. .. have a nice day. –  Jul 07 '17 at 13:51