L'objet DOM window
fournit un accès à l'historique du navigateur via l'objet history
. Il expose un ensemble de méthodes et de propriétés qui permettent d'avancer et de reculer dans l'historique de l'utilisateur ainsi que -- à partir d'HTML5 -- manipuler le contenu de l'ensemble de l'historique.
Se déplacer dans l'historique
Avancer ou reculer dans l'historique de l'utilisateur est possible en utilisant les méthodes back()
, forward()
et go()
.
Avancer et reculer
Pour reculer dans l'historique, il vous suffit de faire:
window.history.back();
Cela agira exactement comme si l'utilisateur cliquait sur le bouton Retour de la barre d'outils de son navigateur.
De la même manière, il est possible d'avancer (comme si l'utilisateur cliquait sur le bouton Avancer):
window.history.forward();
Se déplacer à un élément précis de l'historique
Vous pouvez utiliser la méthode go()
pour charger une page spécifique de l'historique de la session, identifiée par sa position relative par rapport à la page en cours (la page courante étant, évidemment, d'index 0).
Pour reculer d'une page (l'équivalent d'un appel à back()
):
window.history.go(-1);
Pour avancer d'une page, comme en appelant forward()
:
window.history.go(1);
De la même manière, vous pouvez avancer de 2 pages en passant la valeur 2, et ainsi de suite.
Vous pouvez déterminer le nombre de pages de l'historique en accédant à la valeur de la propriété length:
var numberOfEntries = window.history.length;
go()
; ce comportement est non standard et non supporté par Gecko.Ajouter et modifier des entrées de l'historique
HTML5 a introduit les méthodes history.pushState()
et history.replaceState()
, qui permettent, respectivement, d'ajouter et de modifier des entrées de l'historique. Ces méthodes fonctionnent conjointement avec l'événement window.onpopstate
.
L'utilisation de history.pushState()
change le référent créé habituellement dans l'en-tête HTTP pour les objets XMLHttpRequest
, chaque fois que son état a été changé. Le référent sera l'URL de la page dont l'objet window est this
au moment de la création de l'objet XMLHttpRequest
.
Exemple
Supposons que https://mozilla.org/foo.html exécute la séquence JavaScript suivante :
var stateObj = { foo: "bar" }; history.pushState(stateObj, "page 2", "bar.html");
Cela va provoquer l'apparition dans la barre de navigation de https://mozilla.org/bar.html, mais ne provoquera pas le chargement effectif de bar.html
ni même le test d'existence de bar.html
.
Supposons à présent que l'utilisateur accède à la page https://google.com, puis clique sur l'icône "Recul". La barre de navigation va alors afficher https://mozilla.org/bar.html, et la page va récupérer un événement popstate
dont l'objet état contient une copie de stateObj
. La page elle-même ressemblera à foo.html
, bien que son contenu ait pu être modifié pendant l'événement popstate
.
Si on clique à nouveau sur Recul, l'URL de la barre de navigation va se changer en https://mozilla.org/foo.html, et la page va recevoir un autre événement popstate
, qui comportera, cette fois, un état null. Dans ce cas aussi, revenir en arrière ne modifie pas le contenu du document par rapport à ce qu'il était à l'étape précédente, cela bien qu'il ait pu être mis à jour manuellement sur réception de l'événement popstate
.
La méthode pushState()
La méthode pushState()
utilise trois paramètres : un objet état, un titre (qui est pour l'instant ignoré) et, éventuellement, une URL. Examinons chacun de ces paramètres en détail :
-
l'objet état — L'objet état est un objet Javascript qui est associé à une nouvelle entrée de l'historique par
pushState()
. Chaque fois qu'un utilisateur ouvre une nouvelle page, un événementpopstate
est émis et la propriétéstate
de l'événement contient une copie de l'objet état de ce nouvel élément de l'historique. -
L'objet état peut être tout ce qui peut être sous forme de liste. Puisque Firefox sauvegarde les objets état sur le disque de l'utilisateur de façon à ce qu'ils puissent être rétablis après redémarrage du navigateur, le codage de l'objet état est limité à une taille limite de 640k octets. Si vous donnez à
pushState()
un objet état dont la représentation a une taille plus importante, la méthode génèrera une exception. Si vous avez un besoin d'espace plus important, il est conseillé d'utilisersessionStorage
et/oulocalStorage
. -
titre — Firefox, pour l'instant, ignore ce paramètre, bien qu'il puisse être utilisé plus tard. Afin de prévenir les changements futurs de cette méthode, il serait prudent de fournir ici, en paramètre, une chaîne vide. Vous pourriez aussi donner un titre court à l'état vers lequel vous vous dirigez.
-
URL — L'URL de la nouvelle entrée de l'historique est donnée par ce paramètre. Il convient de préciser que le navigateur n'essaiera pas de charger la page pointée par cette URL après un appel à
pushState()
, mais il se peut qu'il tente de le faire plus tard, par exemple, lorsque l'utilisateur relancera son navigateur. Il n'est pas nécessaire que la nouvelle URL soit absolue ; si elle est relative, ce sera par rapport à l'URL courante. La nouvelle URL doit avoir la même origine (domaine) que l'URL courante ; dans le cas contraire,pushState()
génèrera une exception. Ce paramètre est optionnel ; s'il n'est pas spécifié, sa valeur par défaut est l'URL de la page courante.
On peut assimiler l'appel à pushState()
à l'affectation window.location = "#foo"
, en cela que l'un comme l'autre auront pour effet de créer et déclencher une autre entrée de l'historique associée au document courant. Mais pushState()
a quelques avantages :
- La nouvelle URL peut être quelconque pourvu qu'elle ait la même origine que l'URL courante. En revanche, affecter
window.location
vous maintient au mêmedocument
seulement si vous modifiez uniquement le hash. - Vous n'êtes pas contraint de modifier l'URL si vous ne le voulez pas. Par contre, affecter
window.location = "#foo";
crée une nouvelle entrée de l'historique seulement si le hash courant n'est pas#foo
. - Vous pouvez associer des données quelconques avec votre nouvelle entrée de l'historique. Avec l'approche basée sur le hash, il est nécessaire de coder toute donnée pertinente en une chaîne courte.
Notez que pushState()
n'entraîne jamais le déclenchement d'un événement hashchange
, même si la nouvelle URL diffère de l'ancienne seulement par son hash.
La méthode replaceState()
history.replaceState()
fonctionne exactement comme history.pushState()
hormis le fait que replaceState()
modifie l'entrée courante de l'historique au lieu d'en créer une nouvelle.
replaceState()
est particulièrement utile si vous désirez mettre à jour l'objet état ou l'URL de l'entrée courante de l'historique en réponse à une action de l'utilisateur.
L'événement popstate
Un événement popstate
est envoyé à la fenêtre chaque fois que l'entrée active de l'historique change. Si l'entrée de l'historique activée a été créée par un appel à replaceState
, la propriété state
de l'événement popstate
contient une copie de l'objet état de l'entrée de l'historique.
Voir window.onpopstate
pour un exemple d'utilisation.
Lire l'état courant
Quand votre page est chargée, il se pourrait qu'elle ait un objet état non nul. Cela peut se produire, par exemple, si la page fixe un objet état (avec pushState()
ou replaceState()
) et qu'ensuite l'utilisateur redémarre le navigateur. Quand votre page sera rechargée, elle recevra l'événement onload , mais pas l'événement popstate. Néanmoins, si vous lisez la propriété history.state, vous récupèrerez l'objet état que vous auriez obtenu si un événement popstate avait été déclenché.
Vous pouvez lire l'état de l'entrée courante de l'historique sans devoir attendre un événement popstate
en utilisant la propriété history.state
comme ceci:
var currentState = history.state;
Compatibilité des navigateurs
Fonctionnalité | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
replaceState, pushState | 5 | 4.0 (2.0) | 10 | 11.50 | 5.0 |
history.state | 18 | 4.0 (2.0) | 10 | 11.50 | Pas de support |
Fonctionnalité | Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|
replaceState, pushState | ? | ? | ? | ? | ? |
history.state | ? | ? | ? | ? | ? |
Vous pouvez utiliser History.js pour contourner les problèmes de compatibilité entre navigateurs.