Nachdem HTML5 nun eingeführt wurde history.pushState
, um den Browserverlauf zu ändern, verwenden Websites dies in Kombination mit Ajax, anstatt die Fragmentkennung der URL zu ändern.
Leider bedeutet dies, dass diese Anrufe von nicht mehr erkannt werden können onhashchange
.
Meine Frage ist: Gibt es eine zuverlässige Möglichkeit (Hack ?;)) Zu erkennen, wann eine Website verwendet wird history.pushState
? Die Spezifikation gibt nichts über Ereignisse an, die ausgelöst werden (zumindest konnte ich nichts finden).
Ich habe versucht, eine Fassade zu erstellen und durch window.history
mein eigenes JavaScript-Objekt ersetzt, aber es hatte überhaupt keine Auswirkungen.
Weitere Erklärung: Ich entwickle ein Firefox-Add-On, das diese Änderungen erkennen und entsprechend handeln muss.
Ich weiß, dass es vor einigen Tagen eine ähnliche Frage gab, die fragte, ob das Abhören einiger DOM-Ereignisse effizient wäre, aber ich würde mich lieber nicht darauf verlassen, da diese Ereignisse aus vielen verschiedenen Gründen generiert werden können.
Aktualisieren:
Hier ist eine jsfiddle (verwenden Sie Firefox 4 oder Chrome 8), die zeigt, dass sie onpopstate
nicht ausgelöst wird, wenn sie pushState
aufgerufen wird (oder mache ich etwas falsch? Sie können sie jederzeit verbessern!).
Update 2:
Ein weiteres (Neben-) Problem ist, dass window.location
es bei der Verwendung nicht aktualisiert wird pushState
(aber ich habe darüber bereits hier auf SO gelesen, denke ich).
quelle
history
Objekt ersetzt. Dies kann in diesem Fall unnötig sein.window.history
ist schreibgeschützt, aber die Eigenschaften des Verlaufsobjekts sind nicht ... Vielen Dank für diese Lösung :)pushState
Methode für die spätere Verwendung speichern . Anstelle einer globalen Variablen habe ich mich entschieden, den gesamten Code in ein IIFE zu kapseln: en.wikipedia.org/wiki/Immedially-invoked_function_expressionIch habe das benutzt:
Es ist fast das gleiche wie bei Galambalazs .
Normalerweise ist es jedoch übertrieben. Und es funktioniert möglicherweise nicht in allen Browsern. (Ich kümmere mich nur um meine Version meines Browsers.)
(Und es hinterlässt eine Var
_wr
, also möchten Sie es vielleicht einwickeln oder so. Das war mir egal.)quelle
Endlich den "richtigen" Weg gefunden, dies zu tun! Es erfordert das Hinzufügen eines Privilegs zu Ihrer Erweiterung und die Verwendung der Hintergrundseite (nicht nur eines Inhaltsskripts), aber es funktioniert.
Das gewünschte Ereignis
browser.webNavigation.onHistoryStateUpdated
wird ausgelöst, wenn eine Seite diehistory
API zum Ändern der URL verwendet. Es wird nur für Websites ausgelöst, auf die Sie Zugriff haben, und Sie können auch einen URL-Filter verwenden, um den Spam bei Bedarf weiter zu reduzieren. Es erfordert diewebNavigation
Erlaubnis (und natürlich die Host-Erlaubnis für die relevante (n) Domain (s)).Der Ereignisrückruf erhält die Registerkarten-ID, die URL, zu der "navigiert" wird, und andere solche Details. Wenn Sie beim Auslösen des Ereignisses eine Aktion im Inhaltsskript auf dieser Seite ausführen müssen, fügen Sie entweder das entsprechende Skript direkt von der Hintergrundseite ein oder lassen Sie das Inhaltsskript beim Laden
port
auf der Hintergrundseite öffnen und die Hintergrundseite speichern Dieser Port in einer Sammlung wird durch die Registerkarten-ID indiziert und sendet eine Nachricht über den relevanten Port (vom Hintergrundskript zum Inhaltsskript), wenn das Ereignis ausgelöst wird.quelle
Sie könnten an die binden
window.onpopstate
Ereignis ?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
Aus den Dokumenten:
quelle
history.go
,.back
) Funktionen aufgerufen werden. Aber nicht weiterpushState
. Hier ist mein Versuch, es zu testen, vielleicht mache ich etwas falsch: jsfiddle.net/fkling/vV9vd Es scheint nur so verwandt zu sein, dass, wenn der Verlauf von geändert wurdepushState
, das entsprechende Statusobjekt bei den anderen Methoden an den Ereignishandler übergeben wird werden genannt.Da Sie nach einem Firefox-Addon fragen, ist hier der Code, mit dem ich arbeiten muss. Die Verwendung
unsafeWindow
wird nicht mehr empfohlen und es treten Fehler auf, wenn pushState nach einer Änderung von einem Client-Skript aufgerufen wird:Stattdessen gibt es eine API namens exportFunction , mit der die Funktion
window.history
wie folgt eingefügt werden kann :quelle
unsafeWindow.history,
zuwindow.history
. Bei unsafeWindow hat es bei mir nicht funktioniert.Galambalazs Antwort Affenflecken
window.history.pushState
undwindow.history.replaceState
, aber aus irgendeinem Grund funktionierte es nicht mehr für mich. Hier ist eine Alternative, die nicht so schön ist, weil sie Polling verwendet:quelle
Ich denke, dieses Thema braucht eine modernere Lösung.
Ich bin mir sicher, dass
nsIWebProgressListener
es damals da war. Ich bin überrascht, dass niemand es erwähnt hat.Aus einem Framescript (für die Kompatibilität mit e10s):
Dann hören Sie in der
onLoacationChange
Das wird anscheinend alle pushState's fangen. Es gibt jedoch eine Kommentarwarnung, dass "AUCH für pushState ausgelöst wird". Wir müssen hier also noch mehr filtern, um sicherzustellen, dass es sich nur um Pushstate-Inhalte handelt.
Basierend auf: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
Und: resource: //gre/modules/WebNavigationContent.js
quelle
Nun, ich sehe viele Beispiele für das Ersetzen der
pushState
Eigenschaft von,history
aber ich bin nicht sicher, ob dies eine gute Idee ist. Ich würde es vorziehen, ein Serviceereignis zu erstellen, das auf einer ähnlichen API wie der Historie basiert, sodass Sie nicht nur den Push-Status steuern, sondern auch den Status ersetzen können Außerdem öffnet es Türen für viele andere Implementierungen, die nicht auf der globalen Verlaufs-API basieren. Bitte überprüfen Sie das folgende Beispiel:Wenn Sie die
EventEmitter
Definition benötigen , basiert der obige Code auf dem NodeJS-Ereignisemitter: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js .utils.inherits
Die Implementierung finden Sie hier: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970quelle
Ich möchte die native Verlaufsmethode lieber nicht überschreiben, damit diese einfache Implementierung meine eigene Funktion namens eventedPush-Status erstellt, die nur ein Ereignis auslöst und history.pushState () zurückgibt. In beiden Fällen funktioniert es einwandfrei, aber ich finde diese Implementierung etwas sauberer, da native Methoden weiterhin so funktionieren, wie es zukünftige Entwickler erwarten.
quelle
Basierend auf der von @gblazex angegebenen Lösung Sie denselben Ansatz verfolgen möchten, jedoch möchten, folgen Sie dem folgenden Beispiel in Ihrer Javascript-Logik:
Implementieren Sie dann eine andere Funktion
_notifyUrl(url)
, die alle erforderlichen Aktionen auslöst, die Sie möglicherweise benötigen, wenn die aktuelle Seiten-URL aktualisiert wird (auch wenn die Seite überhaupt nicht geladen wurde).quelle
Da ich nur die neue URL haben wollte, habe ich die Codes von @gblazex und @Alberto S. angepasst, um Folgendes zu erhalten:
quelle
Ich halte es nicht für eine gute Idee, native Funktionen zu ändern, auch wenn Sie können, und Sie sollten immer Ihren Anwendungsbereich beibehalten. Ein guter Ansatz ist daher, nicht die globale pushState-Funktion zu verwenden, sondern eine eigene:
Beachten Sie, dass Sie keinen Ereignisauslöser erhalten, wenn ein anderer Code die native pushState-Funktion verwendet (in diesem Fall sollten Sie jedoch Ihren Code überprüfen).
quelle
Standardmäßig:
Wir müssen history.back () aufrufen, um WindowEventHandlers.onpopstate zu aktivieren
So insted von:
machen:
quelle