Preventing click event with jQuery drag and drop

Viewed 78578

I have elements on the page which are draggable with jQuery. Do these elements have click event which 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 is not dragged and drop state?

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

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

16 Answers

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.

lex82's version but for .sortable()

 start: function(event, ui){
 ui.item.find('.ui-widget-header').addClass('noclick');
 },

and you may only need:

 start: function(event, ui){
 ui.item.addClass('noclick');
 },

and here's what I'm using for the toggle:

$("#datasign-widgets .ui-widget-header").click(function(){
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');

}
else {
$(this).next().slideToggle();
$(this).find('.ui-icon').toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
}
});

the most easy and robust solution? just create transparent element over your draggable.

.click-passthrough {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: transparent;
}

element.draggable({        
        start: function () {

        },
        drag: function(event, ui) {
            // important! if create the 'cover' in start, then you will not see click events at all
                  if (!element.find('.click-passthrough').length) {
                      element.append("<div class='click-passthrough'></div>");
                  }
        },
        stop: function() {
          // remove the cover
          element.find('.click-passthrough').remove();
        }
    });

for me helped passing the helper in options object as:

.sortable({
   helper : 'clone', 
   start:function(), 
   stop:function(),
   .....
});

Seems cloning dom element that is dragged prevented the bubbling of the event. I couldn“t avoid it with any eventPropagation, bubbling, etc. This was the only working solution for me.

The onmousedown and onmouseup events worked in one of my smaller projects.

var mousePos = [0,0];
function startClick()
{
    mousePos = [event.clientX,event.clientY];
}
        
function endClick()
{
    if ( event.clientX != mousePos[0] && event.clientY != mousePos[1] )
    {
        alert( "DRAG CLICK" );
    }
    else
    {
        alert( "CLICK" );
    }
}
<img src=".." onmousedown="startClick();" onmouseup="endClick();" />

Yes, I know. Not the cleanest way, but you get the idea.

Related