23

As of recent safari 5 was released, and it turns out to cause some problems for my website. I have a dynamic website running classic ASP (though that shouldn't matter much) and the site has some creative use of the history stack. For instance, you can be on a page that lists products, then go to details about a product and change the product (admin-view). When you click save on the product the information is sent to the server via AJAX, and a history.back() is issued. This works great in all browsers (including safari <= 4), however, in the newly released safari 5 it stopped working. It seems that when you click back in safari 5 it doesn't actually refresh the page, it only loads it from cache, which means that the changes made in the details view isn't shown. How can I go about to make this work in safari 5 as well? This is the current code I have to turn off caching (included at the top of every page):

Dim pStr
pStr = "private, no-cache, no-store, must-revalidate"
Response.AddHeader "pragma","no-cache"      '?
Response.AddHeader "cache-control", pStr    '?  Er ikke sikker på om disse 3 siste er nødvendige.
Response.AddHeader "cache-control", "post-check=0, pre-check=0"     '?  Er ikke sikker på om disse 3 siste er nødvendige.
Response.AddHeader "Expires", "Mon, 26 Jul 1997 05:00:00 GMT"       '?
Response.AddHeader "Last-Modified", Now()
Alxandr
  • 12,345
  • 10
  • 59
  • 95

3 Answers3

46

The empty unload handler will not work anymore. Instead you can check the persisted property of the onpageshow event. It is set to false on initial page load. When page is loaded from bfcache it is set to true.

Kludgish solution is to force a reload when page is loaded from bfcache.

window.onpageshow = function(event) {
    if (event.persisted) {
        window.location.reload() 
    }
};

If you are using jQuery then do:

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        window.location.reload() 
    }
});
Mika Tuupola
  • 19,877
  • 5
  • 42
  • 49
  • 1
    Great fix - Confirmed to work as of iOS 6 (iPhone and iPad)! Thanks Mika! – Jesse Apr 07 '13 at 12:15
  • 2
    This also works on Safari 6, desktop. The old hack of window.onunload no longer works consistently-this should now be considered the 'correct' answer. – Sam Sehnert Jun 06 '13 at 20:34
  • 1
    This works on iPad. Unfortunately (for me at least), it has the side-effect of reloading the page when awaking from sleep mode. And if the user has done a bunch of changing of form elements resulting in all sorts of display changes, the user has to start over. Is there a way to reload the page only if from a back button, but not if awaking? – Chris Valdivia Oct 16 '13 at 20:37
  • You could save the state of the form to local storage. There are ready made plugins for that: https://github.com/shaneriley/jquery_remember_state – Mika Tuupola Oct 16 '13 at 20:48
  • 1
    Little bug in your jQuery version. Missing a ) before the final semicolon. – GeekyMonkey Nov 12 '13 at 14:27
  • jquery bit is missing ); on the 2nd last line – Stuart Dobson Jan 21 '14 at 23:15
  • @ChrisValdivia I feel your pain, I had the same problem, as my page had a really long form. I solved the problem by having a boolean variable be set to true when the user POST'ed the form. Then, I used the code Mika posted above, but I added a check to see if the form already had been posted. Thus, when the user presses the back button, I know I can recreate the whole page, as the data has been POST'ed, so I reload the page. But if the form has not been POST'ed, I don't reload, and so the user's form input is preserved and not lost. – René Jan 22 '14 at 10:24
  • Safari 8 has this problem too, and I got bit by it this week. – Michael Shopsin Jan 30 '15 at 20:46
  • this helps with a fix on ios 8 as well. look at twitter bootstraps navbar on ios 8 and you'll discover when using back button the expanded menu is still there!! – Kelly Milligan Mar 01 '15 at 19:33
  • You are a king and gentlemen. – Aphire Nov 03 '15 at 16:06
7

After some googeling and digging I've found a solution, though I'm not too happy about it. Setting onunload="" in the body-tag causes Safari to invalidate the page and reload it uppon window.history.back();.

Alxandr
  • 12,345
  • 10
  • 59
  • 95
  • 1
    I've been having a similar issue, except I want the user to be revalidated on browser-back (students taking turns on an iPad). The onunload = "" hack seems to work fine forcing the re-validation on Safari on a laptop, but not on mobile Safari on an iPad. Any thoughts? – John Aug 09 '11 at 04:29
3

Here's another way:

    function invalidateBackCache() {
        // necessary for Safari: mobile & desktop
    }

    window.addEventListener("unload", invalidateBackCache, false);

I chose to go this route because adding HTML (onunload="") to the body tag in .Net involved modifying three files in my case. Setting the onunload attribute in jQuery didn't solve it either.

This works for mobile Sarfari (iPad) as well.

webXL
  • 1,630
  • 1
  • 15
  • 21
  • 2
    nope, this didn't work for me either (back button on ipad). it's only working on refresh. – sirmak Feb 14 '12 at 07:14
  • 1
    The idea of this is correct / worked for me. I used the following jquery dependent code: `$(window).on('unload', function () { });` – Sam Apr 15 '14 at 23:25
  • note that unload event was reported to be problematic on recent versions on mobile Safari, so you may want to double-check – Georgii Ivankin Nov 14 '16 at 21:32