I have a simple scenario where hitting the browser back button (and forward) is not triggering history.popstate event as expected.
Mozilla documentation explicitly states: The popstate event of the Window interface is fired when the active history entry changes while the user navigates the session history
I was able to generate a very minimalistic test case that recreates the issue.
The test case is composed of 2 pages, MainPage.html and SecondPage.html. MainPage has a single button. When the user clicks on it, it executes an AJAX GET request. When the response is received, window.location.href is set using assign() method (you can also set the href property directly). This will load the SecondPage.
When MainPage.html loads, the browser URL bar correctly shows /MainPage.html and it also shows that MainPage.html was added to the history. Then, the user clicks on the "Go to SecondPage" button and the SecondPage.html is loaded. The URL bar correctly shows /SecondPage.html. The browser history now shows MainPage.html and SecondPage.html (i.e. SecondPage.html was also added to the history). Now, from SecondPage.html, if the user clicks on the browser's back button (after clicking anywhere on the page - see notes below), the history is navigated backwards and the browser will display /MainPage.html and load the content of MainPage from the cache. However, onpopstate event is never triggered as the associated event handler is never executed. The same happens if you navigate in the opposite direction, hitting the forward button.
The same behavior can be observed in both Chrome (Webkit) and Firefox browsers. Some other notes regarding this test:
- It is well known that Chrome won't trigger onpopstate event before any user interaction with the page, that's why I mentioned that the user must interact with the page first, before hitting the back button. Firefox will trigger it anyway, though.
- I also ran another test with these pages slightly modified so Chrome and Firefox's BFCache was disabled (attaching dummy onbeforeunload and onunload events). The end result was exactly the same, so I'm convinced that there is no interference from BFCache.
From Mozilla documentation, I would expect this sequence of events to trigger the onpopstate event, once the history is being navigated through user actions via back/forward buttons.
This is MainPage.html source
<!DOCTYPE html>
<html><head>
<title>Main Page</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>
$(window).bind("popstate", function (e) {
alert(document.Title + ": popstate ocurred, href is" + window.location.href);
});
$(document).ready(function(){
$("button").click(function(){
$.get("response.json", function(data, status){
window.location.assign('/SecondPage.html');
});
});
});
</script></head><body>
This is the main page <br>
<button>Go to SecondPage</button>
</body></html>
And this is SecondPage.html source
<!DOCTYPE html>
<html><head>
<title>Second Page</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>
$(window).bind("popstate", function (e) {
alert(document.Title + ": popstate ocurred, href is" + window.location.href);
});
</script></head><body>
This is the Second Page<br>
</body></html>
My question is basically: Why onpopstate is not triggered in this scenario? If this is the expected behavior, where is it documented? If it's not expected, how can I make sure that onpopstate will fire in this case?