Javascript – Firefox firing dragleave when dragging over text

drag and dropfirefoxjavascript

I'm attempting to track a dragenter/leave for the entire screen, which is so far working fine in Chrome/Safari, courtesy of the draghover plugin from https://stackoverflow.com/a/10310815/698289 as in:

$.fn.draghover = function(options) {
    return this.each(function() {

        var collection = $(),
            self = $(this);

        self.on('dragenter', function(e) {
            if (collection.size() === 0) {
                self.trigger('draghoverstart');
            }
            collection = collection.add(e.target);
        });

        self.on('dragleave drop', function(e) {
            // timeout is needed because Firefox 3.6 fires the dragleave event on
            // the previous element before firing dragenter on the next one
            setTimeout( function() {
                collection = collection.not(e.target);
                if (collection.size() === 0) {
                    self.trigger('draghoverend');
                }
            }, 1);
        });
    });
};

function setText(text) {
    $('p.target').text(text);
}

$(document).ready(function() {
    $(window).draghover().on({
        'draghoverstart': function() {
            setText('enter');
        },
        'draghoverend': function() {
            setText('leave');
        }
    });
});

However Firefox is still giving me problems when I drag over text items, here's a fiddle to demonstrate: http://jsfiddle.net/tusRy/6/

Is this a Firefox bug or can this be tamed with JS? Or is there a more robust method for performing all of this?

Thanks!

UPDATE: Updated fiddle to http://jsfiddle.net/tusRy/6/ to reduce clutter a bit. To explain the expected behavior of the fiddle:

  • Drag a file into the window and p.target should be "ENTER" colored yellow.
  • Drag a file out of the window and p.target should be "LEAVE" colored red.
  • Drop a file in the window and p.target should be "LEAVE" colored red.

In firefox, the LEAVE event is triggered when you drag the file over text.

Best Answer

As of version 22.0 Firefox is still doing this. When you drag over a text node it fires two kinds of dragenter and dragleave events: one where the event target and relatedTarget are BOTH the parent element of the text node, and another where the target is the parent element and the relatedTarget is the actual text node (not even a proper DOM element).

The workaround is just to check for those two kinds of events in your dragenter and dragleave handlers and ignore them:

try {
    if(event.relatedTarget.nodeType == 3) return;
} catch(err) {}
if(event.target === event.relatedTarget) return;

I use a try/catch block to check the nodeType because occasionally events fire (inexplicably) from outside the document (eg. in other iframes) and trying to access their nodeType throws a permissions error.

Here's the implementation: http://jsfiddle.net/9A7te/