web-dev-qa-db-fra.com

Comment utiliser à la fois onclick et ondblclick sur un élément?

J'ai un élément sur ma page auquel je dois attacher des gestionnaires d'événements onclick et ondblclick. Lorsqu'un simple clic se produit, il devrait faire autre chose qu'un double-clic. Quand j'ai commencé à essayer de faire fonctionner cela, ma tête a commencé à tourner. Évidemment, onclick se déclenche toujours lorsque vous double-cliquez. J'ai donc essayé d'utiliser une structure basée sur le délai d'attente comme celle-ci ...

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

Mais j'ai eu des résultats incohérents (avec IE8). Cela fonctionnerait bien souvent, mais parfois j'obtiendrais l'alerte "Single" deux fois.

Est-ce que quelqu'un a déjà fait ça? Y a-t-il un moyen plus efficace?

24
Josh Stodola

Comme Matt, j'ai eu une bien meilleure expérience lorsque j'ai légèrement augmenté la valeur du délai d'attente. De plus, pour atténuer le problème du déclenchement d'un clic par deux fois (que je ne pouvais quand même pas reproduire avec le minuteur plus long), j'ai ajouté une ligne au gestionnaire de clic:

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

De cette façon, si click est déjà configuré pour se déclencher, il se dégagera pour éviter les alertes «uniques» en double.

23
Soldarnal

Si vous recevez 2 alertes, il semblerait que votre seuil de détection d'un double clic soit trop petit. Essayez d'augmenter de 150 à 300 ms. 

En outre, je ne suis pas sûr que vous ayez la garantie de l'ordre dans lequel clic et dblclick sont déclenchés. Ainsi, lorsque votre dblclick est déclenché, il supprime l’événement premier clic, mais s’il se déclenche avant le deuxième événement 'clic', ce deuxième événement se déclenchera tout seul et vous obtiendrez les deux un événement d’événement à double clic et un événement à un clic.

Je vois deux solutions possibles à ce problème potentiel:

1) Définissez un autre délai d'attente pour déclencher l'événement de double-clic. Marquez dans votre code que l'événement de double-clic est sur le point de se déclencher. Ensuite, lorsque le deuxième événement 'simple clic' est déclenché, il peut vérifier cet état et dire «oups, clic de dbl en attente, je ne ferai donc rien».

2) La deuxième option consiste à échanger vos fonctions cible en fonction des événements liés aux clics. Cela pourrait ressembler à quelque chose comme ça:

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

Fondamentalement, ce qui se passe ici, c'est que vous laissiez le délai initial que vous avez défini continuer. Il appellera toujours firingFunc (); La seule chose qui change est ce que firingFunc () désigne en réalité. Une fois le double clic détecté, il le définit sur doubleClick. Et puis, nous revenons toujours à singleClick une fois le délai expiré.

Nous avons également une variable "de déclenchement" dans ce fichier afin que nous sachions intercepter le deuxième événement en un seul clic.

Une autre alternative consiste à ignorer entièrement les événements dblclick, et à simplement le détecter avec les simples clics et le minuteur:

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

  }
}

Ceci n'est pas testé :)

10
Matt

Simple: 

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
5
Oleksandr Kyrpa
,   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);
        }
0
iamfreenoble

Petite solution 

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