【问题标题】:How do I prevent a jQuery 'click' event from firing when mouse is dragged拖动鼠标时如何防止触发jQuery“单击”事件
【发布时间】:2026-02-13 21:20:03
【问题描述】:

当您单击面板标题时,我的面板会折叠/展开。

但这些标题中的文本通常需要选择以进行复制/粘贴。

如何防止 jQuery 事件 .slideUp.slideDown 在单击鼠标以拖动以选择文本时触发?

var currentlyAnimating = false;
function setAnimationOff() {
    currentlyAnimating = false;
}
function setAnimationOn(this_animation) {
    currentlyAnimating = this_animation;
    setTimeout(setAnimationOff, 650);
}
function panelAccordionAnimation(this_heading) {
    var _meta_div = this_heading.nextAll('.panel-body, .course-heading');
    var _button = this_heading.find('.heading-container-btn.right-most');
    if (_meta_div.css('display') == 'none') {
        this_heading
            .animate({
                borderBottomLeftRadius: 0,
                borderBottomRightRadius: 0}, 200);
        _button
            .animate({
                borderBottomRightRadius: 0}, 200);
        _meta_div.delay(200).slideDown();
    } else {
        _meta_div.slideUp();
        this_heading.delay(200)
            .animate({
                borderBottomLeftRadius: 14,
                borderBottomRightRadius: 14}, 200);
        _button.delay(200)
            .animate({
                borderBottomRightRadius: 14}, 200);
    }
}
_student_details.on('click', '.top-heading.blue', function(e) {
    var _heading = $(e.target);
    if (_heading == currentlyAnimating) {
        return false;
    }
    panelAccordionAnimation(_heading);
    setAnimationOn(_heading);
});
_student_details.on('click', '.top-heading.blue .heading-container-title', function(e) {
    var _heading = $(e.target).parent();
    if (_heading == currentlyAnimating) {
        return false;
    }
    panelAccordionAnimation(_heading);
    setAnimationOn(_heading);
});

我对标题中的文本有单独的单击事件,因为我希望在单击标题时发生折叠/展开,而不是在将鼠标拖动到标题上时发生。

【问题讨论】:

  • 不是“如何防止事件触发”,而是按照“当某个条件为真时如何忽略事件”的思路。
  • 你能分享你正在使用的代码的相关部分吗?
  • 为什么不在标题中使用链接?它可以被点击/选择...就像bootstrap accordion一样。
  • 我什至不知道 bootstrap 自带手风琴!

标签: javascript jquery


【解决方案1】:

mousedown 处理程序绑定到元素,在其中存储鼠标的坐标。在单击事件中,将这些鼠标坐标与当前坐标进行比较,如果它们不一样,则鼠标已移动,您可以阻止处理程序的其余代码运行:

$( yourEl ).on( {
  mousedown: function( evt ) {
    $( this ).data( 'mCoords', { x: evt.pageX, y: evt.pageY } );
  },
  click: function( evt ) {
    var $this = $( this );

    if ( $this.data( 'mCoords' )[ 'x' ] !== evt.pageX 
      || $this.data( 'mCoords' )[ 'y' ] !== evt.pageY
    ) {
      // the mouse was moved
      return true;
    }

    // your code
  }
} );

Here's a fiddle

【讨论】:

    【解决方案2】:

    我相信您有多种方法可供选择,以确定用户是尝试关闭手风琴还是仅选择一些文本。

    1. 您可以查看mousedown 事件和mouseup 之间的时间距离。在mousedown 事件上,将布尔值(我们称之为quick)设置为true,并将timeout 函数设置为80 毫秒(人类最短反应时间)以将其设置为false。在您的 mouseup 事件中,在触发 .slideUp.slideDown 之前检查该布尔值。
    2. 检查用户是否在您的标题中选择了文本。如果此测试是 true,您可以使用 window.getSelection().anchorNode === e.target 执行此操作,在您的标题中选择了一些文本,您可以决定在 mouseup 事件发生时不触发 .slideUp.slideDown

    虽然我会说上面的两个选项都是一种黑客攻击,但我认为没有其他方法可以区分旨在将标题折叠为仅用于选择的点击的点击。

    【讨论】:

      【解决方案3】:

      很简单。

      使用mouseup触发点击事件。

      你可以像这样使用 mouseup:

      $( "#target" ).mouseup(function() {
         alert( "Handler for mouseup() called." );
      })
      

      有一个变量var check = false;

      仅当注册了mouseup 时才将其设为真。

      将此检查添加到所有函数并仅在 check = true 时触发

      【讨论】:

      • 文本被选中后仍然会触发。如果鼠标在mousedownmouseup 之间移动,我试图阻止所有触发
      • @LXXIII 是的,请检查验证。仅当您有 mouseup 事件时才将其设置为 true。如果该检查为真,则触发 click 函数。
      • @billyonecan 我让他在他拥有的点击事件中添加一个条件。它会解决问题。
      • 我不明白添加 mouseup 处理程序如何解决问题
      • @billyonecan 一旦用户点击 div 一个函数就会被调用。我没有使用 click 我让他使用 mouseup。所以在 mouseup 上应该调用这个函数。
      最近更新 更多