Прослушивание mousedown AND touchstart на устройствах, которые используют сенсорный экран и мышь (например, Surface)
Итак, я столкнулся с интересной проблемой при работе с веб-приложением для Microsoft Surface.
Я хочу добавить прослушиватели событий, когда пользователь взаимодействует с элементом DOM. Теперь я могу сделать:
if ('ontouchstart' in document.documentElement) {
//Attach code for touch event listeners
document.addEventListener("touchstart" myFunc, false);
} else {
//Attach code for mouse event listeners
document.addEventListener("mousedown" myFunc, false);
}
Если у устройства не было ввода мыши, эта проблема была бы простой, и вышеуказанный код работал бы очень хорошо. Но на поверхности (и на многих новых компьютерах с Windows 8) есть BOTH сенсорный и мышь. Таким образом, приведенный выше код будет работать только тогда, когда пользователь коснется устройства. Слушатели событий мыши никогда не будут прикреплены.
Итак, я подумал, что я мог бы это сделать:
if ('ontouchstart' in document.documentElement) {
//Attach code for touch event listeners
document.addEventListener("touchstart" myFunc, false);
}
//Always attach code for mouse event listeners
document.addEventListener("mousedown" myFunc, false);
Устройства, которые не поддерживают touch, не будут привязаны к событиям, но устройство, использующее touch, зарегистрирует свои обработчики. Проблема с этим заключается в том, что myFunc()
будет вызываться дважды на сенсорном устройстве:
-
myFunc()
будет срабатывать при поднятии "touchstart".
- Поскольку сенсорные браузеры обычно проходят через сенсорный экран цикла → touchmove → touchhend → mousedown → mousemove → mouseup → click,
myFunc()
будут снова вызваны в "mousedown"
Я рассмотрел добавление кода в myFunc()
, чтобы он вызывал e.preventDefault()
, но, похоже, он также блокирует touchhend, а также mousedown/mousemove/mouseup на некоторых браузерах (ссылка).
Мне не нравится делать useragent sniffers, но кажется, что сенсорные браузеры имеют вариации в том, как реализованы события касания.
Мне, должно быть, что-то не хватает, потому что кажется, что эти реализации JavaScript были решены с возможностью браузера, поддерживающего мышь и прикосновение!
Ответы
Ответ 1
Для Windows 8 вы можете использовать событие "MSPointerDown".
if (window.navigator.msPointerEnabled) {
document.addEventListener("MSPointerDown" myFunc, false);
}
Также добавьте в свой стиль следующее:
html {
-ms-touch-action: none; /* Direct all pointer events to JavaScript code. */
}
Подробнее см. http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx.
Ответ 2
Внутри myFunc проверьте тип события. Если он коснется, тогда сделайте e.stopPropagation()
.
function myFunc(e) {
if (e.type === 'touchstart') {
e.stopPropagation();
}
//the rest of your code here
}
Ответ 3
Редакция:
Если вы используете jQuery, вы сможете сделать вот так:
var clickEventType=((document.ontouchstart!==null)?'mousedown':'touchstart');
$("a").bind(clickEventType, function() {
//Do something
});
Это приведет к срабатыванию только одного из событий привязки.
Найдено здесь: Как привязать события "touchstart" и "click" , но не отвечать на оба: