Javascript 使用jQuery拖放防止单击事件

Javascript 使用jQuery拖放防止单击事件,javascript,jquery,events,drag-and-drop,jquery-ui-sortable,Javascript,Jquery,Events,Drag And Drop,Jquery Ui Sortable,我在页面上有可以用jQuery拖动的元素。这些元素是否具有导航到另一个页面(例如普通链接)的单击事件 在允许单击该元素时,防止单击触发该元素的最佳方法是什么 我对可排序元素有这个问题,但我认为对于一般的拖放有一个解决方案是很好的 我自己解决了这个问题。之后,我找到了相同的解决方案,但可能有人有更好的方法来实现这一点。解决方案是添加单击处理程序,以防止在拖动开始时单击传播。然后在执行drop后删除该处理程序。最后一个动作应该延迟一点,以防点击 可排序的解决方案: ... .sortable({ .

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

在允许单击该元素时,防止单击触发该元素的最佳方法是什么

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


我自己解决了这个问题。之后,我找到了相同的解决方案,但可能有人有更好的方法来实现这一点。

解决方案是添加单击处理程序,以防止在拖动开始时单击传播。然后在执行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);
        }
...
})

您是否尝试过使用event.preventDefault()禁用链接;在开始事件中,并在拖放停止事件或使用取消绑定的拖放事件中重新启用它?

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

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

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

$('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
    }
});

lex82的版本,但不适用于.sortable()

您可能只需要:

 start: function(event, ui){
 ui.item.addClass('noclick');
 },
下面是我使用的切换:

$("#datasign-widgets .ui-widget-header").click(function(){
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');

}
else {
$(this).next().slideToggle();
$(this).find('.ui-icon').toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
}
});

在不阻止违约的情况下,萨沙回答的一个可能的替代方案:

