18

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!

1
  • 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. Commented Dec 13, 2013 at 19:03

3 Answers 3

26

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);
}

Update 2022:

Because window.performance.navigation.type is deprecated (ref: MDN), I updated the code to do the same thing:

if (document.addEventListener) {
    window.addEventListener('pageshow', function (event) {
        if (event.persisted || performance.getEntriesByType("navigation")[0].type === 'back_forward') {
            location.reload();
        }
    },
    false);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Firefox will correctly support window.performance.navigation.type = 2, as of FF v70.
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.

3 Comments

Although this works for Chrome 39.0.2171.95 (64-bit), it doesnt seem to do the same in iOS Chrome or Safari 8. Any advice? thanks
yeah actually i fixed those with history.popstate solution, thanks
@Pan, this does NOT work as of Chrome 39. It also still does not work as of Chrome 70.
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.

1 Comment

Why is this downvoted? This is the right approach, tested on safari.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.