views:

800

answers:

5

I have an elements on page that are draggabe with jQuery. These elements have click event wich navigates to another page (ordinary links for example).

What is the best way to prevent click from firing on dropping such element, while allowing clicking it in not drag and drop state?

I have this problem with sortable elements, but think it is good to have solution for general drag and drop.

I've solved the problem for myself. After that found that same solution exists for Scriptaculous, but maybe someone have a better way to achieve that.

+4  A: 

Solution is to add click handler that will prevent click to propagate on start of drag. And then remove that handler after drop is performed. The last action should be delayed a bit for click prevention to work.

Solution for sortable:

...
.sortable({
...
        start: function(event, ui) {
            ui.item.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.item.unbind("click.prevent");}, 300);
        }
...
})

Solution for draggable:

...
.draggable({
...
        start: function(event, ui) {
            ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
        }
...
})
Sasha Yanovets
A: 

Have you tried disabling the link using event.preventDefault(); in the start event and re-enabling it in the drag stopped event or drop event using unbind?

alienonland
A: 

Hello, im a beginner in Jquery. I'm using the ui.dragabble.js. and having the same problem where the click event is activated at the end of dragging. My question is where exactly do you insert the above code:

start: function(event, ui) { ui.helper.bind("click.prevent", function(event) { event.preventDefault(); }); }, stop: function(event, ui) { setTimeout(function(){ui.helper.unbind("click.prevent");}, 300); }

thank you.

hide
A: 

I'd like to add to this that it seems preventing the click event only works if the click event is defined AFTER the draggable or sortable event. If the click is added first, it gets activated on drag.

kasakka
+3  A: 

A solution that worked well for me and that doesn't require a timeout: (yes I'm a bit pedantic ;-)

I add a marker class to the element when dragging starts, e.g. 'noclick'. When the element is dropped, the click event is triggered -- more precisely if dragging ends, actually it doesn't have to be dropped onto a valid target. In the click handler, I remove the marker class if present, otherwise the click is handled normally.

$('your selector').draggable({
    start: function(event, ui) {
        $(this).addClass('noclick');
    }
});

$('your selector').click(function(event) {
    if ($(this).hasClass('noclick') {
        $(this).removeClass('noclick');
    }
    else {
        // actual click event code
    }
});
lex82
Useful! Didn't working for me in one go, probably because I was messing in previous attempts at the same thing and the classes ended up on a different element than the one clicked.. but anyway, I used a global variable (which on this extremely simple page was ok), and that worked quite well also.
MSpreij
This lead me to my solution, I just used the jQuery data function instead of a class. Thanks.
William