Avant iOS8, l'utilisation de la méthode Javascript .focus()
sur un élément d'entrée semblait n'avoir aucun effet (le clavier virtuel ne s'afficherait pas). Après la dernière version iOS 8, l'exécution de la méthode .focus()
semblait n'avoir aucun effet sur le chargement de la page, mais lorsqu'un utilisateur touchait n'importe où sur l'écran, le clavier virtuel apparaissait instantanément et faisait défiler la page jusqu'à l'élément sélectionné. (Ceci est également un problème lorsque j'utilise l'attribut HTML "autofocus")
Cette modification a provoqué des problèmes avec les utilisateurs iOS8 sur mon site. Lorsqu'un utilisateur tente de cliquer sur un bouton de ma page, le défilement soudain et l'apparence du clavier entraînent un clic involontaire sur un bouton situé plus bas de l'écran.
Je suppose qu’il s’agit d’un bogue dans iOS8 et qu’il ne s’agissait pas d’une fonctionnalité intentionnelle. Ma question est la suivante: quelle est la solution la plus efficace pour résoudre ce problème?
Dois-je vérifier navigator.userAgent
pour voir si le périphérique est iOS8, chaque fois que j'utilise la méthode .focus()
?
Il semble que vous rencontriez un bogue iOS 8. Dans iOS7, Safari ignorait (apparemment) ou conservait les éléments flous ayant le focus défini avant le chargement de la page. Cela inclut à la fois <input autofocus>
et input.focus()
qui se produisent jusqu'à un moment donné, éventuellement un chargement de page (j'ai testé uniquement avec un script intégré).
Dans iOS 8, Safari se souvient apparemment maintenant que l'élément était concentré, mais pas réellement jusqu'à ce qu'un événement touche le sol. Il envoie alors aveuglément un événement de clic à l’un des éléments ayant reçu la retouche.
Les deux navigateurs se comportent de la même manière pour input.focus()
après le chargement de la page. Ils font tous deux un zoom sur l’élément et font apparaître le clavier.
Tests:
input.focus()
avant le chargement de la page: http://fiddle.jshell.net/qo6ctnLz/3/show/<input autofocus>
: http://fiddle.jshell.net/qo6ctnLz/4/show/input.focus()
après le chargement de la page: http://fiddle.jshell.net/qo6ctnLz/6/show/La bonne nouvelle est que vous n’avez qu’à vous inquiéter du nouveau comportement des éléments que vous souhaitez préfocaliser. L'autre bonne nouvelle est que, même si vous devrez utiliser une solution de contournement agent utilisateur, vous pouvez l'utiliser pour toutes les versions d'iOS, car elles se comportaient déjà comme si vous n'étiez pas autofocus:
if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
element.focus();
}
Cela semble être l’approche http://www.google.com utilise basée sur des tests élémentaires d’agent utilisateur:
Si vous ne l'avez pas encore fait, vous devriez enregistrer un radar auprès d'Apple à l'adresse suivante: https://bugreport.Apple.com .
Si vous développez un projet Cordova, vous pouvez le réparer en ajoutant cette ligne.
<preference name="KeyboardDisplayRequiresUserAction" value="false" />
dans votre fichier config.xml
. Testé dans IOS 8.3 et IOS 8.4
Il semble que dans iOS 8, l'API ait modifié la gestion par défaut de la commande javascript focus (). Si votre application est une application hybride dans laquelle vous avez un contrôle direct sur la façade de la vue Web d’Apple, la description ci-dessous provient directement de la documentation Apple.
Une valeur booléenne indiquant si le contenu Web peut être programmé afficher le clavier.
[myWebView setKeyboardDisplayRequiresUserAction: YES];
Lorsque cette propriété est définie sur YES, l'utilisateur doit explicitement appuyer sur le éléments de la vue Web pour afficher le clavier (ou toute autre vue d’entrée pertinente.) pour cet élément. Lorsqu'il est défini sur NO, un événement de focus sur un élément entraîne l'affichage de la vue d'entrée et son association avec celle-ci élément automatiquement.
La valeur par défaut de cette propriété est YES.
D'après le dernier paragraphe, il semble que cet appel de méthode ne soit pas strictement réservé au clavier. Il indique que cela s’applique aux vues d’entrée dans l’ensemble, c’est-à-dire la liste déroulante et le sélecteur de date, etc.
Il semble qu’il y ait un bogue car cet appel de méthode ne fonctionne pas actuellement pour moi. Le comportement actuel que je reçois correspond comme si sa valeur par défaut était NO.
J'ai une solution:
Voici un monkeypatch conditionnel pour jQuery.focus
afin que vous n'ayez pas besoin d'ajouter le test userAgent partout.
if (/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
(function($) {
return $.fn.focus = function() {
return arguments[0];
};
})(jQuery);
}
if /iPad|iPhone|iPod/g.test navigator.userAgent
(($) ->
$.fn.focus = ->
arguments[0]
)(jQuery)
Remarque: je retourne arguments[0]
pour ne pas interrompre le chaînage de méthodes tel que $(el).focus().doSomethingElse()
.
Pour ceux qui viennent à cela en 2018, il existe un plugin qui le corrige. Installez simplement ceci https://github.com/onderceylan/cordova-plugin-wkwebview-inputfocusfix et input.focus()
fonctionnera automatiquement, sans travail supplémentaire.
J'ai signalé un bogue à ce sujet dans Apple Bug Reporter et ils l'ont fermé en double, ce qui est un signe qu'ils travaillent à résoudre ce problème. Malheureusement, ils ne m'ont pas donné plus d'informations sur l'élément en double ou sur le problème lui-même. Je ne peux voir que l'état de l'élément en double, qui est ouvert.