web-dev-qa-db-ja.com

jQuery UI Sortable-ドラッグ/ソートされたアイテムのクリックイベントをキャンセルするにはどうすればよいですか?

jQuery UI Sortable リストがあります。ソート可能なアイテムには、クリックイベントも添付されています。アイテムをドラッグした後にクリックイベントが発生しないようにする方法はありますか?

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

私は同じ問題を抱えていて、私の並べ替え可能なアイテムには3つまたは4つのクリック可能なアイテムが含まれていた(そしてその数は可変だった)ため、それらをオンザフライでバインド/アンバインドすることは実際には選択肢に見えませんでした。しかし、インシデントによって私は

helper : 'clone'

このオプションは、インターフェイスの点では元のソート可能なものと同じように動作しますが、ドラッグされたアイテムでクリックイベントを発生させないため、問題を解決します。それは他のものと同じくらいハックですが、少なくともそれは簡単で簡単です。

135
Elte Hupkes

Liのクリックイベントへの参照がある場合は、並べ替え可能な更新メソッドでバインドを解除し、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>
13
Andrew Champion

何らかの理由で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;
}
3
Fredrik Harloff
$('.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(); } );
    }
});

これは、 "one-listeners"が起動されるために機能しますbefore "normal"リスナー。そのため、1つのリスナーが伝播を停止した場合、以前に設定したリスナーに到達することはありません。

2
Tom de Boer

メルシーラーの答えは、私にとっていくつかの警告をもたらしました。クリックイベントは、実際には、ソートされたアイテム自体ではなく、ハンドル要素にありました。残念ながら、uiオブジェクトは、更新イベントのハンドルへの参照を提供しません(jquery uiへの機能要求?)。だから私は自分でハンドルを取得する必要がありました。また、クリックアクションを停止するにはpreventDefaultを呼び出す必要がありました。

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

また、停止イベントでフラグを使用し、クリックイベントでそのフラグを確認することもできます。

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;

});
1
Saurabh

より簡単に、要素がいつソートされるかを知るために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>
1
ragnar

1つの解決策は、通常のバインディングの代わりにlive()を使用することですが、Elte Hupkesのソリューションは素晴らしいです!!!!

0
Bakaburg