web-dev-qa-db-fra.com

Éliminer les retards de 300 ms sur les événements liés aux clics dans Safari mobile

J'ai lu cela Safari mobile a un délai de 300 ms sur les événements de clic à partir du moment où le lien/bouton est cliqué jusqu'au moment où l'événement est déclenché. La raison du retard est d’attendre de voir si l’utilisateur a l’intention de cliquer deux fois, mais d’un point de vue UX, attendre 300 ms est souvent indésirable.

ne solution pour éliminer ce délai de 300 ms, vous devez utiliser le traitement "tap" de jQuery Mobile. Malheureusement, je ne connais pas bien ce framework et je ne veux pas charger de gros framework si tout ce dont j'ai besoin est une ligne ou deux de code appliquant touchend de la bonne manière.

Comme de nombreux sites, mon site comporte de nombreux événements de clic tels que:

$("button.submitBtn").on('click', function (e) {   
  $.ajaxSubmit({... //ajax form submisssion
});

$("a.ajax").on('click', function (e) {   
  $.ajax({... //ajax page loading
});

$("button.modal").on('click', function (e) {   
      //show/hide modal dialog
});

et ce que je voudrais faire est de se débarrasser du délai de 300 ms sur [~ # ~] tous [~ # ~] ces événements de clic utilisant un seul extrait de code comme ceci:

$("a, button").on('tap', function (e) {
 $(this).trigger('click');
 e.preventDefault();
});

Est-ce une mauvaise/bonne idée?

84
tim peterson

Maintenant, certains navigateurs mobiles éliminent le délai de 300 ms si vous définissez la fenêtre. Vous n'avez plus besoin de recourir à des solutions de contournement.

<meta name="viewport" content="width=device-width, user-scalable=no">

Ceci est actuellement pris en charge Chrome pour Android , Firefox pour Android et Safari pour iOS

Toutefois, sur iOS Safari , un double-clic est un geste de défilement sur des pages immanquables. Pour cette raison , ils ne peuvent pas supprimer le délai de 300 ms . S'ils ne peuvent pas supprimer le retard sur les pages immanimables, il est peu probable qu'ils le suppriment sur les pages zoomables.

Les téléphones Windows conservent également le délai de 300 ms sur les pages immanquables, mais ils ne disposent pas d'un geste alternatif comme iOS, ce qui leur permet de supprimer ce délai Chrome a. Vous pouvez supprimer le retard sur Windows Phone en utilisant:

html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

Source: http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

UPDATE 2015 Décembre

Jusqu'à présent, WebKit et Safari sur iOS disposaient d'un délai de 350 ms avant que les pressions simples activent des liens ou des boutons pour permettre aux utilisateurs de zoomer sur les pages en une double pression. Chrome a déjà changé cela il y a quelques mois en utilisant un algorithme plus intelligent pour détecter cela et WebKit suivra avec une approche similaire . Cet article donne de très bonnes informations sur la manière dont les navigateurs travaillez avec des gestes tactiles et comment les navigateurs peuvent toujours devenir beaucoup plus intelligents qu'aujourd'hui.

UPDATE 2016 Mars

Sur Safari pour iOS, le temps d’attente de 350 ms pour détecter un deuxième tapotement a été supprimé pour créer une réponse "tapotement rapide". Cette option est activée pour les pages qui déclarent une fenêtre avec width = device-width ou user-scalable = no. Les auteurs peuvent également choisir d’appuyer rapidement sur le comportement d’éléments spécifiques à l’aide de CSS touch-action: manipulation comme documenté ici (faites défiler jusqu'à l'en-tête "Style du comportement de frappe rapide") et ici .

61
NoNameProvided

Ce plugin -FastClick développé par Financial Times le fait parfaitement pour vous!

Assurez-vous cependant d’ajouter event.stopPropagation(); et/ou event.preventDefault(); directement après la fonction click, sinon elle risque de fonctionner deux fois plus vite que pour moi, c’est-à-dire:

$("#buttonId").on('click',function(event){
    event.stopPropagation(); event.preventDefault();
   //do your magic

});
43
Jonathan

je sais que c'est vieux, mais ne pouvez-vous pas simplement tester pour voir si "touch" est pris en charge dans le navigateur? Créez ensuite une variable "touchend" ou "click" et utilisez-la comme événement lié à votre élément?

var clickOrTouch = (('ontouchend' in window)) ? 'touchend' : 'click';
$('#element').on(clickOrTouch, function() {
    // do something
});

Cet exemple de code vérifie donc si l'événement "touchend" est pris en charge dans le navigateur. Sinon, nous utilisons l'événement "click".

(Edit: changé "touchend" en "ontouchend")

16
Michael Turnwall

Je suis tombé sur un alternative très populaire appelée Hammer.js(page Github) qui, à mon avis, est la meilleure approche.

Hammer.js est une bibliothèque tactile plus complète (comportant de nombreuses commandes de balayage) que Fastclick.js (réponse la plus votée).

Attention cependant: le défilement rapide sur les appareils mobiles a tendance à verrouiller l'interface utilisateur lorsque vous utilisez Hammer.js ou Fastclick.js. Ceci est un problème majeur si votre site a un fil d’actualité ou une interface où les utilisateurs vont beaucoup défiler (cela ressemble à la plupart des applications Web). Pour cette raison, je n’utilise aucun de ces plugins pour le moment.

12
tim peterson

D'une manière ou d'une autre, la désactivation du zoom semble désactiver ce petit retard. Cela a du sens, car il ne faut plus taper deux fois.

Comment puis-je "désactiver" le zoom sur une page Web mobile?

Mais soyez conscient de l'impact que cela aura sur la convivialité. Cela peut être utile pour les pages Web conçues comme des applications, mais ne devrait pas être utilisé pour des pages "statiques" plus générales, à mon humble avis. Je l'utilise pour un projet animal nécessitant une faible latence.

2
ayke

J'ai cherché un moyen facile sans jQuery et sans bibliothèque fastclick. Cela fonctionne pour moi:

var keyboard = document.getElementById("keyboard");
var buttons = keyboard.children;
var isTouch = ("ontouchstart" in window);
for (var i=0;i<buttons.length;i++) {
    if ( isTouch ) {
        buttons[i].addEventListener('touchstart', clickHandler, false);         
    } else {
        buttons[i].addEventListener('click', clickHandler, false);          
    }
}
1
Jarda Pavlíček

Malheureusement, il n'y a pas de moyen facile de le faire. Donc, utiliser simplement touchstart ou touchend vous laissera avec d'autres problèmes comme quelqu'un commence à défiler lorsque vous cliquez sur un bouton, par exemple. Nous utilisons zepto pendant un certain temps, et même avec ce très bon framework, des problèmes sont apparus au fil du temps. Beaucoup d'entre eux sont fermés , mais il ne semble pas que ce soit un domaine de solution simple.

Nous avons cette solution pour gérer globalement les clics sur les liens:

   $(document.body).
    on('tap', 'a',function (e) {
      var href = this.getAttribute('href');
      if (e.defaultPrevented || !href) { return; }
      e.preventDefault();
      location.href= href;
    }).
    on('click', 'a', function (e) {
      e.preventDefault();
    });
1
Andreas Köberle

Dans jQuery, vous pouvez lier l’événement "touchend" avec le code de déclenchement immédiatement après l’appui (c’est comme une touche au clavier). Testé sur les versions actuelles Chrome et de la tablette Firefox. N'oubliez pas de "cliquer" également, pour vos ordinateurs portables à écran tactile et vos ordinateurs de bureau.

jQuery('.yourElements').bind('click touchend',function(event){

    event.stopPropagation();
    event.preventDefault();

        // everything else
});
0
Benjamin

Vous êtes censé déclarer explicitement le mode passif :

window.addEventListener('touchstart', (e) => {

    alert('fast touch');

}, { passive : true});
0
Bruno

Juste pour fournir des informations supplémentaires.

Sur iOS 10, <button>s sur ma page n'a pas pu être déclenché en permanence. Il y avait toujours un décalage.

J'ai essayé fastclick/Hammer/tapjs/en remplaçant clic par touchstart, tout a échoué.

UPDATE: la raison semble être que le bouton est trop proche de l'Edge! déplacez-le vers le centre et le décalage a disparu!

0
Dai