【问题标题】:How to use both onclick and ondblclick on an element?如何在元素上同时使用 onclick 和 ondblclick?
【发布时间】:2010-12-05 11:40:12
【问题描述】:

我的页面上有一个元素,我需要将 onclick 和 ondblclick 事件处理程序附加到该元素。当单击发生时,它应该执行与双击不同的操作。当我第一次开始尝试完成这项工作时,我的头开始旋转。显然,onclick 总是会在你双击时触发。所以我尝试使用这样的基于超时的结构......

window.onload = function() {
  var timer;
  var el = document.getElementById('testButton');

  el.onclick = function() {
    timer = setTimeout(function() { alert('Single'); }, 150);        
  }

  el.ondblclick = function() {
    clearTimeout(timer);
    alert('Double');
  }
}

但是我得到了不一致的结果(使用 IE8)。它可以正常工作很多次,但有时我会收到两次“Single”警报。

以前有人做过吗?有没有更有效的方法?

【问题讨论】:

  • 当您收到单击警报时,是始终成对出现,还是有时只收到一个警报?

标签: javascript double-click


【解决方案1】:

如果您收到 2 个警报,则您检测双击的阈值似乎太小。尝试增加 150 到 300 毫秒。

另外 - 我不确定你是否能保证 click 和 dblclick 的触发顺序。因此,当您的 dblclick 被触发时,它会清除 first click 事件,但如果它在第二个“click”事件之前触发,则第二个事件仍将自行触发,您将结束包括双击事件触发和单击事件触发。

我看到这个潜在问题的两种可能的解决方案:

1) 为实际触发双击事件设置另一个超时。在您的代码中标记双击事件即将触发。然后,当第二个“单击”事件触发时,它可以检查此状态,并说“哎呀,dbl 点击挂起,所以我什么都不做”

2) 第二种选择是根据点击事件交换目标函数。它可能看起来像这样:

window.onload = function() {
  var timer;
  var el = document.getElementById('testButton');

  var firing = false;
  var singleClick = function(){
    alert('Single');
  };

  var doubleClick = function(){ 
    alert('Double');
  };

  var firingFunc = singleClick;

  el.onclick = function() {
    // Detect the 2nd single click event, so we can stop it
    if(firing) 
      return;

    firing = true;
    timer = setTimeout(function() { 
       firingFunc(); 

       // Always revert back to singleClick firing function
       firingFunc = singleClick;
       firing = false;
    }, 150);

  }

  el.ondblclick = function() {
    firingFunc = doubleClick; 
    // Now, when the original timeout of your single click finishes, 
    // firingFunc will be pointing to your doubleClick handler        
  }
}

基本上这里发生的事情是让您设置的原始超时继续。它总是会调用 fireFunc();唯一改变的是 fireFunc() 实际指向的内容。一旦检测到双击,它就会将其设置为 doubleClick。然后,一旦超时到期,我们总是会恢复为 singleClick。

我们还有一个“触发”变量,所以我们知道要拦截第二次单击事件。

另一种选择是完全忽略 dblclick 事件,只需通过单击和计时器来检测它:

window.onload = function() {
  var timer;
  var el = document.getElementById('testButton');

  var firing = false;
  var singleClick = function(){
    alert('Single');
  };

  var doubleClick = function(){ 
    alert('Double');
  };

  var firingFunc = singleClick;

  el.onclick = function() {
    // Detect the 2nd single click event, so we can set it to doubleClick
    if(firing){
      firingFunc = doubleClick; 
      return;
    }

    firing = true;
    timer = setTimeout(function() { 
       firingFunc(); 

       // Always revert back to singleClick firing function
       firingFunc = singleClick;
       firing = false;
    }, 150);

  }
}

这是未经测试的:)

【讨论】:

  • 第一个代码示例对我有用,但第二个遇到了问题。
【解决方案2】:

和 Matt 一样,我稍微增加了超时值,我的体验要好得多。此外,为了缓解单击触发两次的问题(无论如何我都无法使用更高的计时器重现),我在单击处理程序中添加了一行:

el.onclick = function() {
    if (timer) clearTimeout(timer);
    timer = setTimeout(function() { alert('Single'); }, 250);        
}

这样,如果 click 已经设置为触发,它会自行清除以避免重复的“Single”警报。

【讨论】:

  • 哇,我喜欢你的简单回答。我想您可以将 dblclick 侦听器全部删除,并将您的 IF 块替换为: { clearTimeout(timer); myDoubleClickHandler();返回; }
【解决方案3】:

简单:

obj.onclick=function(e){
   if(obj.timerID){
          clearTimeout(obj.timerID);
          obj.timerID=null;
          console.log("double")
         }
       else{
          obj.timerID=setTimeout(function(){
                                            obj.timerID=null;
                                            console.log("single")
                                            },250)}
}//onclick

【讨论】:

    【解决方案4】:

    小修复

           if(typeof dbtimer != "undefined"){
                dbclearTimeout(timer);
                timer = undefined;
                //double click
            }else{
                dbtimer = setTimeout(function() { 
                dbtimer = undefined;
                //single click
                }, 250);
            }
    

    【讨论】:

      【解决方案5】:
      ,   cellclick   :   
              function(){
                  setTimeout(function(){
                      if (this.dblclickchk) return;
                      setTimeout(function(){
                          click event......                   
                      },100);
                  },500);
              }
      
      ,   celldblclick    :   
              function(){
                  setTimeout(function(){
                      this.dblclickchk    =   true;
                      setTimeout(function(){
                                                dblclick event.....
                      },100);
                      setTimeout(function(){
                          this.dblclickchk = false;
                      },3000);
                  },1);
              }
      

      【讨论】:

      • 目前尚不清楚这如何回答这个问题。一个好的答案也应该对代码提供一些解释。鉴于 this 是一个对象并且以逗号开头,因此很难看出应该如何处理它。
      【解决方案6】:

      我偶然发现这是可行的(Bing Maps 就是这种情况):

                       pushpin.clickTimer = -1;
                        Microsoft.Maps.Events.addHandler(pushpin, 'click', (pushpin) {
                          return function () {
                              if (pushpin.clickTimer == -1) {
                                  pushpin.clickTimer = setTimeout((function (pushpin) {
                                      return function () {
                                          alert('Single Clic!');
                                          pushpin.clickTimer = -1;
                                          // single click handle code here
                                      }
                                  }(pushpin)), 300);
                              }
                          }
                      }(pushpin)));
                      Microsoft.Maps.Events.addHandler(pushpin, 'dblclick', (function (pushpin) {
                          return function () {
                              alert('Double Click!');
                              clearTimeout(pushpin.clickTimer);
                              pushpin.clickTimer = -1;
                              // double click handle here
                          }
                      }(pushpin)));
      

      看起来 click 事件掩盖了 dblclick 事件,当我们添加超时时,这种用法正在清除它。所以,希望这也适用于非 Bing 地图案例,经过轻微调整,但我没有尝试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-20
        • 2013-10-23
        • 1970-01-01
        • 1970-01-01
        • 2022-11-01
        • 2021-11-10
        • 1970-01-01
        相关资源
        最近更新 更多