Comment être notifié sur les changements de l'histoire par l'histoire.pushState?
Alors, maintenant que HTML5 introduit de l'histoire.pushState
de changer les navigateurs de l'histoire, les sites web de commencer à utiliser ce en combinaison avec l'Ajax au lieu de modifier l'identificateur de fragment de l'URL.
Malheureusement, cela signifie que ces appels ne peuvent pas être détecter plus par onhashchange
.
Ma question est: Est-il un moyen fiable (hack? ;)) pour détecter si un site web utilise history.pushState
? La spécification ne précise rien sur les événements qui se sont élevés (au moins je ne pouvais pas trouver quoi que ce soit).
J'ai essayé de créer une façade et remplacé window.history
avec mon propre objet JavaScript, mais cela n'a eu aucun effet du tout.
Plus d'explications: je suis le développement d'un add-on Firefox qui doit détecter ces changements et agir en conséquence.
Je sais qu'il y a une question similaire il y a quelques jours qui a demandé si l'écoute de certains DOM événements serait efficace, mais je préfère ne pas compter sur ce que ces événements peuvent être générés pour beaucoup de raisons différentes.
Mise à jour:
Voici un jsfiddle (utiliser Firefox 4 et Chrome 8) qui montre que onpopstate
n'est pas déclenché lorsque pushState
est appelé (ou suis-je en train de faire quelque chose de mal? Hésitez pas à l'améliorer!).
Mise à jour 2:
L'autre (côté) problème, c'est que window.location
n'est pas mis à jour lors de l'utilisation de pushState
(mais j'ai lu sur ce déjà sur DONC, je pense).
Vous devez vous connecter pour publier un commentaire.
Selon les ce, il n'y a aucune raison pour popstate être déclenché lorsque vous utilisez
pushState
. Mais un événement commepushstate
viendrait dans maniable. Parce quehistory
est un objet hôte, vous devez être prudent avec elle, mais Firefox semble être sympa dans ce cas. Ce code fonctionne très bien:Votre jsfiddle devient:
Vous pouvez singe-patch
window.history.replaceState
de la même manière.Remarque: bien sûr, vous pouvez ajouter
onpushstate
simplement à l'objet global, et vous pouvez même en faire manipuler plus d'événements par l'intermédiaire deadd/removeListener
history
objet. Qui peut être inutile dans ce cas.window.history
est en lecture seule, mais les propriétés de l'histoire de l'objet ne sont pas... Merci beaucoup pour cette solution 🙂history
est un objet hôte, il n'est pas garanti que la méthode ci-dessus fonctionne de la croix-navigateur. Mais la question était à propos d'un extension de Firefox, j'ai donc essayé de le résoudre dans Firefox.window.history
en tant que paramètre au lieu de l'exécuter directement le code et l'utilisation dewindow.history
à la place de lahistory
paramètre?pushState
méthode pour les utiliser plus tard. Ainsi, au lieu d'une variable globale que j'ai choisi pour encapsuler l'ensemble du code dans une IIFE: en.wikipedia.org/wiki/Immediately-invoked_function_expressionif (typeof history.onpushstate == "function")
vérifier exactement? Ce n'est pas définie dans n'importe quel navigateur, j'ai essayé... :^) Peut-être que certains vieux de la version du navigateur?Vous pouvez lier à la
window.onpopstate
événement?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
De la documentation:
history.go
,.back
) les fonctions sont appelées. Mais pas surpushState
. Voici ma tentative de le tester, peut-être que je fais quelque chose de mal: jsfiddle.net/fkling/vV9vd Il semble uniquement lié à la manière que si l'histoire a été modifié parpushState
, le correspondant de l'état de l'objet est passé au gestionnaire d'événement lorsque les autres méthodes sont appelées.J'ai utilisé ceci:
C'est presque la même que galambalazs fait.
C'est généralement les excès de si. Et il pourrait ne pas fonctionner dans tous les navigateurs. (Je ne se soucient ma version de mon navigateur).
(Et il laisse une var
_wr
, de sorte que vous pouvez l'envelopper ou quelque chose. Je n'ai pas de soins à ce sujet.)Je pense que ce sujet a besoin d'une solution plus moderne.
Je suis sûr que
nsIWebProgressListener
était autour du dos, puis je suis surpris que personne ne le mentionne.À partir d'un framescript (pour e10s de compatibilité):
Puis l'écoute dans la
onLoacationChange
Qui sera apparemment attraper tous pushState de l'. Mais il y a un commentaire indiquant que "déclenche ÉGALEMENT pour pushState". Nous avons donc besoin de faire un peu plus de filtrage ici pour s'assurer qu'il est juste pushstate choses.
Basée sur: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
Et: resource://gre/modules/WebNavigationContent.js
galambalazs réponse singe patchs
window.history.pushState
etwindow.history.replaceState
, mais pour quelque raison il a cessé de travailler pour moi. Voici une alternative qui n'est pas aussi agréable car il utilise l'interrogation:Depuis que vous vous posez à propos d'un addon Firefox, voici le code que j'ai eu à travailler. À l'aide de
unsafeWindow
est n'est plus recommandé, et d'erreur quand pushState est appelé à partir d'un script client après avoir été modifié:Au lieu de cela, il y a une API appelée exportFunction qui permet à la fonction d'être injecté dans
window.history
comme ceci:Bien, je vois de nombreux exemples de remplacement de la
pushState
propriété dehistory
mais je ne suis pas sûr que ce soit une bonne idée, je préfère créer un service de base avec une API similaire à l'histoire de cette façon, vous pouvez contrôler non seulement de pousser l'état, mais de remplacer l'état et il ouvert des portes pour beaucoup d'autres implémentations ne s'appuyant pas sur l'histoire mondiale de l'API. Veuillez consulter l'exemple suivant:Si vous avez besoin de la
EventEmitter
définition, le code ci-dessus est basé sur NodeJS cas de l'émetteur: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js.utils.inherits
mise en œuvre peut être trouvé ici: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970utils
venir enutils.inherits(EventEmitter.prototype);
???Enfin trouvé la "bonne" façon de faire cela! Il nécessite l'ajout d'un privilège à l'extension et à l'aide de la page de fond (et pas seulement un contenu de script), mais il fonctionne.
L'événement que vous souhaitez est
navigateur.webNavigation.onHistoryStateUpdated
, qui est déclenché lorsqu'une page utilise lehistory
API pour modifier l'URL. Il se déclenche uniquement pour les sites que vous avez l'autorisation d'accès, et vous pouvez également utiliser un filtre d'URL pour couper plus bas sur le spam si vous en avez besoin. Il nécessite lawebNavigation
autorisation (et bien sûr de l'hôte la permission pour le domaine concerné(s)).L'événement de rappel obtient l'onglet ID de l'URL de la page qui est en cours de "naviguer", et d'autres détails. Si vous avez besoin de prendre une action dans le contenu du script de la page lorsque l'événement se déclenche, soit injecter le script approprié directement à partir de la page d'arrière-plan, ou le contenu de script ouvrir un
port
à l'arrière-plan de la page lors du chargement, de l'arrière-plan de la page enregistrer ce port dans une collection indexée par onglet ID, et d'envoyer un message à travers le port (à partir de l'arrière-plan de script pour le contenu du script) lorsque l'événement est déclenché.Standard unis:
nous avons besoin de l'historique des appels.de retour() pour trigeer WindowEventHandlers.onpopstate
Donc insted de:
faire: