web-dev-qa-db-fra.com

comment différencier les événements simple clic et les événements double clic?

J'ai un seul bouton dans li avec id "my_id". J'ai attaché des événements two jquery avec cet élément

1.

$("#my_id").click(function() { 
    alert('single click');
});

2.

$("#my_id").dblclick(function() {
    alert('double click');
});

Mais à chaque fois, il me donne le single click

87
user426795

Vous devez utiliser un délai d'attente pour vérifier s'il y a un autre clic après le premier clic.

Voici le tour :

// Author:  Jacek Becela
// Source:  http://Gist.github.com/399624
// License: MIT

jQuery.fn.single_double_click = function(single_click_callback, double_click_callback, timeout) {
  return this.each(function(){
    var clicks = 0, self = this;
    jQuery(this).click(function(event){
      clicks++;
      if (clicks == 1) {
        setTimeout(function(){
          if(clicks == 1) {
            single_click_callback.call(self, event);
          } else {
            double_click_callback.call(self, event);
          }
          clicks = 0;
        }, timeout || 300);
      }
    });
  });
}

Usage:

$("button").single_double_click(function () {
  alert("Try double-clicking me!")
}, function () {
  alert("Double click detected, I'm hiding")
  $(this).hide()
})
<button>Click Me!</button>

MODIFIER:

Comme indiqué ci-dessous, préférez utiliser l'événement dblclick natif: http://www.quirksmode.org/dom/events/click.html

Ou celui fourni par jQuery: http://api.jquery.com/dblclick/

53
Adrien Schuler

Le comportement de l'événement dblclick est expliqué à Quirksmode .

L'ordre des événements pour une dblclick est:

  1. souris vers le bas
  2. mouseup
  3. cliquez sur
  4. souris vers le bas
  5. mouseup
  6. cliquez sur
  7. dblclick

La seule exception à cette règle est (bien sûr) Internet Explorer avec leur ordre personnalisé de:

  1. souris vers le bas
  2. mouseup
  3. cliquez sur
  4. mouseup
  5. dblclick

Comme vous pouvez le constater, écouter les deux événements ensemble sur le même élément entraîne des appels supplémentaires vers votre gestionnaire click.

71
Ryan

Une fonction simple. Aucune requête ou autre cadre n'est requis. Passez vos fonctions en tant que paramètres

<div onclick="doubleclick(this, function(){alert('single')}, function(){alert('double')})">click me</div>
    <script>
        function doubleclick(el, onsingle, ondouble) {
            if (el.getAttribute("data-dblclick") == null) {
                el.setAttribute("data-dblclick", 1);
                setTimeout(function () {
                    if (el.getAttribute("data-dblclick") == 1) {
                        onsingle();
                    }
                    el.removeAttribute("data-dblclick");
                }, 300);
            } else {
                el.removeAttribute("data-dblclick");
                ondouble();
            }
        }
    </script>
20
Renzo Ciot

Je crains que le comportement dépend du navigateur:

Il est déconseillé de lier les gestionnaires à les événements click et dblclick pour le même élément. La séquence de les événements déclenchés varient selon le navigateur au navigateur, certains recevant deux cliquez sur les événements avant le dblclick et le les autres seulement un. Double-cliquez sur La sensibilité (durée maximale entre les clics .__ détectée sous forme de double clics .__) peut varier en fonction du système d'exploitation et navigateur, et est souvent configurable par l'utilisateur.

http://api.jquery.com/dblclick/

Lorsque vous exécutez votre code dans Firefox, alert () dans le gestionnaire click() vous empêche de cliquer une seconde fois. Si vous supprimez une telle alerte, vous obtenez les deux événements.

13
Álvaro González

Eh bien, pour double-cliquer (cliquer deux fois), vous devez d'abord cliquer une fois. Le gestionnaire click() se déclenche au premier clic et, comme l'alerte apparaît, vous ne pouvez pas effectuer le second clic pour déclencher le gestionnaire dblclick().

