1

I am trying to use .bind() with 'dragenter', 'dragover', and 'drop' so I can drag a file from my desktop to my browser.

Please see attached jsfiddle. http://jsfiddle.net/v82An/23/

$(function(){
    function dragenter(e) {
        e.stopPropagation();
        e.preventDefault();
    }
    function dragover(e) {
        e.stopPropagation();
        e.preventDefault();
    }    
    function drop(e) {
        e.stopPropagation();
        e.preventDefault();        
        alert('hi')
    }

    $('#drop').bind('dragenter', dragenter, false);
    $('#drop').bind('dragover', dragover, false);
    $('#drop').bind('drop', drop, false);    
});

This fiddle attaches these events properly in 1.5, but in 1.6 they simply don't work.

Anyone know if I'm just doing it wrong?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
kidcapital
  • 5,064
  • 9
  • 46
  • 68

2 Answers2

6

It seems to work if you don't set preventBubble to false:

$('#drop').bind('dragenter', dragenter);
$('#drop').bind('dragover', dragover);
$('#drop').bind('drop', drop);   

DEMO

Update: If you look at the documentation, passing three parameters where the last one is a boolean, is interpreted as:

.bind( eventType, [eventData], preventBubble )

which means that the handler is not used as event handler but as event data.

They changed how they detect the handler though. In jQuery 1.5.2, it was:

if ( jQuery.isFunction( data ) || data === false ) {
    fn = data;
    data = undefined;
}

You see, when the second argument was a function, then this one was used as event handler (instead of the third one).

But it was changed in jQuery 1.6.2 to:

if ( arguments.length === 2 || data === false ) {
    fn = data;
    data = undefined;
}

Now it is only tested how many arguments are passed. As, in your case, data is not false (it is a function) and you pass three arguments, fn is not changed. It stays false.

When the handler is false, then this happens:

if ( handler === false ) {
    handler = returnFalse;
} else if ( !handler ) {
    // Fixes bug #7229. Fix recommended by jdalton
    return;
}

So this could actually be seen as bug in jQuery 1.5 which is now fixed and is not a problem with these particular events.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

I found that my issue lied with jQuery glorifying the original event object during the bind process.

My code looked like this:

$dropArea = $(".dropArea");
$dropArea.bind({
    dragover: function (ev) {
        $(this).addClass('hover');
        ev.preventDefault();
        return false;
    },
    dragend: function () {
        $(this).removeClass('hover');
        return false;
    },
    dragleave: function () {
        $(this).removeClass('hover');
        return false;
    },
    drop: function (ev) {
        ev.preventDefault();
        //e = e || window.event;
        var data = ev.dataTransfer.getData("text/html");
        ev.target.appendChild(document.getElementById(data));

        console.log("dropping element.");
        return false;
    });

jQuery was wrapping the old event object up into a newer more glorified jQuery version of the event object.

I added this line:

ev = ev.originalEvent; 

to get the original event object back, upon which I could call the preventDefault(), and all worked well once again.

I hope this helps save someone time! (Still wrapping my head around the jQuery objects and functions associated with them, as they relate back to the original javascript objects).

Stevers
  • 516
  • 5
  • 11