HTML5 Drag & Drop Child Element

October 16, 2013

HTML5 Drag & Drop allows you to make some interesting stuff. Using Javascript you can bind to a number of events dragenter dragover dragleave drop. However, there can be a problem with the events that you bind to where the dragleave event fires when you don’t except it eg. entering the child element of a parent element. For CoffeeScript versions of the scripts see the JSFiddle’s.

Imagine the following page:

<div class="dropbox">drag some files here but not <strong>here</strong></div>

And the following code:

$(function() {
  $(".dropbox").on("dragenter", function(event) {
    $(this).addClass("active");
  });
  $(".dropbox").on("dragleave", function(event) {
    $(this).removeClass("active");
  });
});

JSFiddle of the above: http://jsfiddle.net/mmriis/CzESd/.

The problem here is that when you drag the file over the child <strong> element the dragleave event will fire. This can be a bit annoying to work around and there are a lot of “hacky” workarounds.

An easy solution is to just bind to the dragenter event on body and work from there like so:

$(function() {
  var changeDropTarget, currentDropTarget;
  currentDropTarget = null;
  changeDropTarget = function(newTarget) {
    currentDropTarget && currentDropTarget.removeClass("active");
    newTarget = $(newTarget).hasClass('dropbox') ? $(newTarget) : 
                                      $(newTarget).parents('.dropbox');
    currentDropTarget = newTarget;
    newTarget.addClass("active");
    if (newTarget.length === 0) {
      currentDropTarget = $("body");
    }
  };
  $("body").on("dragenter", function(event) {
    event.preventDefault();
    changeDropTarget(event.target);
  });
  $("body").on("drop", function(event) {
    event.preventDefault();
  });
  $("body").on("dragover", function(event) {
    event.preventDefault();
  });
  $("body").on("dragleave", function(event) {
    event.preventDefault();
  });
});

What we do here is we keep track of the current drop target and because dragenter will fire each time you drag over a new element we can easily manipulate the new and the old target.Using jQuery’s parents() method we can find the actual “dropbox”.

JSFiddle of the above: http://jsfiddle.net/mmriis/k8nAD/.

Share this post on Twitter
Morten Møller Riis

By Morten Møller Riis

I am a programmer, sysadmin, devops. I work for Gigahost in Copenhagen, Denmark. I am based in Odense, Denmark.

Twitter   ·   LinkedIn   ·   E-mail