Как использовать как onclick, так и ondblclick для элемента?
У меня есть элемент на моей странице, для которого мне нужно привязать обработчики событий 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). Он работал бы много раз, но иногда я получал предупреждение "Single" два раза.
Кто-нибудь сделал это раньше? Есть ли более эффективный способ?
Ответы
Ответ 1
Как и Мэтт, у меня был намного лучший опыт, когда я немного увеличил значение тайм-аута. Кроме того, чтобы смягчить проблему однократного нажатия на один щелчок (что в любом случае я не смог воспроизвести с более высоким таймером), я добавил строку в обработчик одиночного клика:
el.onclick = function() {
if (timer) clearTimeout(timer);
timer = setTimeout(function() { alert('Single'); }, 250);
}
Таким образом, если клик уже установлен, он очистится, чтобы избежать дублирования предупреждений "Single".
Ответ 2
Если вы получаете 2 предупреждения, кажется, ваш порог для обнаружения двойного щелчка слишком мал. Попробуйте увеличить от 150 до 300 мс.
Кроме того - я не уверен, что вам гарантирован порядок, в котором стреляли клики и dblclick. Итак, когда ваш dblclick запущен, он очищает событие первого клика, но если он срабатывает перед вторым событием 'click', это второе событие по-прежнему запускается само по себе, и вы получите как событие двойного щелчка стрельба и однократная стрельба.
Я вижу два возможных решения этой потенциальной проблемы:
1) Установите другой тайм-аут для фактического запуска события двойного щелчка. Отметьте в своем коде, что событие двойного щелчка собирается запустить. Затем, когда срабатывает событие "один клик", он может проверить это состояние и сказать "oops, dbl click pending, поэтому я ничего не сделаю"
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(). Как только двойной клик обнаружен, он устанавливает его в doubleClick. И тогда мы всегда возвращаемся к 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
Простой:
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
Небольшое исправление
if(typeof dbtimer != "undefined"){
dbclearTimeout(timer);
timer = undefined;
//double click
}else{
dbtimer = setTimeout(function() {
dbtimer = undefined;
//single click
}, 250);
}
Ответ 5
, 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);
}
Ответ 6
Я случайно обнаружил, что это работает (в случае с Bing Maps):
pushpin.clickTimer = -1;
Microsoft.Maps.Events.addHandler(pushpin, 'click', (pushpin) {
return function () {
if (pushpin.clickTimer == -1) {
pushpin.clickTimer = setTimeout((function (pushpin) {
return function () {
alert('Single Clic!');
pushpin.clickTimer = -1;
// single click handle code here
}
}(pushpin)), 300);
}
}
}(pushpin)));
Microsoft.Maps.Events.addHandler(pushpin, 'dblclick', (function (pushpin) {
return function () {
alert('Double Click!');
clearTimeout(pushpin.clickTimer);
pushpin.clickTimer = -1;
// double click handle here
}
}(pushpin)));
Похоже, что событие click маскирует событие dblclick, и это использование очищает его, когда мы добавляем таймаут. Так что, надеюсь, это будет работать и со случаями, не относящимися к Bing Maps, после небольшой адаптации, но я не пробовал.