jQuery UI Sortable -- How can I cancel the click event on an item that's dragged/sorted?

Viewed 32841

I have a jQuery UI Sortable list. The sortable items also have a click event attached. Is there a way to prevent the click event from firing after I drag an item?

$().ready( function () { 
 $('#my_sortable').sortable({
   update: function() { console.log('update') },
   delay: 30
 });    

 $('#my_sortable li').click(function () {    
   console.log('click');
 });                        

});
#my_sortable li {
          border: 1px solid black;
          display: block;
          width: 100px;
          height: 100px;    
          background-color: gray;
        }
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>

<ul id="my_sortable">                 
  <li id="item_1">A</li>
  <li id="item_2">B</li>
  <li id="item_3">C</li>
</ul>   

10 Answers

If you have a reference to the click event for your li, you can unbind it in the sortable update method then use Event/one to rebind it. The event propagation can be stopped before you rebind, preventing your original click handler from firing.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head> 


  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>

  <script type="text/javascript" charset="utf-8">
    var myClick = function () {
        console.log('click');
    };

    $().ready( function () { 

       $('#my_sortable').sortable({
         update: function(event, ui) { 
            ui.item.unbind("click");
            ui.item.one("click", function (event) { 
                console.log("one-time-click"); 
                event.stopImmediatePropagation();
                $(this).click(myClick);
            }); 
            console.log('update') },
         delay: 30
       });    


       $('#my_sortable li').click(myClick);                        

     });
  </script>

  <style type="text/css" media="screen">
    #my_sortable li {
      border: 1px solid black;
      display: block;
      width: 100px;
      height: 100px;    
      background-color: gray;
    }
  </style>

</head>
<body>

      <ul id="my_sortable">                 
        <li id="item_1">A</li>
        <li id="item_2">B</li>
        <li id="item_3">C</li>
      </ul>   

</body>
</html>

The answer by mercilor worked for me a couple of caveats. The click event was actually on the handle element rather than the sorted item itself. Unfortunately the ui object, doesn't give you a reference to the handle in the update event (feature request to jquery ui?). So I had to get the handle myself. Also, I had to call preventDefault as well to stop the click action.

update: function(ev, ui) {
    var handle = $(ui.item).find('h3');
    handle.unbind("click");
    handle.one("click", function (event) {
                            event.stopImmediatePropagation();
                            event.preventDefault();
                            $(this).click(clickHandler);
                        });
    // other update code ...

We can also use a flag on the stop event that and check that flag on the click event.

var isSortableCalled = false;

$('#my_sortable').sortable({
         stop: function(event, ui){
              isSortableCalled = true;
         },
         update: function() { console.log('update') },
         delay: 30
});

$('#my_sortable li').click(function () {    
       if(!isSortableCalled){
            console.log('click');
       }
       isSortableCalled = false;

});
Related