working not long libreria hold eventos detectar custom javascript jquery ios click touch

javascript - not - long click jquery



JavaScript touchend versus dilema de clic (5)

Estoy trabajando en algunas UI de JavaScript y usando muchos eventos táctiles como ''touchend'' para una mejor respuesta en dispositivos táctiles. Sin embargo, hay algunos problemas lógicos que me están molestando ...

He visto que muchos desarrolladores mezclan ''touchend'' y ''click'' en el mismo evento. En muchos casos no dolerá, pero esencialmente la función se dispararía dos veces en dispositivos táctiles:

button.on(''click touchend'', function(event) { // this fires twice on touch devices });

Se ha sugerido que uno podría detectar la capacidad táctil y establecer el evento de manera apropiada, por ejemplo:

var myEvent = (''ontouchstart'' in document.documentElement) ? ''touchend'' : ''click''; button.on(myEvent, function(event) { // this fires only once regardless of device });

El problema con lo anterior, es que se romperá en los dispositivos que admiten el tacto y el mouse. Si el usuario está utilizando actualmente el mouse en un dispositivo de doble entrada, el ''clic'' no se disparará porque solo se asigna ''touchend'' al botón.

Otra solución es detectar el dispositivo (por ejemplo, "iOS") y asignar un evento basado en eso: haga clic en evento llamado dos veces en touchend en iPad . Por supuesto, la solución en el enlace de arriba es solo para iOS (no Android u otros dispositivos), y parece más un "truco" para resolver algo bastante elemental.

Otra solución sería detectar el movimiento del mouse y combinarlo con la capacidad táctil para averiguar si el usuario está en el mouse o toca. Por supuesto, el problema es que el usuario puede no estar moviendo el mouse cuando quiere detectarlo ...

La solución más confiable que se me ocurre es usar una función de debounce para simplemente asegurarme de que la función solo se active una vez dentro de un intervalo corto (por ejemplo, 100 ms):

button.on(''click touchend'', $.debounce(100, function(event) { // this fires only once on all devices }));

¿Me estoy perdiendo algo o alguien tiene alguna sugerencia mejor?

Editar: Encontré este enlace después de mi publicación, que sugiere una solución similar a la anterior: ¿Cómo vincular los eventos ''touchstart'' y ''click'' pero no responder a ambos?


Después de un día de investigación, pensé que la mejor solución era simplemente hacer clic y usar https://github.com/ftlabs/fastclick para eliminar el retraso de toque. No estoy 100% seguro de que sea tan eficiente como touchend , pero no muy lejos de al menos.

Descubrí una forma de desactivar los eventos desencadenantes dos veces al tocar usando stopPropagation y preventDefault , pero esto es dudoso ya que podría interferir con otros gestos táctiles dependiendo del elemento donde se aplica:

button.on(''touchend click'', function(event) { event.stopPropagation(); event.preventDefault(); // this fires once on all devices });

De hecho, estaba buscando una solución para combinar touchstart en algunos elementos de la interfaz de usuario, pero no veo cómo se puede combinar con un clic que no sea la solución anterior.


Esta pregunta es respondida, pero tal vez necesite ser actualizada.

Según un aviso de Google , ya no habrá una demora de 300-350 ms si incluimos la línea siguiente en el elemento <head> .

<meta name="viewport" content="width=device-width">

¡Eso es! ¡Y ya no habrá diferencia entre el clic y el evento táctil!


Hola, puedes implementarlo de la siguiente manera.

function eventHandler(event, selector) { event.stopPropagation(); // Stop event bubbling. event.preventDefault(); // Prevent default behaviour if (event.type === ''touchend'') selector.off(''click''); // If event type was touch turn off clicks to prevent phantom clicks. } // Implement $(''.class'').on(''touchend click'', function(event) { eventHandler(event, $(this)); // Handle the event. // Do somethings... });



Su función debounce retrasará el manejo de cada clic durante 100 ms:

button.on(''click touchend'', $.debounce(100, function(event) { // this is delayed a minimum of 100 ms }));

En cambio, creé una función cancelDuplicates que se cancelDuplicates inmediato, pero cualquier llamada posterior dentro de 10 ms se cancelará:

function cancelDuplicates(fn, threshhold, scope) { if (typeof threshhold !== ''number'') threshhold = 10; var last = 0; return function () { var now = +new Date; if (now >= last + threshhold) { last = now; fn.apply(scope || this, arguments); } }; }

Uso:

button.on(''click touchend'', cancelDuplicates(function(event) { // This fires right away, and calls within 10 ms after are cancelled. }));