Предотвращение призрачного щелчка при привязке "touchstart" и 'click'
Я разрабатываю приложение, тестируя свой рабочий стол и мобильный. Я пытаюсь исправить эти медленные нажатия кнопок на мобильном устройстве и только что узнал о различии между touchstart и щелчком.
Итак, я связал свои кнопки с jquery, чтобы выполнить оба touchstart и щелкнуть так:
$('.button').on('touchstart click', function(){
});
Теперь приложение работает немного лучше на телефоне. Тем не менее, он выполняет сенсорный щелчок, а затем обычный клик, то есть потенциально двойной клик, или когда приходит следующий слайд, он нажимает на что-то там. В моем случае появляется форма, и поле ввода, которое появляется в пространстве, где была нажата кнопка, выбрано. Призрачный клик.
Как я могу сказать своей функции, что если есть прикосновение, игнорируйте клик?
Или еще лучше, есть ли способ сказать jquery просто признать все "клики" как прикосновения?
Я бы удалил привязку 'click', но тогда я не могу точно протестировать в своей среде рабочего стола так легко.
Ответы
Ответ 1
Если вы хотите делать конкретные вещи для разных типов событий, используйте e.type
$('.button').on('touchstart click', function(e) {
e.preventDefault(); //prevent default behavior
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
Ответ 2
Touchstart должен произойти до щелчка, поэтому я удаляю обработчик кликов, если событие имеет тип touchstart. Кажется, это хорошо работает для моих целей:
$('.do-popdown').on('click touchstart', handlePopdown);
function handlePopdown(e){
if(e.type == 'touchstart') {
$('.do-popdown').off('click', handlePopdown).click(function(e){
// do nothing
e.stopPropagation();
e.preventDefault();
return false;
});
}
// do my handling...
// and nothing else:
e.stopPropagation();
e.preventDefault();
return false;
}
e.stopPropagation(); e.preventDefault(); return false;
может быть излишним, но я использую его для множества различных элементов (<a>
, <div>
, <span>
, <button>
, & c.), и это соответствует моим обычным потребностям.
EDIT:. Более общий (лучший?) подход - создать нечто похожее на знакомое связующее событие .click()
:
jQuery.fn.extend({
clickOrTouch: function(handler) {
return this.each(function() {
var event = ('ontouchstart' in document) ? 'touchstart' : 'click';
$(this).on(event, handler);
});
}
});
Таким образом, к выбранному элементу (элементам) прикрепляется только соответствующее событие.
Я предполагаю, что более "правильное" имя будет .touchstartOrClick()
, но поскольку это более или менее замена для .click()
, я решил начать имя с click
.
Это можно использовать так же, как .click()
. Например, поставьте button
внутри div
и запустите:
$('button').clickOrTouch(doSomething);
$('div').clickOrTouch(doSomething);
function doSomething(e) {
$('body').append(this.tagName + ' ' + e.type + '<br>');
e.stopPropagation();
}
В зависимости от того, как он запускается, отобразится "DIV click" или "BUTTON touchstart". Если это используется для ссылки, добавьте e.preventDefault()
, если это необходимо в обработчик.
Ответ 3
Этот код от @Krishna не работает для меня:
$('.button').on('touchstart click', function(e) {
e.stopPropagation(); //stops propagation
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
Но этот должен работать, как первоначально предлагал @Slashback.
$('.button').on('touchstart click', function(e) {
e.preventDefault();
if(e.type == "touchstart") {
// Handle touchstart event.
} else if(e.type == "click") {
// Handle click event.
}
});
.preventDefault() работал только для меня, а не .stopPropagation(). Мне тоже не нужно делать переполнения.
Ответ 4
Я использую PhoneGap. Это может быть полезно:
function longTapEvent(id, longTapFun) {
$(id).click(function() {
longTapFun();
return;
})
$(id).unbind("touchstart");
$(id).bind("touchstart", function() {
//do sth...
});
$(id).unbind("touchend");
$(id).bind("touchend", function() {
//do sth...
});
}
Ответ 5
В моих проектах я использую следующее:
$('.button').on('touchstart', function() {
var thisButton = $(this);
if(!thisButton.hasClass('disabled')) {
thisButton.addClass('disabled'); //add class disabled to prevent double execution
............rest of code
window.setTimeout(function () {
thisButton.removeClass('disabled'); //remove class disalbed after 300ms
}, 300);
});
Надеюсь, это поможет кому-то.
Ответ 6
Использование data-tap-disabled = "true" на элементе решает мою проблему.
http://ionicframework.com/docs/api/page/tap/
Ответ 7
Вы можете обнаружить щелчок и избежать текущего срабатывания функции, если предыдущий огонь не был кликом (т.е. был прикосновением или чем-то еще) - в vanilla js:
buttonx.addEventListener('touchend',clicktap);
buttonx.addEventListener('click',clicktap);
function clicktap(e) {
var c = e.type.includes("click"); // or "mouse" if using "mousedown"
if (c && (this.wastouched)) return this.wastouched = 0;
this.wastouched = !c;
// ..run things..
}
Ответ 8
Это мое собственное домашнее решение, пожалуйста, критикуйте его! Спасибо!
var price_button = $(evt.target).closest('.price-button')
if(price_button.length) {
price_button.on('mouseleave', function() {
$(this).removeAttr('data-touched')
})
if(evt.type == 'touchstart') {
jQuery.touch_start = true
if(!price_button.attr('data-touched')) {
price_button.attr('data-touched', 1)
return
}
price_button.attr('data-touched', 2)
}
if(evt.type == 'click') {
if(price_button.attr('data-touched'))
return
}
bag.add($(evt.target).closest('.price-button'))
return true
}