Javascript – HTML5 drag & drop behaviour

drag and drophtmljavascriptjquery

I'm making extensive use of the HTML5 native drag & drop, and it's almost entirely behaving itself, with one small exception.

I'm trying to highlight my dropzones when anything is dragged over the page. I originally tried to accomplish this by putting jQuery listeners on the document body, like this:

$("body").live('dragover',function(event){lightdz(event)});
$("body").live('dragexit dragleave drop',function(event){dimdz(event)});

with lightdz() and dimdz() changing the background-color style property of all dropzones on the page to make them stand out. This didn't work. Whenever a dragged object entered a child element on the page (like a div container), the listener would flag this up as a dragleave event and dim the dropzones.

I got around this by applying the listener to all visible elements on the page, instead of just the body. There was occasionally a slight visible flickering on the dropzones when it crossed the boundary between one element and another, but it looked fine.

Anyway, now I've changed lightdz() and dimdz() so that they apply a quick jQuery fadeTo() animation to all non-dropzones. This looks awesome when it works, and makes it very apparent to the user what they can and can't drop things on. The trouble is that when it passes between element boundaries, it applies the fade animation. This is a lot more apparent than the occasional flicker of background-color, especially since if the object is dragged over multiple boundaries very quickly, it will queue the animations and have the page fade in and out repeatedly.

Even if I don't bother with the fadeTo() animation, and just change the opacity, it's a lot more visible than the background-color flicker, because the entire page changes rather than just the dropzone elements.

Is there any way to reference the entire page as a single element for purposes of dragover and dragleave events? Failing that, is there any way to detect a drop that takes place outside of the browser window? If I skip the dragleave event, it looks fine, but if any object is dragged over the browser window and then dropped outside it, the whole page stays faded.

Best Answer

I'm genuinely embarrassed by how easy this one was.

$("*:visible").live('dragenter dragover',function(event){lightdz(event)});

$("#page").live('dragleave dragexit',function(event)
{
    if(event.pageX == "0")
       dimdz(event);
});

$("*:visible").live('drop',function(event){dimdz(event)});

#page is a page-wide container. If the dragleave event takes the dragged object outside of the browser window, event.pageX will have a value of 0. If it happens anywhere else, it'll have a non-zero value.