11

In a standard Java / SpringMVC / JSP / jQuery web-app, I'm trying to detect a "Back" (or history.go(-1)) event, in order to refresh (AJAX) a summary component/panel content when I return to a page (where we can change the backend data that is displayed by the summary component).

I tried the following in JavaScript (following some posts on StackExchange re how to achieve this):

<script type="text/javascript">
$(document).ready(function() {
    window.onpageshow = function(event) {
        console.log("Event:");
        console.dir(event);
        if (event.persisted) {
            alert("non-jQuery - back to page - loaded from bfcache");
        } else {
            alert("non-jQuery - loaded page from server");
        }
    };
    $(window).on("pageshow", function(event){
        console.log("Event:");
        console.dir(event);
        if (event.originalEvent.persisted) {
            alert("jquery - back to page - loaded from bfcache");
        } else {
            alert("jquery - loaded page from server");
        }
    });
});
</script>

I am running OpenSUSE Linux and have tried this with FireFox and Chrome (latest versions), but every time the event's persisted attribute is set to false (I can see this in the JavaScript console and by the alerts that pop-up from the above code). By every time, I mean, regardless of whether it was loaded from the server or shown again via the Back button (or a 'Back' link).

My intention was to make an AJAX call to reload the summary component/panel with the updated data from the server if the page was showing via the Back button or history.go(-1) call.

I also tried setting an unload handler (that does nothing) to prevent the page from being put into the bfcache but it still seems to be showing a bf-cached version and the event.persisted (or event.originalEvent.persisted) is set to false.

Is this property managed correctly on Linux? Am I doing something stupid in my code? Any help or ideas would be much appreciated, thanks!

Eoin
  • 171
  • 1
  • 2
  • 8
  • I don't think this has anything to do with Linux. I'm running into it on a Mac running OS 10.9 Mavericks with both Safari 7 and Firefox 26. I've tried every technique I can find, including having the server send cache-control headers (`Cache-Control: no-cache, must-revalidate, max-age=0`). The browsers never actually reload the page (checked via Wireshark), and event.persisted is always false. – giskard22 Dec 13 '13 at 19:03

3 Answers3

12

I have found hidden input buttons are not a reliable solution since they may hold the wrong value when the user navigates back to the page and then hits refresh. Some browsers (Firefox) retain input values on refresh so every time the user hits refresh it will refresh again since the input button holds the wrong value. This is a typical scenario for forums (user views a topic, hits the back button to go back to the list of topics, and may continue to hit refresh to check if there are new topics).

As noted by Grégoire Clermont, event.persisted is buggy in chrome (and IE) and this still hasn't been fixed for either browser as of Feb 2017. The good news is you can rely on window.performance.navigation.type == 2 for chrome and IE. Ironically Firefox is unreliable for the latter but it shouldn't matter since it is reliable for event.persisted. The following code worked for me:

if (document.addEventListener) {
    window.addEventListener('pageshow', function (event) {
        if (event.persisted || window.performance && 
            window.performance.navigation.type == 2) 
        {
            location.reload();
        }
    },
   false);
}
Tom Davenport
  • 121
  • 1
  • 6
9

This appears to be a bug in Chrome (also present in IE11).

I have found the following workaround:

<input type="hidden" id="cacheTest"></input>
<script>
  var input = document.querySelector('#cacheTest')

  if (input.value === "") {
    // the page has been loaded from the server,
    // equivalent of persisted == false
  }
  else {
    // the page has been loaded from the cache,
    // equivalent of persisted == true
  }

  // change the input value so that we can detect
  // if the page is reloaded from cache later
  input.value = "some value"
</script>

This exploits the fact that in most browsers, when the page is loaded from the cache, form fields values are also conserved.

user1003545
  • 1,928
  • 1
  • 14
  • 15
0

I know this is a bit late but this works for me:

window.onpageshow = function(e) {

    if (e.persisted) {

        alert("Page shown");
        window.location.reload();
    }
};

I don't think you need it in the document ready function, just use vanilla as above.

ChrisF
  • 127,439
  • 29
  • 243
  • 315
Chez
  • 801
  • 1
  • 8
  • 20