Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I detect a HTML5 drag event entering and leaving the window, like Gmail does?

Tags:

I'd like to be able to highlight the drop area as soon as the cursor carrying a file enters the browser window, exactly the way Gmail does it. But I can't make it work, and I feel like I'm just missing something really obvious.

I keep trying to do something like this:

this.body = $('body').get(0) this.body.addEventListener("dragenter", this.dragenter, true) this.body.addEventListener("dragleave", this.dragleave, true)` 

But that fires the events whenever the cursor moves over and out of elements other than BODY, which makes sense, but absolutely doesn't work. I could place an element on top of everything, covering the entire window and detect on that, but that'd be a horrible way to go about it.

What am I missing?

like image 410
Heilemann Avatar asked Jun 29 '10 21:06

Heilemann


People also ask

Does html5 support drag and drop?

Now HTML 5 came up with a Drag and Drop (DnD) API that brings native DnD support to the browser making it much easier to code up. HTML 5 DnD is supported by all the major browsers like Chrome, Firefox 3.5 and Safari 4 etc.


1 Answers

I solved it with a timeout (not squeaky-clean, but works):

var dropTarget = $('.dropTarget'),     html = $('html'),     showDrag = false,     timeout = -1;  html.bind('dragenter', function () {     dropTarget.addClass('dragging');     showDrag = true;  }); html.bind('dragover', function(){     showDrag = true;  }); html.bind('dragleave', function (e) {     showDrag = false;      clearTimeout( timeout );     timeout = setTimeout( function(){         if( !showDrag ){ dropTarget.removeClass('dragging'); }     }, 200 ); }); 

My example uses jQuery, but it's not necessary. Here's a summary of what's going on:

  • Set a flag (showDrag) to true on dragenter and dragover of the html (or body) element.
  • On dragleave set the flag to false. Then set a brief timeout to check if the flag is still false.
  • Ideally, keep track of the timeout and clear it before setting the next one.

This way, each dragleave event gives the DOM enough time for a new dragover event to reset the flag. The real, final dragleave that we care about will see that the flag is still false.

like image 154
Tyler Avatar answered Oct 06 '22 23:10

Tyler