使用 jQuery 拖放防止单击事件

IT技术 javascript jquery events drag-and-drop jquery-ui-sortable
2021-01-14 15:23:36

我在页面上有可使用 jQuery 拖动的元素。这些元素是否具有导航到另一个页面的点击事件(例如普通链接)。

防止单击在放置此类元素时触发同时允许单击它不是拖放状态的最佳方法是什么?

我对可排序元素有这个问题,但认为有一个通用拖放的解决方案是很好的。

我已经为自己解决了这个问题。在那之后,我发现Scriptaculous 存在相同的解决方案,但也许有人有更好的方法来实现这一目标。

6个回答

一个对我来说效果很好并且不需要超时的解决方案:(是的,我有点迂腐;-)

我在拖动开始时向元素添加一个标记类,例如“noclick”。当元素被放置时,点击事件被触发——更准确地说,如果拖动结束,实际上它不必被放置到一个有效的目标上。在单击处理程序中,我删除标记类(如果存在),否则将正常处理单击。

$('your selector').draggable({
    start: function(event, ui) {
        $(this).addClass('noclick');
    }
});

$('your selector').click(function(event) {
    if ($(this).hasClass('noclick')) {
        $(this).removeClass('noclick');
    }
    else {
        // actual click event code
    }
});
有用!一次没有为我工作,可能是因为我在之前的尝试中搞砸了同样的事情,并且这些类最终在与单击的元素不同的元素上......但无论如何,我使用了一个全局变量(在这方面非常简单的页面还可以),而且效果也很好。
2021-03-21 15:23:36
要保存类或数据的设置,您还可以在单​​击事件处理程序中使用: if (!$(this).is('.ui-draggable-dragging')) { ... click action }
2021-03-25 15:23:36
这让我找到了我的解决方案,我只是使用了 jQuery 数据函数而不是类。谢谢。
2021-03-29 15:23:36
但浏览器不会在每次放下元素时触发点击事件
2021-03-29 15:23:36
oop,你不想stop: function(event, ui) { $(this).removeClass('noclick'); }在可拖动处理程序中吗?否则不会在其他地方的每次拖放都会阻止下一次单击“您的选择器”。
2021-04-01 15:23:36

解决方案是添加单击处理程序,以防止单击在拖动开始时传播。然后在执行 drop 后删除该处理程序。最后一个动作应该延迟一点,以便点击预防工作。

可排序的解决方案:

...
.sortable({
...
        start: function(event, ui) {
            ui.item.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.item.unbind("click.prevent");}, 300);
        }
...
})

可拖动解决方案:

...
.draggable({
...
        start: function(event, ui) {
            ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
        }
...
})
如果您传递值为 'clone' 的属性助手,它会避免将事件触发到拖动排序的项目.. {helper: 'clone', start, stop... etc},
2021-03-15 15:23:36
@aaron 这个答案如下有效:http ://stackoverflow.com/a/4572831/119765
2021-03-25 15:23:36
另一个简单的答案 - 只需将 jQuery .click() 处理程序放在 .draggable() stackoverflow.com/questions/18032136/...
2021-03-28 15:23:36
奇怪的是你回答了你自己的问题,它甚至不起作用,Sasha lol。
2021-04-03 15:23:36
似乎这无法阻止我的点击事件,我使用的是 jquery 1.9.1 和 jquery.ui 1.10.3
2021-04-08 15:23:36

我遇到了同样的问题并尝试了多种方法,但没有一种对我有用。

方案一

$('.item').click(function(e)
{            
    if ( $(this).is('.ui-draggable-dragging') ) return false;
});  

对我没有任何作用。拖动完成后正在单击该项目。

解决方案 2(作者:Tom de Boer)

$('.item').draggable(
{   
    stop: function(event, ui) 
    {
         $( event.originalEvent.target).one('click', function(e){ e.stopImmediatePropagation(); } );
    }
});

这工作得很好,但在一种情况下失败 - 当我全屏点击时:

var body = $('body')[0];     
req = body.requestFullScreen || body.webkitRequestFullScreen || body.mozRequestFullScreen;
req.call(body); 

解决方案 3(由 Sasha Yanovets)

 $('.item').draggable({
        start: function(event, ui) {
            ui.helper.bind("click.prevent",
                function(event) { event.preventDefault(); });
        },
        stop: function(event, ui) {
            setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
        }
})

这对我不起作用。

解决方案 4 - 唯一一个运行良好的解决方案

$('.item').draggable(
{   
});
$('.item').click(function(e)
{  
});

是的,就是这样 - 正确的顺序可以解决问题 - 首先你需要绑定 draggable() 然后 click() 事件。即使我将全屏切换代码放在 click() 事件中,拖动时它仍然没有进入全屏。适合我!

#4 对我来说是正确和最简单的解决方案,不使用类或变量。
2021-04-03 15:23:36
只有一个对我有用(在 IE11/Edge 中)是解决方案 4。谢谢!
2021-04-09 15:23:36

我想补充一点,似乎只有在可拖动或可排序事件之后定义单击事件时,才能阻止单击事件。如果首先添加点击,它会在拖动时激活。

我真的不喜欢使用计时器或预防,所以我所做的是:

var el, dragged

el = $( '#some_element' );

el.on( 'mousedown', onMouseDown );
el.on( 'mouseup', onMouseUp );
el.draggable( { start: onStartDrag } );

onMouseDown = function( ) {
  dragged = false;
}

onMouseUp = function( ) {
  if( !dragged ) {
    console.log('no drag, normal click')
  }
}

onStartDrag = function( ) {
  dragged = true;
}

坚如磐石..

这对我来说是最好的解决方案。我在使用 jquery.ui.touch.punch.js 使单击事件在可在移动 Web 浏览器中排序的 jquery UI 上工作时遇到了麻烦,但这相当优雅地解决了它。
2021-03-30 15:23:36