Que faire si les événements" mousemove "et" click " se déclenchent simultanément?

Je ne sais pas si c'est seulementChrome problème (ne peut pas vérifier maintenant), cependant essayons le morceau de code suivant, où nous lions deux événements à un élément:

$("div").on({
    mousemove: function(e) {
        console.log("move");
    },
    click: function(e) {
        console.log("click");
    }
});

Si nous essayons de cliquer sur l'élément, nous trouverons que pour une raison quelconque mousemove l'événement se déclenche immédiatement après le clic, donc dans la console nous avons:

>> ...
>> click
>> move

DÉMO: http://jsfiddle.net/gKqVt/

Notez que les événements mousedown et mouseup fonctionnent selon le même scénario.

J'en ai vu beaucoup questions sur SO sur le même problème, mais aucun (dans ma recherche) n'a donné l'idée simple de ce qu'il faut faire pour déclencher l'événement click seulement.

22
demandé sur VisioN 2013-01-26 20:07:44

6 réponses

Ce comportement est étrange, et il ne semble pas se produire universellement (arrive dans Chrome / IE pour moi, mais pas FFX). Je pense que vous n'avez pas eu une réponse directe parce qu'il n'y en a pas vraiment.

Il est possible que la souris soit très légèrement déplacée par l'action de clic, mais ce n'est probablement pas le cas. Pourrait juste être une bizarrerie de navigateur. Ceux-ci ne semblent même pas être le même événement puisque stopImmediatePropagation dans click n'empêche pas mousemove de tirer. Si vous concentrez l'élément et appuyez sur un bouton du clavier, il sera en fait déclencheur click et seulement click.

Comme c'est tellement bizarre, il semble que la seule façon de le faire est le temps. Même si c'est un kludge, je remarque que click arrive une milliseconde avant mousemove, ainsi, vous pouvez vous rapprocher en comparant l'horodatage de clic + 2 ( ou 10):

mousemove: function(e) {
    if ($(this).data('lastClick') + 10 < e.timeStamp) {

Http://jsfiddle.net/gKqVt/3/

C'est très spécifique, cependant. Vous devriez envisager de ne pas avoir de comportement qui se produit immédiatement sur mousemove comme il est si fréquent.

3
répondu Explosion Pills 2013-01-26 16:23:43

Mousemove semble être lié à chaque action de la souris dans Chrome, alors stockez la position de la souris chaque fois que la souris "se déplace "et vérifiez-la par rapport à la position précédente de la souris pour valider qu'elle a effectivement"bougé"..

var currentPos=[];
$("div").on({
    mousemove: function(e) {
        if (e.pageX!==currentPos[0] && e.pageY !==currentPos[1]){
            currentPos=[e.pageX,e.pageY];
        this.innerHTML = "Event: " + e.type;
        console.log("move");
        }
    },
    click: function(e) {
        this.innerHTML = "Event: " + e.type;
        console.log("click");
    }
});

Démo | Source

8
répondu extramaster 2013-01-26 16:50:19

Cela semble être un bug dans Chrome qui a été signalé pour la première fois en novembre, et reste ouvert.

Chrome Question 161464

Si vous ciblez Chrome spécifiquement, il peut être utile de comparer les horodatages d'événements pour le contourner (en utilisant un temps delta minimum comme suggéré par @ExplosionPills. Mais si vous cherchez un comportement général, il semble que vous feriez mieux de les traiter comme des événements séparés, car dans tous les navigateurs sauf chrome (et peut-être Safari? le bug est étiqueté comme webkit-core), ils seront en fait des événements distincts.

7
répondu Ben McCormick 2013-01-26 16:32:39

Pourquoi ne pas simplement vérifier que la souris a vraiment bougé ou pas comme ci-dessous:

function onMouseDown (e) {
    mouseDown = { x: e.clientX, y: e.clientY };
    console.log("click");
}

function onMouseMove (e) {
    //To check that did mouse really move or not
    if ( e.clientX !== mouseDown.x || e.clientY !== mouseDown.y) {
        console.log("move");
    }
}

DÉMO DE VIOLON

(je pense que c'est toujours correct dans tous les navigateurs)

1
répondu Ben Mack 2015-07-05 03:30:16

var a,b,c,d;
  $(".prd img").on({
	mousedown: function(e){
	  a= e.clientX, b= e.clientY;
	},
	mouseup: function(e){
	  c= e.clientX, d= e.clientY;
	  if(a==c&&b==d){
	    console.log('clicked');
	  }
	}
  });

Essayez ceci. Ce un travail correct.

0
répondu Hanul Choi 2016-08-04 09:38:56

J'ai remarqué ce comportement quand j'avais besoin de différencier entre mousedown et mouseup sans glisser entre les deux et mousedown et mouseup avec glisser entre eux, la solution que j'ai utilisée est la suivante:

var div = $('#clickablediv');
var mouseDown = false;
var isDragging = 0;
div.mousedown(function () {
   isDragging = false;
       mouseDown = true;
   }).mousemove(function () {
       if (mouseDown) isDragging++;
   }).mouseup(function () {
       mouseDown = false;
       var wasDragging = isDragging;
       isDragging = 0;
       if (!wasDragging || wasDragging<=1) {
           console.log('there was no dragging');
       }
   });

Quand je l'ai essayé, j'ai remarqué que periodacaly un simple clic rend "isDragging" égal à 3 mais pas très fréquemment

0
répondu AZNI HAMZA 2016-11-27 13:15:18