代码之家  ›  专栏  ›  技术社区  ›  Josh Stodola

如何在元素上同时使用onclick和ondblclick?

  •  24
  • Josh Stodola  · 技术社区  · 15 年前

    我的页面上有一个元素,需要将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)。它可以正常工作很多次,但有时我会得到两次“单一”警报。

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

    5 回复  |  直到 8 年前
        1
  •  23
  •   Soldarnal    15 年前

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

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

    这样,如果单击已设置为“激发”,它将自动清除以避免重复的“单一”警报。

        2
  •  10
  •   Matt    15 年前

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

    另外-我不确定您是否被保证单击和dblclick的触发顺序。所以,当你的dblclick被解雇时,它会清除掉 第一 单击事件,但如果它在第二个“单击”事件之前激发,则第二个事件仍将自己激发,最后将同时触发双击事件激发和单击事件激发。

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

    1)为实际触发双击事件设置另一个超时。在代码中标记双击事件即将触发。然后,当第二个“单击”事件触发时,它可以检查此状态,并说“oops,dbl click pending,so I'll do nothing”

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

    基本上,这里发生的是让您设置的原始超时继续进行。它总是调用firingfunc();唯一改变的是firingfunc()实际指向的。一旦检测到双击,就会将其设置为双击。然后,一旦超时结束,我们总是返回到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);
    
      }
    }
    

    这是未测试的:)

        3
  •  5
  •   Oleksandr Kyrpa    11 年前

    简单的:

    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
  •  0
  •   Marnick Hartgers    9 年前

    小修理

           if(typeof dbtimer != "undefined"){
                dbclearTimeout(timer);
                timer = undefined;
                //double click
            }else{
                dbtimer = setTimeout(function() { 
                dbtimer = undefined;
                //single click
                }, 250);
            }
    
        5
  •  0
  •   iamfreenoble    8 年前
    ,   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);
            }