var tmp_handler;
.sortable({
        start : function(event,ui){
            tmp_handler = ui.item.data("events").click[0].handler;
            ui.item.off();
        },
        stop : function(event,ui){
            setTimeout(function(){ui.item.on("click", tmp_handler)}, 300);
        },

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

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

岩石固体..

以上给出的答案只需添加一点褶皱即可。我必须创建一个包含SalesForce元素Dragable的div,但是SalesForce元素通过一些VisualForce gobbledigook在html中定义了onclick操作

显然,这违反了“拖动操作后定义单击操作”规则,因此作为一种解决方法,我重新定义了SalesForce元素要触发的操作“onDblClick”,并将以下代码用于容器div:

$(this).draggable({
        zIndex: 999,
        revert: true,
        revertDuration: 0,
        start: function(event, ui) {
                   $(this).addClass('noclick');
                }
});

$(this).click(function(){
    if( $(this).hasClass('noclick'))
    {
        $(this).removeClass('noclick');
    }
    else
    {
        $(this).children(":first").trigger('dblclick');
    }
});

父元素的click事件本质上隐藏了双击子元素的需要,用户体验保持不变。

在阅读了本文和一些线程之后,这就是我使用的解决方案

var dragging = false;
$("#sortable").mouseover(function() {
    $(this).parent().sortable({
        start: function(event, ui) {
            dragging = true;
        },
        stop: function(event, ui) {
            // Update Code here
        }
    })
});
$("#sortable").click(function(mouseEvent){
    if (!dragging) {
        alert($(this).attr("id"));
    } else {
        dragging = false;
    }
});

我也有同样的问题,尝试了多种方法,但没有一种对我有效

解决方案1

$('.item').click(function(e)
{            
    if ( $(this).is('.ui-draggable-dragging') ) return false;
});  
对我来说什么都不做。拖动完成后,将单击该项

解决方案2(作者:汤姆·德·波尔)

这很好,但在一个案例中失败了-当我全屏点击时:

var body = $('body')[0];     
req = body.requestFullScreen || body.webkitRequestFullScreen || body.mozRequestFullScreen;
req.call(body); 
解决方案3(萨沙·亚诺维茨)

这对我不起作用

解决方案4-唯一一个工作正常的解决方案

$('.item').draggable(
{   
});
$('.item').click(function(e)
{  
});
是的,就是这样-正确的顺序起作用-首先需要绑定draggable(),然后单击()事件。即使我将全屏切换代码放入click()事件中,拖动时它仍然不会全屏显示。非常适合我

我试着这样做:

var dragging = true; 

$(this).click(function(){
  if(!dragging){
    do str...
  }
});

$(this).draggable({
  start: function(event, ui) {
      dragging = true;
  },

  stop: function(event, ui) {
      setTimeout(function(){dragging = false;}, 300);
  }

});

在我的例子中,它是这样工作的:

var dragging = true; 

$(this).click(function(){
  if(!dragging){
    do str...
  }
});

$(this).draggable({
  start: function(event, ui) {
      dragging = true;
  },

  stop: function(event, ui) {
      setTimeout(function(){dragging = false;}, 300);
  }

});
$(“#可拖动”).draggable({
开始:功能(事件、用户界面){
$(event.toElement).one('click',函数(e){e.stopPropagation();});
}
});

在jQuery UI中,被拖动的元素被赋予类“UI可拖动拖动”。
因此,我们可以使用此类来确定是否单击,只需延迟事件。
您不需要使用“开始”或“停止”回调函数,只需执行以下操作:

$('#foo').on('mouseup', function () {
    if (! $(this).hasClass('ui-draggable-dragging')) {
        // your click function
    }
});

这是从“mouseup”触发的,而不是“mousedown”或“click”-因此有一点延迟,可能并不完美-但它比此处建议的其他解决方案更简单。

对于我,帮助在选项对象中传递帮助者,如下所示:

.sortable({
   helper : 'clone', 
   start:function(), 
   stop:function(),
   .....
});

似乎克隆拖动的dom元素阻止了事件冒泡。我无法避免任何事件传播、冒泡等。这是我唯一可行的解决方案

onmousedown和onmouseup事件在我的一个较小的项目中起作用

var mousePos=[0,0];
函数startClick()
{
mousePos=[event.clientX,event.clientY];
}
函数endClick()
{
if(event.clientX!=mousePos[0]&&event.clientY!=mousePos[1])
{
警报(“拖动单击”);
}
其他的
{
警报(“点击”);
}
}

最简单、最可靠的解决方案?只需在可拖动对象上创建透明元素

.click-passthrough {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: transparent;
}

element.draggable({        
        start: function () {

        },
        drag: function(event, ui) {
            // important! if create the 'cover' in start, then you will not see click events at all
                  if (!element.find('.click-passthrough').length) {
                      element.append("<div class='click-passthrough'></div>");
                  }
        },
        stop: function() {
          // remove the cover
          element.find('.click-passthrough').remove();
        }
    });
。单击传递{
位置:绝对位置;
左:0;
排名:0;
右:0;
底部:0;
背景:透明;
}
元素。可拖动({
开始:函数(){
},
拖动:函数(事件、ui){
//重要提示!如果在“开始”中创建“封面”,则根本看不到单击事件
如果(!element.find('.click passthrough').length){
元素。追加(“”);
}
},
停止:函数(){
//取下盖子
元素。查找('.click passthrough')。删除();
}
});

有用!可能是因为我之前尝试过同一件事,结果这些类出现在了与单击的元素不同的元素上。。但不管怎样,我使用了一个全局变量(在这个非常简单的页面上,这个变量还可以),这也很好地工作了。这就引出了我的解决方案,我只是使用jQuery数据函数而不是类。谢谢。但浏览器不会在您每次拖放元素时触发单击事件要保存设置类或数据,在单击事件处理程序中,您还可以使用:if(!$(this).is('.ui可拖动)-
.sortable({
   helper : 'clone', 
   start:function(), 
   stop:function(),
   .....
});
.click-passthrough {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: transparent;
}

element.draggable({        
        start: function () {

        },
        drag: function(event, ui) {
            // important! if create the 'cover' in start, then you will not see click events at all
                  if (!element.find('.click-passthrough').length) {
                      element.append("<div class='click-passthrough'></div>");
                  }
        },
        stop: function() {
          // remove the cover
          element.find('.click-passthrough').remove();
        }
    });