55 votes

Champ de texte autofocus de Mobile Safari

Dans Mobile Safari, je ne parviens pas à me concentrer sur un champ de texte après avoir défini un délai. Je joins un exemple de code illustrant le problème. Si, en cliquant sur le bouton, vous déclenchez .focus(), tout fonctionne comme prévu. Si vous suspendez le focus à un callback, comme la fonction setTimeout, cela échoue UNIQUEMENT dans Safari mobile. Dans tous les autres navigateurs, il y a un délai, puis le focus se produit.

De façon déroutante, l'événement "focusin" est déclenché, même dans safari mobile. Ceci (et des commentaires similaires dans SO) me font penser qu'il s'agit d'un bug de mobile safari. Tout conseil sera accepté.

J'ai testé dans l'émulateur, et sur l'iPhone 3GS/4 iOS4.

Exemple HTML :

<!DOCTYPE html> 
  <html lang='en'> 
    <head> 
      <title>Autofocus tests</title> 
      <meta content='width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0' name='viewport'> 
      <meta content='yes' name='apple-mobile-web-app-capable'> 
    </head> 
    <body>
      <h1> 
        Show keyboard without user focus and select text:
      </h1> 
      <p> 
        <button id='focus-test-button'> 
          Should focus on input when you click me after .5 second
        </button> 
        <input id='focus-test-input' type='number' value='20'> 
      </p> 
      <script type="text/javascript"> 
        //<![CDATA[
        var button = document.getElementById('focus-test-button');
        var input  = document.getElementById('focus-test-input');

        input.addEventListener('focusin', function(event) {
          console.log('focus');
          console.log(event);
        });

        button.addEventListener('click', function() {
          // *** If triggered immediately - functionality occurs as expected
          // input.focus();
          // *** If called by callback - triggers the focusin event, but does not bring up keyboard or cursor
          var t = setTimeout("input.focus();",500);
        });
        //]]>
      </script>
    </body>
  </html>

~Des questions similaires :

81voto

Matt Points 4882

Je pense qu'il s'agit d'une fonctionnalité de Safari mobile plutôt que d'un bogue. Dans notre travail sur FastClick Nous avons découvert, mes collègues et moi, que iOS ne permet de déclencher la mise au point sur d'autres éléments, à partir d'une fonction, que si la première fonction de la pile d'appels a été déclenchée par un événement non programmatique. Dans votre cas, l'appel à setTimeout lance une nouvelle pile d'appels, et le mécanisme de sécurité entre en jeu pour vous empêcher de mettre le focus sur l'entrée.

Rappelez-vous que sur iOS, le fait de mettre le focus sur un élément de saisie fait apparaître le clavier. Ainsi, toutes les pages web qui mettent le focus sur un élément de saisie au chargement de la page, comme le fait Google, seraient extrêmement gênantes à utiliser sur iOS. Je suppose qu'Apple a décidé qu'il fallait faire quelque chose pour empêcher cela. Je ne suis donc pas d'accord avec @DA : il s'agit d'une fonctionnalité et non d'un bug.

Il n'y a pas de solution connue pour remédier à ce problème, vous devez donc abandonner l'idée d'utiliser un délai.

Mise à jour : août 2012 :

À partir d'iOS 5, les gestionnaires déclenchés par des événements de clics synthétisés sont autorisés à déclencher le focus sur les éléments d'entrée. Essayez la version mise à jour de Exemple de mise en avant d'une entrée FastClick .

5voto

Nick Saretzky Points 31

J'ai pu faire apparaître le clavier en envoyant un événement de clic uniquement lorsque l'événement original provenait de l'interaction avec l'utilisateur, et non de setTimeout. Je pense que le résultat est que vous pouvez activer le clavier à partir d'un événement de type touchend, mais pas à partir d'un timeout.

1voto

elweilando Points 147

Il semble que focus() ne fonctionne que si vous avez ajouté le site à l'écran d'accueil et si vous avez ouvert le site avec ce lien.

0voto

user1459954 Points 1

Ajout à la réponse de Matt. Au moins sur Safari sous iOS 5.1, ce problème est corrigé. Votre FastClick fonctionne, c'est-à-dire que la synthèse d'un événement de clic ne fera pas échouer le focus. Cependant, cela n'aide pas les personnes qui veulent que leur unique focus() pour fonctionner sur toutes les versions d'iOS, soupir.

0voto

Marz Points 142

J'ai réussi à faire fonctionner .focus() en l'attachant à deux événements distincts dans la carte des événements, mais c'est un peu compliqué.

Après avoir ajouté FastClick.js, voici ce qui se passe dans iOS : .focus() ne fonctionne que lorsqu'il est activé par une fonction attachée à un événement. MAIS le focus est également un événement dans la carte des événements de Safari mobile qui est en fait appelé lorsque vous utilisez le .focus() de jQuery. Vous pouvez donc être redondant et attacher un autre .focus() à l'événement focus de l'objet pour vous assurer qu'il est bien appelé. Cela fonctionne particulièrement bien lorsque vous créez une entrée dans le DOM. J'aime programmer pour MeteorJS ces derniers temps, voici à quoi ressemble la solution là-bas :

Template.templateName.events({
    "click button":function(){
        Session.set("makeButtonVisible",true);
        $("input.created").focus();
    },
    "focus input.created":function(){
        $("input.created").focus();
    }
});

J'espère que cela sera utile à quelqu'un d'autre, j'ai mis deux heures à trouver la solution.

EDITAR: Eh bien, pour MeteorJS en particulier, vous ne pouvez pas non plus utiliser la fonction Template.templateName.rendered car le .focus() doit être invoqué à partir d'un événement. MAIS, pour une raison quelconque, lorsque vous ajoutez une entrée par le biais de jQuery, vous pouvez vous concentrer sur celle-ci dans l'événement. Je suppose que c'est la meilleure solution. Voici ce que j'ai fini par faire :

Template.templateName.events({
    "click button":function(){
        $("body").append("<input class='created' type='tel'>");
        $("input.created").focus();
    }
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X