Event when window.location.href changes
Solution 1
The popstate event is fired when the active history entry changes. [...] The popstate event is only triggered by doing a browser action such as a click on the back button (or calling history.back() in JavaScript)
So, listening to popstate
event and sending a popstate
event when using history.pushState()
should be enough to take action on href
change:
window.addEventListener('popstate', listener);
const pushUrl = (href) => {
history.pushState({}, '', href);
window.dispatchEvent(new Event('popstate'));
};
Solution 2
I use this script in my extension "Grab Any Media" and work fine ( like youtube case )
var oldHref = document.location.href;
window.onload = function() {
var bodyList = document.querySelector("body")
var 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);
};
Solution 3
You can't avoid polling, there isn't any event for href change.
Using intervals is quite light anyways if you don't go overboard. Checking the href every 50ms or so will not have any significant effect on performance if you're worried about that.
Solution 4
There is a default onhashchange
event that you can use.
And can be used like this:
function locationHashChanged( e ) {
console.log( location.hash );
console.log( e.oldURL, e.newURL );
if ( location.hash === "#pageX" ) {
pageX();
}
}
window.onhashchange = locationHashChanged;
If the browser doesn't support oldURL
and newURL
you can bind it like this:
//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;
} );
} () );
Solution 5
Through Jquery, just try
$(window).on('beforeunload', function () {
//your code goes here on location change
});
By using javascript:
window.addEventListener("beforeunload", function (event) {
//your code goes here on location change
});
Refer Document : https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
Comments
-
Johan Dahlin over 2 years
I'm writing a Greasemonkey script for a site which at some point modifies
location.href
.How can I get an event (via
window.addEventListener
or something similar) whenwindow.location.href
changes on a page? I also need access to the DOM of the document pointing to the new/modified url.I've seen other solutions which involve timeouts and polling, but I'd like to avoid that if possible.
-
Noslide over 13 yearsI'm not sure if this will work because often the hash changes do no involve a page reload.
-
Johan Dahlin over 13 yearsI need access to the new DOM as well, I updated the question to clarify that.
-
belugabob over 13 yearsOK - didn't consider the
hash
situation - will think about that one. As for being able to access the new DOM, then you are out of luck (as far as accesssing this from an event handler is concerned) as the event will fire before the new DOM has been loaded. You might be able to incorporate the logic into the onload event of the new page, but you may have the same issues with respect to identifying whether you need to carry out the logic for every load of that page. Can you provide some more details about what you are trying to achieve, including page flow? -
CMCDragonkai about 7 yearsI just tried accessing the location.href inside the onbeforeunload event handler, and it shows the original url, not the target url.
-
user2782001 about 7 yearsBut will the popstate fire before the content is loaded?
-
serv-inc about 7 years@AlexanderMills: fortunately there are these new solutions of
popstate
andhashchange
. -
Guntram about 6 yearsSomehow, I like this approach... feels a little RxJs-ish :)
-
Simon Meusel about 6 yearsThe only solution that could have worked for youtube: [Report Only] Refused to create a worker from 'youtube.com/sw.js' because it violates the following Content Security Policy directive: "worker-src 'none'".
-
inf3rno over 5 yearsThis is not true.
-
inf3rno over 5 yearsBeforeunload can cancel the unloading of the page, so the unload event is better, if you don't want to cancel navigation.
-
inf3rno over 5 years@MartinZvarík Even in 2010 it was possible to use the unload event plus a micro or macro task to get the new document loaded.
-
Fredrik_Borgstrom over 5 yearsHashchange events are only sent if your URL has a part starting with a '#' symbol, normally used for anchor links. Otherwise it won't fire.
-
Admin over 4 yearsMutationObserver
-
Nathan Gouy about 4 yearsunusable if don't have any control over the piece of code that
pushState
-
Bishoy Hanna about 4 yearswindow.addEventListener("hashchange", funcRef, false);
-
Sanchit Batra about 4 yearsWorked out of the box with no trouble for my use case, God bless! It's annoying there's no native event for this yet (popstate did not work for me) but one day! I would use
window.addEventListener("load", () => {})
instead of window.onload though :) -
YangombiUmpakati about 4 yearsthis works, detects history.pushState even in extension context
-
Rico Kahler about 4 yearsUnfortunately this answer is still correct in 2020. popstate only fires when the user uses the forward/back buttons and hashchange only fires for hash changes. Unless you have control over the code that's causing the location to change, you have to poll 🤷♀️
-
TrySpace almost 4 yearsThis does not always work, it relies on a popstate event to be fired. For example navigating within youtube it won't trigger, only if you press back or forward in history
-
Eyal Cohen about 3 yearsman this is amazing. the smartest solution I've seen to date
-
mikey about 3 yearsthis assume you have visibility or know if pushState is called.. it won't work everywhere, like comments above state as well
-
Boontawee Home about 3 yearsman this is amazing. work with shopee webpage.
-
Al Foиce ѫ almost 3 yearsCode-only answers are not particularly helpful. Please add some descriptions of how this code solves the problem.
-
s.r. over 2 yearsThis is the smartest solution to this problem (listening for changes in the body). Also works within React to detect URL changes. Thanks a lot!
-
TGrif over 2 yearsJust try it, doesn't work on Firefox.
-
Praveen Danagoudru over 2 yearsit's working, use javascript
-
S. W. G. about 2 yearsput this in content script but it is not firing.
-
SShah about 2 yearsHello I am new to using MutationObservers and love this solution,its the only one I found that worked sofar for YT redirects. Just wanted to note that you could make it more efficient by moving the
if (oldHref != document.location.href)
check before yourforEach
call as you would only need to do the check once.