jQuery UI Sortable -- 如何取消拖动/排序项目的点击事件?

Posted

技术标签:

【中文标题】jQuery UI Sortable -- 如何取消拖动/排序项目的点击事件?【英文标题】:jQuery UI Sortable -- How can I cancel the click event on an item that's dragged/sorted? 【发布时间】:2010-10-31 03:18:22 【问题描述】:

我有一个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>   

【问题讨论】:

现在浏览器和 jqueryui 已经有一些时间来发展(补偿?)这种行为只在 Firefox (47.0) 中很明显。现代 Chrome 和 IE 在sortable 之后不会触发click 事件。 【参考方案1】:

我遇到了同样的问题,因为我的可排序项目包含三个或四个可点击项目(并且数量是可变的),动态绑定/取消绑定它们似乎并不是一个选项。但是,顺便说一句,我指定了

helper : 'clone'

选项,在界面方面与原始可排序的行为相同,但显然不会在拖动的项目上触发点击事件,从而解决了问题。它和其他任何东西一样都是一个 hack,但至少它是简短而容易的..

【讨论】:

Levi Crain 说:“"helper : 'clone'" 技巧在 chrome 中不起作用。onclick 事件永远不会触发。” 在 Firefox 16 中的工作就像一个魅力!谢谢 绝对是最佳答案!我喜欢简单的解决方案。上一个答案(选定答案)中的代码很聪明,但长期维护具有挑战性,尤其是对于试图找出聪明代码的新程序员 我在组合 sortable 和 Magnific Popup 时遇到了问题。拖动元素后,将显示弹出窗口。在我为这个问题挣扎了几个小时之后,这就像上帝的礼物。 哇!这救了我的命!谢啦!谁知道会这么简单! :D【参考方案2】:

如果你的 li 引用了 click 事件,你可以在 sortable update 方法中解绑它,然后使用 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;

【讨论】:

draggable 来自哪里?我以为这是关于sortable。确实,$('.draggable') 对我来说是一个空列表。 ´.sortable´ 是容器列表,里面的所有项目都是´.draggable´【参考方案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();  );
    
);

这是可行的,因为 "one-listeners" "normal" 侦听器之前触发。因此,如果一个监听器停止传播,它将永远无法到达您之前设置的监听器。

【讨论】:

问题是如果浏览器在拖动过程中从不触发点击事件,这将阻止第一个“真正的”点击事件 对于 Firefox 42.0,我无法确认 on 监听器是在 one 监听器之后触发的。事实上,我的on 侦听器仍然在我的one 侦听器之前被调用。【参考方案5】:

mercilor 的回答对我有一些警告。 click 事件实际上是在句柄元素上,而不是在排序的项目本身上。不幸的是,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 ...

【讨论】:

【参考方案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】:

感谢Elte Hupkus;

helper: 'clone' 

我已经实现了相同的,下面显示了一个示例。

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

【讨论】:

【参考方案9】:

一种解决方案是使用 live() 而不是普通绑定,但 Elte Hupkes 解决方案非常棒!!!!

【讨论】:

【参考方案10】:
$('.menu_group tbody a').click(function()
    link = $(this).attr('href');
    window.location.href = link;
);

这个解决方案似乎对我有用。现在我可以点击可排序元素内的可点击内容。

注意:".menu_group tbody".sortable();

【讨论】:

以上是关于jQuery UI Sortable -- 如何取消拖动/排序项目的点击事件?的主要内容,如果未能解决你的问题,请参考以下文章

jquery UI sortable:如何更改“占位符”对象的外观?

jquery UI sortable:如何让原始可见直到下降?

jQuery UI 的 Sortable - 如何设置我的 'li.ui-state-highlight' 的样式?,总是出现白色 bg 颜色

如何让 jQuery UI 的 Draggable 和 Sortable 函数在 iPhone 上工作?

jQuery UI Sortable -- 如何取消拖动/排序项目的点击事件?

将 jquery ui-sortable 位置保存到 DB