当dblclick事件触发时,防止点击事件被触发

时间:2009-05-19 01:37:28

标签: javascript javascript-events

我正在处理DOM元素上的click和dblclick事件。每个执行一个不同的命令,但我发现双击该元素时,除了触发双击事件外,click事件也会被触发两次。防止这种行为的最佳方法是什么?

13 个答案:

答案 0 :(得分:22)

如果其他人偶然发现(正如我所做)寻找答案,我能提出的绝对最佳解决方案如下:         

Dim a As Range

Set a = ActiveSheet.Cells.Find("Part Class")

If a Is Nothing Then Exit Sub

Set a = a.EntireColumn

'Note: if any of the terms below are not found then you'll get
'  a run-time error
'If you want to ignore those then uncomment the lines noted

'On Error Resume Next '<<##
With a
    .Find("CONS").EntireRow.DELETE
    .Find("MISC").EntireRow.DELETE
    .Find("PFG").EntireRow.DELETE
    .Find("PRT").EntireRow.DELETE
    .Find("TOTE").EntireRow.DELETE
End With
'On Error Goto 0 '<<##

完成。如果背靠背有多个点击,第二个,第三个等等。不会开枪。我绝对更喜欢使用任何类型的计时器。

我通过阅读this让自己指向了这个方向。

顺便说一句:我第一次研究这个问题是因为我不小心双击了一个分页链接,并且在回调发生之前事件被触发并完成了两次。

在提出上述代码之前,我有

    $node.on('click',function(e){
      if(e.originalEvent.detail > 1){
         return;
        /* if you are returning a value from this
         function then return false or cancel 
         the event some other way */
      }
    });

然而,我能够点击链接3次(三次点击),虽然第二次点击没有触发,但第三次点击

答案 1 :(得分:13)

在评论中,你说,

  

我将点击处理程序延迟了300毫秒(一个明显而烦人的延迟)甚至......

所以听起来你想要的是,当你点击时,DOM应该立即生成一个点击事件,除非点击是第一次点击双击。

