50

I'm trying to implement drag and dropping of files from the desktop the browser window. I have used jQuery to attach three events to the HTML element as in the code below:

$("html").on("dragover", function() {
    $(this).addClass('dragging');
});

$("html").on("dragleave", function() {
    $(this).removeClass('dragging');
});

$("html").on("drop", function(event) {
    event.preventDefault();  
    event.stopPropagation();
    alert("Dropped!");
});

The 'dragover' and 'dragleave' events work fine, displaying an inset border around the entire page when I drag a file over an removing it if I drag the file out again.

However, the 'drop' event doesn't seem to fire at all, the dropped file simply opens in the browser window.

Does anyone have any idea why this event is not firing?

Btw, I am testing this in the latest version of Chrome and using jQuery 1.10.2.

Kara
  • 6,115
  • 16
  • 50
  • 57
TreacleWench
  • 503
  • 1
  • 4
  • 5
  • duplicate question: http://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome/36207613#36207613 – bob Mar 24 '16 at 18:42
  • potential answer: http://stackoverflow.com/questions/8414154/html5-drop-event-doesnt-work-unless-dragover-is-handled – bob Mar 24 '16 at 18:42

3 Answers3

124

You need to cancel all events

$("html").on("dragover", function(event) {
    event.preventDefault();  
    event.stopPropagation();
    $(this).addClass('dragging');
});

$("html").on("dragleave", function(event) {
    event.preventDefault();  
    event.stopPropagation();
    $(this).removeClass('dragging');
});

$("html").on("drop", function(event) {
    event.preventDefault();  
    event.stopPropagation();
    alert("Dropped!");
});
Francisco Presencia
  • 8,732
  • 6
  • 46
  • 90
Christian Lund
  • 1,666
  • 1
  • 13
  • 6
  • That did it, thanks. Funny how that never actually occurred to me! I also had to remove the class on the 'drop' event as, when dropped, the 'dragleave' event won't get triggered. – TreacleWench Oct 07 '13 at 12:42
  • 23
    For anyone following; its the additional cancel of "dragover" that causes the drop to then fire. Canceling dragenter and dragleave isn't enough. As @Christian says you have to cancel them ALL. – Kong Dec 02 '13 at 21:58
  • 4
    Can you please add explanation on why do I need to remove/cancel the CSS – aroos Mar 01 '14 at 03:46
  • 2
    If you mean the "$(this).removeClass('dragging')" statement, this is simply the OPs way of styling the page when dragging occurs. It has nothing to do with the drag-and-drop operation. – Christian Lund Mar 01 '14 at 11:08
  • 5
    Since I ended here first with google, maybe have a look at [this](http://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) answer, and the referenced link to the [MDN](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets) with the explanation *why* u have to cancel the events! – Lux Jul 09 '14 at 14:02
  • @Kong: Thank you! This wasn't working for me at all until I read your comment. Now, finally, after hours of pain, it works! :) – kornfridge Oct 21 '14 at 08:12
  • 1
    Make sure you wait for the DOM to be loaded first. I didn't. Classic mistake. – Jaap Weijland Oct 22 '18 at 08:48
  • Adding to @Lux comment, here's a [link](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#specifying_drop_targets) to exact section that explains this. – Daniyal Nasir Jan 01 '23 at 09:30
26

In addition to Christian's solution this can be shortened to:

$('#my-dropzone')
    // crucial for the 'drop' event to fire
    .on('dragover', false) 

    .on('drop', function (e) {
        // do something
        return false;
    });
JimmyBlu
  • 648
  • 5
  • 20
0

You don't need to cancel any event. Just you can user event.preventDefault() for dragover and drop events:

$(document)
.on('dragover', '.target', function (event) {
    event.preventDefault()
    // Do anything you want to do in dragover
})
.on('drop', '.target', function (event) {
    event.preventDefault()
    // You will catch this event here
})
Raserad
  • 41
  • 4