Modifiez vos gestionnaires pour qu'ils fassent autre chose qu'une alert() et vous verrez le comportement. (peut-être changer la couleur de fond de l'élément):

$("#my_id").click(function() { 
    $(this).css('backgroundColor', 'red')
});

$("#my_id").dblclick(function() {
    $(this).css('backgroundColor', 'green')
});
10
bradley.ayers

Aucune de ces réponses ne répondant à mes besoins, j'ai donc créé une solution inspirée du Gist posté par @AdrienSchuler. Utilisez cette solution uniquement lorsque vous souhaitez lier un simple clic ET un double-clic sur un élément. Sinon, je vous recommande d'utiliser les écouteurs natifs click et dblclick.

Ce sont les différences:

  • Vanillajs, Pas de dépendances
  • N'attendez pas la setTimeout pour gérer le gestionnaire de clic ou de double-clic
  • Lorsque vous double-cliquez dessus, le gestionnaire de clics est déclenché, puis le gestionnaire double-clic

Javascript:

function makeDoubleClick(doubleClickCallback, singleClickCallback) {
    var clicks = 0, timeout;
    return function() {
        clicks++;
        if (clicks == 1) {
            singleClickCallback && singleClickCallback.apply(this, arguments);
            timeout = setTimeout(function() { clicks = 0; }, 400);
        } else {
            timeout && clearTimeout(timeout);
            doubleClickCallback && doubleClickCallback.apply(this, arguments);
            clicks = 0;
        }
    };
}

Usage:

var singleClick = function(){ console.log('single click') };
var doubleClick = function(){ console.log('double click') };
element.addEventListener('click', makeDoubleClick(doubleClick, singleClick));

Ci-dessous est l'utilisation dans un jsfiddle, le bouton jQuery est le comportement de la réponse acceptée.

jsfiddle

6
A1rPun

Une autre solution simple de Vanilla basée sur la réponse A1rPun (voir son violon pour la solution jQuery et les deux sont dans celui-ci ).

Il semble que pour ne PAS déclencher un gestionnaire en un seul clic lorsque l'utilisateur double-clique dessus, le gestionnaire en un seul clic est nécessairement déclenché après un délai ...

var single = function(e){console.log('single')},
    double = function(e){console.log('double')};

var makeDoubleClick = function(e) {

  var clicks = 0,
      timeout;

  return function (e) {

    clicks++;

    if (clicks == 1) {
      timeout = setTimeout(function () {
        single(e);
        clicks = 0;
      }, 250);
    } else {
      clearTimeout(timeout);
      double(e);
      clicks = 0;
    }
  };
}
document.getElementById('btnVanilla').addEventListener('click', makeDoubleClick(), false);
5
jeum

Voici une alternative du code de jeum pour un nombre arbitraire d'événements:

 var multiClickHandler = function (handlers, delay) {
    var clicks = 0, timeout, delay = delay || 250;
    return function (e) {
      clicks++;
      clearTimeout(timeout);
      timeout = setTimeout(function () {
        if(handlers[clicks]) handlers[clicks](e);
        clicks = 0;
      }, delay);
    };
  }

  cy.on('click', 'node', multiClickHandler({
    1: function(e){console.log('single clicked ', e.cyTarget.id())},
    2: function(e){console.log('double clicked ', e.cyTarget.id())},
    3: function(e){console.log('triple clicked ', e.cyTarget.id())},
    4: function(e){console.log('quadro clicked ', e.cyTarget.id())},
    // ...
  }, 300));

Nécessaire pour un cytoscape.js app.

4
nex

Au lieu d'utiliser davantage d'états ad-hoc et setTimeout, il existe une propriété native appelée detail à laquelle vous pouvez accéder à partir de l'objet event!

element.onclick = event => {
   if (event.detail === 1) {
     // it was a single click
   } else if (event.detail === 2) {
     // it was a double click
   }
};

Les navigateurs modernes et même IE-9 le supporte :) 

Source: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail

3
kyw

J'ai écrit un simple plugin jQuery qui vous permet d'utiliser un événement personnalisé 'singleclick' pour différencier un simple clic d'un double-clic:

https://github.com/omriyariv/jquery-singleclick

