34 votes

L'API historique ne fonctionne-t-elle pas sur iOS ? (La barre de localisation ne se met pas à jour sur pushState)

A classer dans les catégories "Je ne peux pas croire que personne ne l'ait remarqué avant" ou "Je dois manquer quelque chose" :

Il semble que si vous effectuez une simple window.history.pushState sur iOS, la barre de localisation n'est pas mise à jour à moins qu'elle ne réponde à un geste de l'utilisateur. L'état lui-même est poussé (comme vous pouvez le voir en appuyant sur le bouton "retour").

Voici le plus petit cas de test que j'ai pu trouver pour recréer le problème :

http://thelink.is/history-api-ios-bug

Sur un navigateur de bureau qui prend en charge l'API Historique, vous devriez voir l'URL dans la barre d'adresse se transformer en /0, /1, etc. toutes les secondes. Sur iOS - testé sur iPhone (iOS 4.3) et iPad (iOS 4.3.3) - la barre d'adresse n'est pas mise à jour, mais le fait d'appuyer sur le bouton "retour" vous ramène à l'adresse précédente correcte (qui est 404 dans le cas de test, car il n'y a pas de logique d'arrière-plan pour gérer ces URL).

Réflexions ? Solutions de rechange ? Une épaule pour pleurer et des câlins ?

MISE À JOUR : ce problème a été résolu dans iOS 5.

22voto

Remy Sharp Points 2953

En résumé, iOS a ajouté sa propre sécurité autour de l'API de l'historique, ce qui signifie que vous ne pouvez pas utiliser script pour changer l'url. Seule une action de l'utilisateur peut permettre à l'API de l'historique de changer l'url - c'est-à-dire un clic - comme dans l'exemple d'Aral.

La solution consiste à utiliser un hachage (ou identifiant de fragment) sur l'url.

Au lieu de la history.pushState nous changerons simplement de lieu :

var i = 0;
var locationUpdateInterval = setInterval(function(){
  window.location.hash = i;
  i++;
}, 1000);   

Pour capturer l'événement lorsque quelque chose change à cet endroit dans l'application iOS ou s'ils ont permuté vers une page/panneau particulier dans votre application :

// named function on purpose for later
function hashchange() {
  var pageId = location.hash.substr(1); // drop the # symbol
  // do something with pageId
}

window.onhashchange = hashchange;

// onload - if there's a hash on the url, try to do something with it
if (location.hash) hashchange();

Il est assez regrettable que nous ne puissions pas utiliser la fonction pushState / popState sur iOS, mais il s'agit de la même sécurité que l'impossibilité de déclencher une vidéo en plein écran à moins que l'utilisateur n'initie l'action, ce qui est la même chose que le téléchargement de contenu vidéo ou audio sur iOS - vous ne pouvez pas script, l'utilisateur doit le lancer (d'une manière ou d'une autre).

Juste une note concernant Android - les problèmes sont assez similaires, donc ceci (devrait) également fonctionner comme solution de contournement pour Android.

Si vous souhaitez une assistance bureautique, la plupart des navigateurs prennent en charge les éléments suivants onhashchange mais, oui, vous l'avez deviné, IE n'est pas à la hauteur - vous pouvez donc polyfiller ce mauvais garçon (bien que cela nécessite jQuery...) : http://benalman.com/projects/jquery-hashchange-plugin/

J'espère que cela vous aidera.

2voto

balupton Points 17805

Il fonctionne bien pour moi lorsque je l'utilise : https://github.com/browserstate/history.js - Cela corrige également de nombreux autres bogues entre navigateurs avec l'API HTML5 History.

Depuis la version 1.7, voici les bogues qu'elle résout :

  • Histoire.js résout les bogues de navigateur suivants
    • H
      • Chrome 8 ne contient parfois pas les données d'état correctes lorsqu'il retourne à l'état initial
      • Safari 5, Safari iOS 4 et Firefox 3 et 4 ne déclenchent pas la fonction onhashchange lorsque la page est chargée avec un hachage
      • Safari 5 et Safari iOS 4 ne déclenchent pas la fonction onpopstate lorsque le hash a changé, contrairement aux autres navigateurs.
      • Safari 5 et Safari iOS 4 ne parviennent pas à revenir à l'état correct lorsqu'un hash est remplacé par un replaceState appeler / rapport de bogue
      • Safari 5 et Safari iOS 4 ne parviennent pas toujours à appliquer le changement d'état en cas d'activité intense / rapport de bogue
      • Google Chrome 8,9,10 et Firefox 4 avant la RC se déclencheront toujours. onpopstate une fois la page chargée / recommandation de modification
      • Safari iOS 4.0, 4.1, 4.2 ont un HTML5 History API fonctionnel - bien que les boutons de retour de ces navigateurs ne fonctionnent pas, nous les traitons donc comme des navigateurs HTML4.
      • Aucun des navigateurs HTML5 n'utilise la fonction title à l'argument pushState y replaceState appels
    • H
      • Les anciens navigateurs tels que MSIE 6, 7 et Firefox 2 n'ont pas d'option d'affichage. onhashchange événement
      • MSIE 6 et 7 n'appliquent parfois pas un hachage alors qu'on le leur a demandé (ce qui nécessite un deuxième appel à la fonction apply).
      • Les navigateurs HTML4 non-Opera n'appliquent parfois pas le hachage lorsqu'il n'est pas urlencoded
    • A
      • Les données et les titres des États ne persistent pas lorsque l'on quitte le site et que l'on y revient (y compris lorsque la page est rafraîchie).
      • Les titres d'État ne sont jamais appliqués aux document.title

1voto

Aral Balkan Points 179

(Mise à jour : je viens de voir que Remy a également répondu - lisez plutôt sa réponse détaillée, ci-dessus).

Remy prévu une solution de contournement pour ce problème sur Twitter.

En fait, si vous modifiez le fichier location.hash, l'adresse dans la barre d'adresse est mise à jour. Cependant, cela crée une entrée séparée dans l'historique (ce qui ne fonctionne pas pour ce que j'essaie de réaliser). La solution de contournement que j'ai mise en place consiste à utiliser des URLs hash-bang pour iOS et des URLs normales pour les autres plateformes jusqu'à ce que le bug d'iOS soit corrigé. Ce n'est certainement pas idéal et j'espère que Mobile Safari sur iOS commencera à se comporter comme Chrome, Firefox et Safari sur les ordinateurs de bureau.

1voto

Cref Points 23

Voici ce que j'ai trouvé :

Lorsque l'emplacement poussé contient un symbole de hachage, la barre d'adresse est mise à jour. Cela fonctionnera donc :

window.history.pushState(data, title, 'a/new/url#');

Mais l'objet window.location ne sera pas mis à jour, vous devez donc enregistrer l'url poussée dans une variable et l'utiliser à la place de window.location si vous avez besoin de l'emplacement poussé.

Testé sur Safari pour Android.

0voto

Soska Points 155

J'ai trouvé une astuce qui fonctionne. Il s'avère que si vous changez le hash juste après history.pushState, la barre de localisation est mise à jour. Par exemple :

        window.history.pushState(data, title, 'a/new/url');
        window.location.hash = 'new';

modifie la barre d'adresse en http://example.com/a/new/url#new . Ce qui pose un autre problème, car le hachage devient sa propre entrée dans l'historique. Vous devrez donc écouter onHashChange de toute façon.

C'est un peu compliqué, mais il y a des gens qui détestent vraiment, vraiment les urls hashbang et qui le disent haut et fort. Cela en vaut donc la peine.

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