JQuery UI Sortable - Как я могу отменить событие клика на элементе, который перетаскивался/сортировался?

У меня есть сортируемый список jQuery UI. Сортируемые элементы также имеют прикрепленное событие щелчка. Есть ли способ предотвратить срабатывание события click после перетаскивания элемента?

$().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>   

Ответ 1

У меня была такая же проблема, и поскольку мои сортируемые элементы содержали три или четыре элемента, которые можно было бы щелкнуть (и число было переменным), привязка/развязка их на лету действительно не представляла собой вариант. Однако по инциденту я указал

helper : 'clone'

который ведет себя идентично исходному, сортируемому с точки зрения интерфейса, но, по-видимому, не вызывает события щелчка на перетаскиваемом элементе и, таким образом, решает проблему. Это как взломать как что-нибудь еще, но, по крайней мере, это коротко и легко.

Ответ 2

Если у вас есть ссылка на событие click для вашего ли, вы можете отменить его в отсортированном методе обновления, а затем использовать Event/one для его повторной привязки. Распространение события может быть остановлено до того, как вы переустановите его, чтобы предотвратить запуск исходного обработчика кликов.

<!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>

Ответ 3

Если вы по какой-то причине не хотите использовать трюк helper:'clone', это сработало для меня. Он отменяет событие клика на элементе, который перетаскивается. jQuery добавляет класс ui-sortable-helper к перетаскиваемому элементу.

$('.draggable').click(clickCancelonDrop);
function clickCancelonDrop(event) {
    var cls = $(this).attr('class');
    if (cls.match('ui-sortable-helper'))
         return event.stopImmediatePropagation() || false;
}

Ответ 4

$('.selector').draggable({
    stop: function(event, ui) {
        // event.toElement is the element that was responsible
        // for triggering this event. The handle, in case of a draggable.
        $( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );
    }
});

Это работает, потому что "однослушатели" увольняются перед "нормальными" слушателями. Поэтому, если один слушатель прекращает распространение, он никогда не достигнет ваших ранее установленных слушателей.

Ответ 5

Ответ мерсилором дал мне пару предостережений. Событие click было фактически на элементе handle, а не на отсортированном элементе. К сожалению, объект ui, не дает вам ссылку на дескриптор события обновления (запрос функции jquery ui?). Поэтому мне пришлось самому взять ручку. Кроме того, мне пришлось вызвать preventDefault, чтобы остановить действие click.

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 ...

Ответ 6

Проще, используйте var, чтобы знать, когда элемент сортируется...

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

<html>
<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">
    $().ready( function () {    
       $('#my_sortable').sortable({
         start: function() {
            sorting = true;
         },
         update: function() {
            console.log('update');
            sorting = false;
         },
         delay: 30
       });    


       $('#my_sortable li').click(function () {
         if (typeof(sorting) == "undefined" || !sorting) {
            console.log('click');
         }
       });                        

     });
  </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>

Ответ 7

Мы также можем использовать флаг в событии остановки и проверить этот флаг на событии клика.

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;

});

Ответ 8

Одним из решений является использование live() вместо нормального связывания, но решение Elte Hupkes Rock!!!!

Ответ 9

Благодаря Elte Hupkus;

helper: 'clone' 

Я реализовал то же самое, и образец показан ниже.

$(document).ready(function() {
$("#MenuListStyle").sortable({
 helper:'clone',
 revert:true
}).disableSelection();
});

Ответ 10

$('.menu_group tbody a').click(function(){
    link = $(this).attr('href');
    window.location.href = link;
});

Это решение работает для меня. Теперь я могу щелкнуть clickables внутри сортируемых элементов.

Примечание: ".menu_group tbody" есть .sortable();