Tengo una pantalla táctil, si no obtiene el tiempo de presión del botón exactamente en Chrome, que es aproximadamente el 50% del tiempo para todos, el click() no se registra. Si presiona un botón durante demasiado tiempo, simplemente lo enfoca (sin disparar un evento de enfoque). Si presiona un botón demasiado rápido, lo ignora como un error. Así que actualmente la pantalla táctil es muy difícil de usar.
Aunque digo botón arriba, en realidad es una etiqueta para una entrada de radio, pero también ocurre en los botones.
Después de sumergirme en el problema, descubrí que no son eventos de enfoque, sino los siguientes eventos que se disparan dependiendo de cómo se presione el botón:
Código para imprimir los eventos:
['focus', 'contextmenu', 'touchstart', 'touchend', 'touchcancel', 'touchmove', 'click'].forEach( eventName => { document.addEventListener(eventName, event => console.log(eventName)) });Y estos son los tipos de prensas:
// Context menu (slightly longer press) touchstart contextmenu touchend // Touch move (not stead finger press)1 touchstart touchmove x N touchend // Touch move and context menu (combination of above) touchstart contextmenu touchmove touchend // Got it right, click occurred touchstart touchend clickLo intenté:
document.addEventListener('touchstart', event => { event.preventDefault(); event.target.click();} )Pero luego, si obtiene el clic correcto, disparará un segundo clic. Deseo convertir todos los escenarios anteriores en un solo clic.
Podría pasar una versión antirrebote (o acelerada) de su detector de eventos a todas las funciones de la siguiente manera:
// copied from https://davidwalsh.name/javascript-debounce-function function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; const myDebouncedFunction = debounce(myHandler, 100, true); document.addEventListener('touchstart', myDebouncedFunction); document.addEventListener('click', myDebouncedFunction); ... whatever other events you want to attach toAlternativamente, si usa lodash, puede usar su función de rebote incorporada.
Gracias a Tom, creé un rebote simplificado, si no hubo ningún clic dentro de los 100 ms después del evento del extremo táctil, luego disparé uno.
var touchedEl = null; document.addEventListener('click', () => touchedEl = null); document.addEventListener('touchend', event => {touchedEl=event.target; setTimeout(() => { touchedEl && touchedEl.click() }, 100)})