Alors maintenant que HTML5 introduit history.pushState
pour modifier l'historique des navigateurs, les sites Web commencent à l'utiliser en combinaison avec Ajax au lieu de changer l'identifiant de fragment de l'URL.
Malheureusement, cela signifie que ces appels ne peuvent plus être détectés par onhashchange
.
Ma question est la suivante: existe-t-il un moyen fiable (piratage?;)) De détecter quand un site Web utilise history.pushState
? La spécification n'indique rien sur les événements déclenchés (au moins je n'ai rien trouvé).
J'ai essayé de créer une façade et window.history
je l'ai remplacée par mon propre objet JavaScript, mais cela n'a eu aucun effet.
Explication supplémentaire: je développe un module complémentaire Firefox qui doit détecter ces changements et agir en conséquence.
Je sais qu'il y avait une question similaire il y a quelques jours qui demandait si l'écoute de certains événements DOM serait efficace, mais je préfère ne pas me fier à cela car ces événements peuvent être générés pour de nombreuses raisons différentes.
Mettre à jour:
Voici un jsfiddle (utilisez Firefox 4 ou Chrome 8) qui montre qu'il onpopstate
ne se déclenche pas lors de l' pushState
appel (ou est-ce que je fais quelque chose de mal? N'hésitez pas à l'améliorer!).
Mise à jour 2:
Un autre problème (secondaire) est qu'il window.location
n'est pas mis à jour lors de l'utilisation pushState
(mais j'ai déjà lu à ce sujet ici sur donc je pense).
la source
history
objet. Cela peut être inutile dans ce cas.window.history
est en lecture seule, mais les propriétés de l'objet historique ne sont pas ... Merci beaucoup pour cette solution :)pushState
méthode native pour une utilisation ultérieure. Donc, au lieu d'une variable globale, j'ai choisi d'encapsuler tout le code dans un IIFE: en.wikipedia.org/wiki/Immediately-invoked_function_expressionJ'avais l'habitude d'utiliser ceci:
C'est presque la même chose que les galambalazs .
C'est généralement exagéré cependant. Et cela peut ne pas fonctionner dans tous les navigateurs. (Je ne me soucie que de ma version de mon navigateur.)
(Et cela laisse un var
_wr
, alors vous voudrez peut-être l'envelopper ou quelque chose comme ça. Je m'en fichais.)la source
Enfin trouvé la manière «correcte» de faire cela! Cela nécessite d'ajouter un privilège à votre extension et d'utiliser la page d'arrière-plan (pas seulement un script de contenu), mais cela fonctionne.
L'événement que vous souhaitez est
browser.webNavigation.onHistoryStateUpdated
, qui est déclenché lorsqu'une page utilise l'history
API pour modifier l'URL. Il se déclenche uniquement pour les sites auxquels vous êtes autorisé à accéder, et vous pouvez également utiliser un filtre d'URL pour réduire davantage le spam si vous en avez besoin. Il nécessite l'webNavigation
autorisation (et bien sûr l'autorisation d'hôte pour le (s) domaine (s) concerné (s)).Le rappel d'événement obtient l'ID de l'onglet, l'URL vers laquelle «navigue» et d'autres détails similaires. Si vous devez effectuer une action dans le script de contenu sur cette page lorsque l'événement se déclenche, soit injectez le script approprié directement à partir de la page d'arrière-plan, soit ouvrez le script de contenu
port
sur la page d'arrière-plan lors du chargement, enregistrez la page d'arrière-plan ce port dans une collection indexée par ID d'onglet et envoyer un message sur le port approprié (du script d'arrière-plan au script de contenu) lorsque l'événement se déclenche.la source
Vous pourriez vous lier à l'
window.onpopstate
événement?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
À partir de la documentation:
la source
history.go
,.back
) 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 seulement lié de cette manière que si l'historique a été modifié parpushState
, l'objet d'état correspondant est passé au gestionnaire d'événements lorsque les autres méthodes sont appelés.Puisque vous posez des questions sur un addon Firefox, voici le code que je dois travailler. L' utilisation
unsafeWindow
est pas recommandé plus , et les erreurs quand pushState est appelé à partir d' un script client après avoir été modifié:Au lieu de cela, il existe une API appelée exportFunction qui permet à la fonction d'être injectée
window.history
comme ceci:la source
unsafeWindow.history,
pourwindow.history
. Cela ne fonctionnait pas pour moi avec unsafeWindow.patches de singe de réponse de galambalazs
window.history.pushState
etwindow.history.replaceState
, mais pour une raison quelconque, cela a cessé de fonctionner pour moi. Voici une alternative qui n'est pas aussi agréable car elle utilise l'interrogation:la source
Je pense que ce sujet nécessite une solution plus moderne.
Je suis sûr que
nsIWebProgressListener
c'était à l'époque, je suis surpris que personne ne l'ait mentionné.À partir d'un framescript (pour la compatibilité e10s):
Puis écoutant dans le
onLoacationChange
Cela attrapera apparemment tous les pushState. Mais il y a un commentaire avertissant qu'il "déclenche AUSSI pour pushState". Nous devons donc faire un peu plus de filtrage ici pour nous assurer qu'il ne s'agit que de choses pushstate.
Basé sur: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
Et: resource: //gre/modules/WebNavigationContent.js
la source
Eh 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érerais créer un événement de service basé sur une API similaire à l'historique de cette façon, vous pouvez contrôler non seulement l'état de poussée, mais également remplacer l'état. ainsi et cela ouvre des portes à de nombreuses autres implémentations ne reposant pas sur l'API d'historique global. Veuillez vérifier l'exemple suivant:Si vous avez besoin de la
EventEmitter
définition, le code ci-dessus est basé sur l'émetteur d'événements NodeJS: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js .utils.inherits
La mise en œuvre peut être trouvée ici: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970la source
Je préfère ne pas écraser la méthode d'historique native afin que cette implémentation simple crée ma propre fonction appelée eventedPush state qui distribue simplement un événement et renvoie history.pushState (). Dans les deux cas, cela fonctionne bien, mais je trouve cette implémentation un peu plus propre, car les méthodes natives continueront à fonctionner comme les futurs développeurs l'attendent.
la source
Sur la base de la solution donnée par @gblazex , au cas où vous voudriez suivre la même approche, mais en utilisant les fonctions fléchées, suivez l'exemple ci-dessous dans votre logique javascript:
Ensuite, implémentez une autre fonction
_notifyUrl(url)
qui déclenche toute action requise dont vous pourriez avoir besoin lorsque l'url de la page actuelle est mise à jour (même si la page n'a pas été chargée du tout)la source
Puisque je voulais juste la nouvelle URL, j'ai adapté les codes de @gblazex et @Alberto S.pour obtenir ceci:
la source
Je ne pense pas que ce soit une bonne idée de modifier les fonctions natives même si vous le pouvez, et vous devez toujours garder la portée de votre application, donc une bonne approche consiste à ne pas utiliser la fonction globale pushState, à la place, utilisez l'une des vôtres:
Notez que si un autre code utilise la fonction native pushState, vous n'obtiendrez pas de déclencheur d'événement (mais si cela se produit, vous devriez vérifier votre code)
la source
Comme l'indique la norme:
nous devons appeler history.back () pour triger WindowEventHandlers.onpopstate
Donc insted de:
faire:
la source