Ich schreibe ein Greasemonkey-Skript für eine Site, die irgendwann geändert wird location.href
.
Wie kann ich ein Ereignis (über window.addEventListener
oder ähnliches) erhalten, wenn window.location.href
Änderungen auf einer Seite vorgenommen werden? Ich benötige auch Zugriff auf das DOM des Dokuments, das auf die neue / geänderte URL verweist.
Ich habe andere Lösungen gesehen, die Zeitüberschreitungen und Abfragen beinhalten, aber ich möchte dies nach Möglichkeit vermeiden.
javascript
dom
greasemonkey
dom-events
Johan Dahlin
quelle
quelle
Antworten:
Popstate-Ereignis :
Das Abhören eines
popstate
Ereignisses und das Senden einespopstate
Ereignisses bei Verwendunghistory.pushState()
sollten also ausreichen, um Maßnahmen beihref
Änderungen zu ergreifen :window.addEventListener('popstate', listener); const pushUrl = (href) => { history.pushState({}, '', href); window.dispatchEvent(new Event('popstate')); };
quelle
pushState
Ich benutze dieses Skript in meiner Erweiterung "Grab Any Media" und arbeite gut ( wie YouTube Fall )
var oldHref = document.location.href; window.onload = function() { var bodyList = document.querySelector("body") ,observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (oldHref != document.location.href) { oldHref = document.location.href; /* Changed ! your code here */ } }); }); var config = { childList: true, subtree: true }; observer.observe(bodyList, config); };
quelle
window.addEventListener("load", () => {})
anstelle von window.onload verwenden :)Sie können das Abrufen nicht vermeiden, es gibt kein Ereignis für eine Änderung von href.
Die Verwendung von Intervallen ist sowieso recht einfach, wenn Sie nicht über Bord gehen. Wenn Sie diesbezüglich etwa 50 ms lang die href überprüfen, hat dies keine wesentlichen Auswirkungen auf die Leistung.
quelle
popstate
undhashchange
.Es gibt ein Standardereignis
onhashchange
, das Sie verwenden können.HIER dokumentiert
Und kann so verwendet werden:
function locationHashChanged( e ) { console.log( location.hash ); console.log( e.oldURL, e.newURL ); if ( location.hash === "#pageX" ) { pageX(); } } window.onhashchange = locationHashChanged;
Wenn der Browser dies nicht unterstützt
oldURL
undnewURL
Sie ihn wie folgt binden können://let this snippet run before your hashChange event binding code if( !window.HashChangeEvent )( function() { let lastURL = document.URL; window.addEventListener( "hashchange", function( event ) { Object.defineProperty( event, "oldURL", { enumerable: true, configurable: true, value: lastURL } ); Object.defineProperty( event, "newURL", { enumerable: true, configurable: true, value: document.URL } ); lastURL = document.URL; } ); } () );
quelle
Haben Sie es schon einmal versucht? Dieses Ereignis wird unmittelbar ausgelöst, bevor die Seite auf eine Navigationsanforderung reagiert. Dies sollte die Änderung der href beinhalten.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE></TITLE> <META NAME="Generator" CONTENT="TextPad 4.6"> <META NAME="Author" CONTENT="?"> <META NAME="Keywords" CONTENT="?"> <META NAME="Description" CONTENT="?"> </HEAD> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function(){ $(window).unload( function(event) { alert("navigating"); } ); $("#theButton").click( function(event){ alert("Starting navigation"); window.location.href = "http://www.bbc.co.uk"; } ); }); </script> <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?"> <button id="theButton">Click to navigate</button> <a href="http://www.google.co.uk"> Google</a> </BODY> </HTML>
Beachten Sie jedoch, dass Ihr Ereignis immer dann ausgelöst wird, wenn Sie von der Seite weg navigieren, sei es aufgrund des Skripts oder wenn jemand auf einen Link klickt. Ihre eigentliche Herausforderung besteht darin, die verschiedenen Gründe für das Auslösen des Ereignisses zu ermitteln. (Wenn dies für Ihre Logik wichtig ist)
quelle
hash
Situation nicht berücksichtigt - werde darüber nachdenken. Wenn Sie auf das neue DOM zugreifen können, haben Sie kein Glück (was den Zugriff von einem Event-Handler betrifft), da das Ereignis ausgelöst wird, bevor das neue DOM geladen wurde. Möglicherweise können Sie die Logik in das Onload-Ereignis der neuen Seite integrieren, aber Sie haben möglicherweise dieselben Probleme bei der Identifizierung, ob Sie die Logik für jedes Laden dieser Seite ausführen müssen. Können Sie weitere Details zu dem, was Sie erreichen möchten, einschließlich des Seitenflusses, angeben?Durch JQuery , versuchen Sie einfach
$(window).on('beforeunload', function () { //your code goes here on location change });
Durch die Nutzung Javascript :
window.addEventListener("beforeunload", function (event) { //your code goes here on location change });
Siehe Dokument: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
quelle
Nun, es gibt zwei Möglichkeiten, das zu ändern
location.href
. Sie können entweder schreibenlocation.href = "y.html"
, wodurch die Seite neu geladen wird, oder Sie können die Verlaufs-API verwenden, die die Seite nicht neu lädt. Ich habe in letzter Zeit viel mit dem ersten experimentiert.Wenn Sie ein untergeordnetes Fenster öffnen und die Last der untergeordneten Seite aus dem übergeordneten Fenster erfassen, verhalten sich verschiedene Browser sehr unterschiedlich. Das einzige, was häufig vorkommt, ist, dass das alte Dokument entfernt und ein neues hinzugefügt wird. Das Hinzufügen von Readystatechange- oder Load-Ereignishandlern zum alten Dokument hat also keine Auswirkungen. Die meisten Browser entfernen auch die Ereignishandler aus dem Fensterobjekt. Die einzige Ausnahme ist Firefox. In Chrome mit Karma Runner und in Firefox können Sie das neue Dokument im Ladebereitschaftsstatus erfassen, wenn Sie es verwenden
unload + next tick
. So können Sie beispielsweise einen Ladeereignishandler oder einen Readystatechange-Ereignishandler hinzufügen oder einfach protokollieren, dass der Browser eine Seite mit einem neuen URI lädt. In Chrome mit manuellen Tests (wahrscheinlich auch GreaseMonkey) und in Opera, PhantomJS, IE10, IE11 können Sie das neue Dokument nicht im Ladezustand erfassen. In diesen Browsernunload + next tick
ruft der Rückruf einige hundert ms später auf, als das Ladeereignis der Seite ausgelöst wird. Die Verzögerung beträgt normalerweise 100 bis 300 ms, aber die Oper simetime macht eine Verzögerung von 750 ms für den nächsten Tick, was beängstigend ist. Wenn Sie also in allen Browsern ein konsistentes Ergebnis erzielen möchten, tun Sie nach dem Ladeereignis, was Sie möchten. Es gibt jedoch keine Garantie dafür, dass der Speicherort zuvor nicht überschrieben wird.var uuid = "win." + Math.random(); var timeOrigin = new Date(); var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes"); var callBacks = []; var uglyHax = function (){ var done = function (){ uglyHax(); callBacks.forEach(function (cb){ cb(); }); }; win.addEventListener("unload", function unloadListener(){ win.removeEventListener("unload", unloadListener); // Firefox remembers, other browsers don't setTimeout(function (){ // IE10, IE11, Opera, PhantomJS, Chrome has a complete new document at this point // Chrome on Karma, Firefox has a loading new document at this point win.document.readyState; // IE10 and IE11 sometimes fails if I don't access it twice, idk. how or why if (win.document.readyState === "complete") done(); else win.addEventListener("load", function (){ setTimeout(done, 0); }); }, 0); }); }; uglyHax(); callBacks.push(function (){ console.log("cb", win.location.href, win.document.readyState); if (win.location.href !== "http://localhost:4444/y.html") win.location.href = "http://localhost:4444/y.html"; else console.log("done"); }); win.location.href = "http://localhost:4444/x.html";
Wenn Sie Ihr Skript nur in Firefox ausführen, können Sie eine vereinfachte Version verwenden und das Dokument in einem Ladezustand erfassen, sodass beispielsweise ein Skript auf der geladenen Seite nicht weg navigieren kann, bevor Sie die URI-Änderung protokollieren:
var uuid = "win." + Math.random(); var timeOrigin = new Date(); var win = window.open("about:blank", uuid, "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=yes"); var callBacks = []; win.addEventListener("unload", function unloadListener(){ setTimeout(function (){ callBacks.forEach(function (cb){ cb(); }); }, 0); }); callBacks.push(function (){ console.log("cb", win.location.href, win.document.readyState); // be aware that the page is in loading readyState, // so if you rewrite the location here, the actual page will be never loaded, just the new one if (win.location.href !== "http://localhost:4444/y.html") win.location.href = "http://localhost:4444/y.html"; else console.log("done"); }); win.location.href = "http://localhost:4444/x.html";
Wenn es sich um Einzelseitenanwendungen handelt, die den Hash-Teil des URI ändern oder die Verlaufs-API verwenden, können Sie das
hashchange
bzw. daspopstate
Ereignis des Fensters verwenden. Diese können auch dann erfasst werden, wenn Sie sich im Verlauf vor und zurück bewegen, bis Sie auf derselben Seite bleiben. Das Dokument ändert sich dadurch nicht und die Seite wird nicht wirklich neu geladen.quelle