要实现此功能,当您单击时,DOM需要能够预测这是否是最终点击或者是否是双击中的第一次(但我认为通常不可能用于预测用户是否即将再次点击的DOM。


点击和双击时,您尝试采取的两个不同的操作是什么? IMO,在正常的应用程序中,您可能需要两个事件:例如单击以关注元素,然后双击以激活它。

当您必须分开事件时,某些应用程序会使用双击之外的其他内容:例如,他们使用右键单击或按住Control键单击。

答案 2 :(得分:5)

在这种情况下,最好稍微延迟单击事件的执行。让双击处理程序设置单击事件将检查的变量。如果该变量具有特定值,可以是boolDoubleClick == true,则不要fire/handle单击。

答案 3 :(得分:4)

如果您想要检测点击元素的次数并根据该次数触发事件,则可以使用UIEvent.detail

一个简单的例子:

element.addEventListener("click", function (e) {
  if (e.detail === 1) {
    // do something if the element was clicked once.
  } else if (e.detail === 2) {
    // do something else if the element was clicked twice
  }
});

答案 4 :(得分:3)

AFAIK DOM Level 2 Events没有双击规范。 它在IE7上对我不起作用(有震撼),但FF和Opera管理规范没有问题,我可以将所有动作附加到click事件,但是双击只是等到“detail”属性事件对象是2.从文档:“如果在同一屏幕位置发生多次点击,则重复序列,每次重复时细节属性都会递增。”

答案 5 :(得分:3)

以下是我在模块中区分的内容

       node.on('click', function(e) {

            //Prepare for double click, continue to clickHandler doesn't come soon enough
            console.log("cleared timeout in click",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            _this.clickTimeout = setTimeout(function(){
                console.log("handling click");
                _this.onClick(e);
            },200);
            console.log(_this.clickTimeout);
        });

        node.on('dblclick', function (e) {

            console.log("cleared timeout in dblclick",_this.clickTimeout);
            clearTimeout(_this.clickTimeout);
            // Rest of the handler function

答案 6 :(得分:2)

感谢这里的所有其他答案,因为它们的组合似乎为我提供了一个合理的解决方案,当交互需要两者,但互相排斥时:

var pendingClick = 0;

function xorClick(e) {
    // kill any pending single clicks
    if (pendingClick) {
        clearTimeout(pendingClick);
        pendingClick = 0;
    }

    switch (e.detail) {
        case 1:
            pendingClick = setTimeout(function() {
                console.log('single click action here');
            }, 500);// should match OS multi-click speed
            break;
        case 2:
            console.log('double click action here');
            break;
        default:
            console.log('higher multi-click actions can be added as needed');
            break;
    }
}

myElem.addEventListener('click', xorClick, false);

更新:我添加了此方法的通用版本以及针对此Github存储库的触摸设备的点击填充,并附带示例:

https://github.com/mckamey/doubleTap.js

答案 7 :(得分:0)

我知道这已经老了,但我想我发布的任何内容,因为我遇到了同样的问题。以下是我如何解决它。

@include imgRetina('../assets/images/logo', png, 370px, 115px);

答案 8 :(得分:0)

如果我的dblclick事件应该执行其他操作,则我将这种解决方案用于我的项目以防止点击事件操作。

注意:此解决方案仅适用于click和dblclick,而不适用于其他任何东西,例如Tripleclick等。

要查看单击和双击之间的正确时间,请参见this

对不起,我的英语不好。 希望对您有所帮助:)

var button, isDblclick, timeoutTiming;
var clickTimeout, dblclickTimeout;
//-----
button = $('#button');
isDblclick = false;
/*
the proper time between click and dblclick is not standardized,
and is cutsomizable by user apparently (but this is windows standard I guess!)
*/
timeoutTiming = 500;
//-----
button.on('dblclick', function () {

  isDblclick = true;
  clearTimeout(dblclickTimeout);
  dblclickTimeout = setTimeout(function () {
    isDblclick = false;
  }, timeoutTiming);
  //-----
  // here goes your dblclick codes
  console.log('double clicked! not click.');
  
}).on('click', function () {

  clearTimeout(clickTimeout);
  clickTimeout = setTimeout(function () {
    if(!isDblclick) {
      // here goes your click codes
      console.log('a simple click.');
    }
  }, timeoutTiming);
  
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="button" id="button">
click/dblclick on this to see the result
</button>

答案 9 :(得分:0)

这是防止第二次点击的简单解决方案。当然,当检测到双击时,我可以重新启动超时,但实际上我根本不需要它。

update-ca-certificates

答案 10 :(得分:0)

总结一下,要识别同一元素上的simpleClick和doubleClick事件,只需使用以下方法处理onClick事件:

var EVENT_DOUBLE_CLICK_DELAY = 220; // Adjust max delay btw two clicks (ms)
var eventClickPending = 0;

function onClick(e){
    if ((e.detail == 2 ) && (eventClickPending!= 0)) {
//       console.log('double click action here ' + e.detail);
         clearTimeout(eventClickPending);
         eventClickPending = 0;
         // call your double click method
         fncEventDblclick(e);

    } else if ((e.detail === 1 ) && (eventClickPending== 0)){   
//      console.log('sigle click action here 1');
        eventClickPending= setTimeout(function() {
//          console.log('Executing sigle click');
            eventClickPending = 0
            // call your single click method
            fncEventClick(e);
        }, EVENT_DOUBLE_CLICK_DELAY);

//    } else { // do nothing
//      console.log('more than two clicks action here ' + e.detail);
            
    }
}

答案 11 :(得分:0)

您可以使用 debounce 使单击处理程序免于检测双击/多次单击

测试:https://jsfiddle.net/L3sajybp/

HTML

<div id='toDetect'>
Click or double-click me
</div>
<hr/>

<ol id='info'>
</ol>

JS

function debounce(func, wait, immediate) {
    let timeout;
    return function () {
        const context = this,
            args = arguments;
        const later = function () {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
}

function debounceSingleClickOnly(func, timeout = 500) {
   function eventHandler (event) {
        const { detail } = event;
      if (detail > 1) {
         console.log('no double click for you '+ func.name);
         console.log('');
         return;
      }
      
      func.apply(this, arguments);
   }
   
   return debounce(eventHandler, timeout); 
}

window.toDetect.addEventListener('click', debounceSingleClickOnly(handleSingleClick));

window.toDetect.addEventListener('dblclick', handleDoubleClick);

function handleS() {
    console.log('S func');
  console.log(this.id);
}

function handleSingleClick(event) { 
   console.log('single click');
   const divText = document.createElement('li');
   divText.appendChild(document.createTextNode('single click'));
   window.info.appendChild(divText)

   console.group();
   console.log('this element was single-clicked: ' + event.target.id);   
   console.log(this.id);  
     console.log('');   
   console.groupEnd();
}

function handleDoubleClick(event) {
   console.log('double click');
   const divText = document.createElement('li');
   divText.appendChild(document.createTextNode('double click'));
   window.info.appendChild(divText);


     console.group();  
   console.log('this element was double-clicked: ' + event.target.id);
   console.log(this.id);  
     console.log('');
   console.groupEnd();
 }

输出:enter image description here

答案 12 :(得分:-1)


  const toggle = () => {
      watchDouble += 1;
      setTimeout(()=>{
        if (watchDouble === 2) {
          console.log('double' + watchDouble)
        } else if (watchDouble === 1) {
          console.log("signle" + watchDouble)
        }
        watchDouble = 0
      },200);

  }