$('#someDiv').on('singleclick', function(e) {
    // The event will be fired with a small delay.
    console.log('This is certainly a single-click');
}
3
omriyariv

Utilisez l'excellent plugin jQuery Sparkle. Le plugin vous donne la possibilité de détecter le premier et le dernier clic. Vous pouvez l'utiliser pour différencier clic et dblclick en détectant si un autre clic a été suivi du premier clic. 

Découvrez-le à http://balupton.com/sandbox/jquery-sparkle/demo/

3
Hussein

Comment différencier les simples clics et les doubles clics sur un même élément?

Si vous n'avez pas besoin de les mélanger, vous pouvez compter sur click et dblclick et chacun fera son travail correctement.

Un problème survient lorsque vous essayez de les mélanger: un événement dblclick déclenchera également un événement click. Vous devez donc déterminer si un simple clic est un clic "autonome" ou une partie d'un double-clic. .

De plus: vous ne devriez pas utiliser à la fois click et dblclick sur un même élément:

Il est déconseillé de lier les gestionnaires aux événements click et dblclick pour le même élément. La séquence d'événements déclenchés varie d'un navigateur à l'autre, certains recevant deux événements de clic avant le clic sur dblclick, d'autres un seul. La sensibilité du double-clic (le délai maximum entre les clics détecté comme un double-clic) peut varier en fonction du système d'exploitation et du navigateur, et est souvent configurable par l'utilisateur.
Source: https://api.jquery.com/dblclick/

Passons maintenant à la bonne nouvelle:

Vous pouvez utiliser la propriété detail de l'événement pour détecter le nombre de clics liés à l'événement. Cela rend les doubles clics dans click assez faciles à détecter.

Reste le problème de détecter les simples clics et de déterminer s’ils font ou non partie d’un double-clic. Pour cela, nous revenons à utiliser une minuterie et setTimeout.

En regroupant tout cela, en utilisant un attribut de données (pour éviter une variable globale) et sans avoir besoin de compter les clics, nous obtenons:

HTML:

<div class="clickit" style="font-size: 200%; margin: 2em; padding: 0.25em; background: orange;">Double click me</div>

<div id="log" style="background: #efefef;"></div>

JavaScript:

<script>
var clickTimeoutID;
$( document ).ready(function() {

    $( '.clickit' ).click( function( event ) {

        if ( event.originalEvent.detail === 1 ) {
            $( '#log' ).append( '(Event:) Single click event received.<br>' );

            /** Is this a true single click or it it a single click that's part of a double click?
             * The only way to find out is to wait it for either a specific amount of time or the `dblclick` event.
             **/
            clickTimeoutID = window.setTimeout(
                    function() {
                        $( '#log' ).append( 'USER BEHAVIOR: Single click detected.<br><br>' );
                    },
                    500 // how much time users have to perform the second click in a double click -- see accessibility note below.
                );

        } else if ( event.originalEvent.detail === 2 ) {
            $( '#log' ).append( '(Event:) Double click event received.<br>' );
            $( '#log' ).append( 'USER BEHAVIOR: Double click detected.<br>' );
            window.clearTimeout( clickTimeoutID ); // it's a dblclick, so cancel the single click behavior.
        } // triple, quadruple, etc. clicks are ignored.

    });

});
</script>

Démo:

JSfiddle


Remarques sur l'accessibilité et les vitesses de double-clic:

  • Comme le dit Wikipedia, "le délai maximum requis pour que deux clics consécutifs soient interprétés comme un double-clic n'est pas normalisé."
  • Aucun moyen de détecter la vitesse du double-clic du système dans le navigateur.
  • La valeur par défaut est 500 ms et la plage 100-900mms sous Windows ( source )
  • Pensez aux personnes handicapées qui définissent, dans les paramètres de leur système d’exploitation, la vitesse du double-clic sur sa vitesse la plus lente .
    • Si la vitesse du double-clic du système est inférieure à la valeur par défaut de 500 ms ci-dessus, le comportement du simple et du double-clic sera déclenché.
    • Soit, ne vous fiez pas à la combinaison de simples et doubles clics sur un seul et même élément.
    • Ou: ajoutez un paramètre dans les options pour pouvoir augmenter la valeur.

Il a fallu un certain temps pour trouver une solution satisfaisante, j'espère que cela aidera!

0
Fabien Snauwaert

J'aime éviter jquery (et d'autres bibliothèques de 90 à 140 Ko) et, comme noté par les navigateurs, gère d'abord onclick. Voici donc ce que j'ai fait sur un site Web que j'ai créé (cet exemple couvre également l'obtention d'un emplacement cliqué x x).

clicksNow-0; //global js, owell

function notify2(e, right) {  // called from onclick= and oncontextmenu= (rc)
var x,y,xx,yy;
var ele = document.getElementById('wrap');  
    // offset fixed parent for local win x y
var xxx= ele.offsetLeft;
var yyy= ele.offsetTop;

//NScape
if (document.layers || document.getElementById&&!document.all) {
    xx= e.pageX;
    yy= e.pageY;
} else {
    xx= e.clientX;
    yy= e.clientY;
}
x=xx-xxx;
y=yy-yyy;

clicksNow++;
    // 200 (2/10ths a sec) is about a low as i seem to be able to go
setTimeout( "processClick( " + right + " , " + x + " , " + y + ")", 200);
}

function processClick(right, x, y) {
if (clicksNow==0) return; // already processed as dblclick
if (clicksNow==2) alert('dbl');
clicksNow=0;
    ... handle, etc ...
}

j'espère que cela pourra aider

0
dako