Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Firefox to fire the popstate event when going back from a page on a different domain?

I have a simple web page, namely:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>History hacks</title>
<script>
window.onpopstate = function (e) {
    alert("location: " + document.location + ", state: " + JSON.stringify(e.state));
}
window.onload = function (e) {
    alert('page loaded');
}
</script>
</head>
<body>
<p> <a href="http://www.yahoo.com">Yahoo</a> <a href="#part1">Part 1</a></p>
</body>
</html>

Now there are a number of differences regarding how Chrome and Firefox trigger the popstate event (I shudder to think what I'm up against when I get around to testing IE), but one that's giving me problems here is that Chrome will trigger a popstate event whenever I click on either of those two links, and then again when I hit the back button. Firefox will trigger the event for the link that changes the hash part (only the first time though if the hash link is the same), and won't trigger it at all if I click on the Yahoo link and then click the back button.

So is there a way that I can tell in Firefox that a user has just clicked back and landed back on my page from a completely different site on a different domain? Is there another event that would work for this purpose in Firefox? (The load event does not get triggered either when I go back from yahoo.com.)

like image 226
sagittarian Avatar asked Oct 11 '12 13:10

sagittarian


1 Answers

To get a popstate event when the back (or forward) button is used to go to the initial page load, use replaceState() like

window.onload = function(e) {
  history.replaceState(null, null, document.URL);
}

To ignore the initial popstate that Chrome generates when the page is loaded you can tag the state whenever you call pushState / replaceState, e.g.

history.pushState({myTag: true}, null, url);

Then your popstate handler just filters for myTag

window.onpopstate = function(e) { 
  if (!e.state.myTag) return; // none of my business
  // code to handle popstate 
}

You can combine these two for a trivial cross-browser solution:

window.onpopstate = function(e) { 
  if (!e.state.myTag) return; // none of my business
  // code to handle popstate 
}

window.onload = function(e) {
  history.replaceState({myTag: true}, null, document.URL);
}

@Boris Zbarsky has detailed the bfcache. I haven't thought about how to combine that with my approach. I just disable it by adding a page unload handler

window.onunload = function(e) { }
like image 200
Sean Hogan Avatar answered Oct 19 '22 23:10

Sean Hogan