Что делать, если одновременно срабатывают события "mousemove" и "click"?
Я не знаю, является ли это проблемой только Chrome (не могу проверить сейчас), однако пусть попробуй следующий фрагмент кода, где мы привязываем два события к некоторому элементу:
$("div").on({
mousemove: function(e) {
console.log("move");
},
click: function(e) {
console.log("click");
}
});
Если мы попытаемся щелкнуть элемент, мы обнаружим, что по какой-то причине событие mousemove
срабатывает сразу после клика, поэтому в консоли мы имеем:
>> ...
>> click
>> move
DEMO: http://jsfiddle.net/gKqVt/
Обратите внимание, что события mousedown
и mouseup
работают по тому же сценарию.
Я видел много вопросов о SO по той же проблеме, но ни один (в моем поиске) не дал простой идеи, что делать, чтобы только запустить событие click
.
Ответы
Ответ 1
Такое поведение является нечетным, и, похоже, оно не происходит повсеместно (это происходит в Chrome/IE для меня, но не для FFX). Я думаю, что ты не получил прямого ответа, потому что на самом деле этого нет.
Возможно, что мышь слегка движется нажатием кнопки, но это, вероятно, не так. Это может быть просто причуда браузера. Это даже не похоже на то же событие, поскольку stopImmediatePropagation
в click
не останавливает mousemove
от стрельбы. Если вы сфокусируете элемент и нажмете кнопку клавиатуры, он фактически вызовет click
и только click
.
Так как это так странно, кажется, что единственный способ справиться с этим - это времена. Как бы то ни было, я заметил, что click
происходит за миллисекунду до mousemove
, поэтому вы можете приблизиться, сравнив отметку времени + 2 (или 10):
mousemove: function(e) {
if ($(this).data('lastClick') + 10 < e.timeStamp) {
http://jsfiddle.net/gKqVt/3/
Это очень специфично. Вы должны подумать о том, что поведение, которое происходит сразу на mousemove, происходит так часто.
Ответ 2
Mousemove, похоже, привязан к каждому действию мыши в Chrome, поэтому сохраняйте позицию мыши каждый раз, когда мышь "перемещается" и проверяет ее против предыдущей позиции мыши, чтобы подтвердить, что она действительно "перемещена".
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");
}
});
Демо | Источник
Ответ 3
Это, кажется, ошибка в Chrome, о которой впервые сообщалось в ноябре, и остается открытым.
Chromium Issue 161464
Если вы настроили таргетинг на Chrome, то, возможно, стоит сравнить временные метки событий, чтобы обойти его (используя некоторое минимальное время дельта как предложено @ExplosionPills. Но если вы ищете общее поведение, кажется, что вам лучше рассматривая их как отдельные события, потому что в каждом браузере, но хром (и, возможно, Safari? ошибка помечена как webkit-core), они на самом деле будут отдельными событиями.
Ответ 4
Почему бы просто не проверить, действительно ли мышь двигалась или нет, как показано ниже:
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");
}
}
FIDDLE DEMO
(я думаю, что он все равно будет исправлен во всех браузерах)
Ответ 5
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');
}
}
});
Ответ 6
Я заметил это поведение, когда мне нужно было различать между mousedown и mouseup, не перетаскивая между ними и mousedown и mouseup с перетаскиванием между ними, решение, которое я использовал, выглядит следующим образом:
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');
}
});
когда я попробовал это, я заметил, что период простоя простого щелчка делает "isDragging" равным 3, но не очень часто.