web-dev-qa-db-fra.com

sous iOS8, en utilisant .focus () affichera le clavier virtuel et la page de défilement après toucher

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()?

48
Mac Mad Ill

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:

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:

  • Mac Book Pro: mise au point automatique avant le chargement de la page.
  • iPhone: pas de mise au point automatique
  • iPad: pas de mise au point automatique
  • Kit Kat (Android): focus après chargement de la page, éventuellement détection supplémentaire de la présence d'un clavier logiciel.

Si vous ne l'avez pas encore fait, vous devriez enregistrer un radar auprès d'Apple à l'adresse suivante: https://bugreport.Apple.com .

30
Brian Nickel

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

21
Del

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. 

4
xMythicx

J'ai une solution:

  1. Désactiver toutes les entrées
  2. Activer l'entrée que vous souhaitez mettre au point
  3. Définir le focus sur cette entrée
  4. Réactiver toutes les autres entrées

Voici un monkeypatch conditionnel pour jQuery.focus afin que vous n'ayez pas besoin d'ajouter le test userAgent partout.

JavaScript

if (/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
  (function($) {
    return $.fn.focus = function() {
      return arguments[0];
    };
  })(jQuery);
}

CoffeeScript

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().

1
Adam Fraser

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.

0
Ahmad Alfy

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.

0
Lipata