javascript-events - eventos - touch events javascript library
Evitar eventos de emulación de mouse(es decir, hacer clic) desde eventos táctiles en Mobile Safari/iPhone usando Javascript (5)
Al hacer una aplicación de una sola página de JavaScript con elementos DOM interactivos, descubrí que la mouseover-mousemove-mousedown-mouseup-click
" mouseover-mousemove-mousedown-mouseup-click
" pasa de una vez a otra después de la secuencia de eventos " touchstart-touchmove-touchend
".
También descubrí que es posible evitar que ocurran los eventos " mouse*-click
" haciendo un " event.preventDefault()
" durante el evento touchstart
, pero solo en ese momento, y no durante el touchmove
y el touchend
. Este es un diseño extraño, porque no es posible saber durante el touchstart
si el usuario tiene la touchstart
de arrastrar o deslizar o simplemente tocar / hacer clic en el elemento.
Terminé configurando una bandera "ignore_next_click" en algún lugar vinculada a una marca de tiempo, pero obviamente esto no es muy limpio.
¿Alguien sabe de una mejor manera de hacer esto, o nos falta algo?
Tenga en cuenta que si bien un "clic" puede reconocerse como una touchstart-touchend
" touchstart-touchend
" (es decir, no " touchmove
"), hay ciertas cosas, como el enfoque de entrada del teclado, que solo pueden ocurrir durante un evento de click
apropiado.
Envolver el código del mouse solo en una función Window.matchesMedia es la forma más limpia que encontré.
if (window.matchMedia(''(hover: hover), (any-hover: hover), (-moz-touch-enabled: 0)'').matches) {
el.addEventListener(''mouseover'', ev => {
// mouse handler, no simulated hover
}
}
Esto funciona para evitar los desplazamientos simulados, pero probablemente también evitará los clics simulados.
Nota: se requiere una parte habilitada para tocar conmoz en Firefox a partir de la versión 58.
He hecho una solución yo mismo, ya que no he encontrado una solución suficiente en otro lugar:
var isTouch = (''ontouchstart'' in window);
function kill(type){
window.document.body.addEventListener(type, function(e){
e.preventDefault();
e.stopPropagation();
return false;
}, true);
}
if( isTouch ){
kill(''mousedown'');
kill(''mouseup'');
kill(''click'');
kill(''mousemove'');
}
La comprobación de isTouch
permite que las cosas funcionen normalmente en los dispositivos de entrada de ratón, pero elimina los eventos emulados en Safari / iOS. El truco es usar useCapture = true
en la llamada a addEventListener
para que recojamos todos los eventos del mouse en la página sin hackear el código en toda la aplicación web. Consulte los documentos para la función aquí: https://developer.mozilla.org/en-US/docs/DOM/EventTarget.addEventListener?redirectlocale=en-US&redirectslug=DOM%2Felement.addEventListener
Editar:
Ahora que las bibliotecas para manejar este problema son mejores, puede usar algo como Fastclick como alternativa ( https://github.com/ftlabs/fastclick ).
Me he encontrado con problemas similares al hacer aplicaciones HTML5 / JS multiplataforma. La única respuesta real para mí fue prevenir por defecto en los eventos táctiles, y realmente administrar los estados táctiles y disparar los eventos de clic, arrastre, etc. por mi cuenta de acuerdo con mi lógica. Esto suena mucho más desalentador de lo que realmente es, pero los eventos de clic / mouse imitados funcionan perfectamente en la mayoría de los navegadores móviles.
Haga clic y la secuencia adicional del mouse estará allí para su conveniencia (y compatibilidad). Mi regla general: si es por su conveniencia, pero es inconveniente, es mejor que lo mate.
En cuanto a los cuadros de entrada, solo necesitan los eventos touchend. He eliminado los eventos de clic / mouse y todavía he podido permitir que los navegadores móviles respondan correctamente a los toques en las entradas. Si todavía te está dando problemas, puedes modificar el controlador de eventos para solo suprimir eventos en los no-inputs:
function touchHandler(event) {
var shouldIgnore = event.target != null
&& ( event.target.tagName.toLowerCase() == "input" || event.target.tagName.toLowerCase() == "textarea" );
if(!shouldIgnore) e.preventDefault();
}
Si tiene que admitir dispositivos compatibles con mouse y touch, otra solución es usar un detector de eventos de captura que detenga todos los eventos de mouse que ocurran ya sea
- dentro de un retraso después del evento táctil
- en la misma posición que el evento táctil
- en el mismo elemento objetivo como el evento táctil
La información (hora, posición o elemento objetivo) del evento táctil puede grabarse en otro oyente de eventos de captura.
La creación de botones rápidos para aplicaciones web móviles tiene su solución al problema.
Además, tenga en cuenta que al usar IE10, prevenirDefault () no detiene los eventos del mouse fantasma / sintético / emulado después de un evento MSPointerDown, por lo que una verdadera solución entre navegadores es más difícil.