15

I have the following handler:

        $(window).bind('pageshow', function() { alert("back to page"); });

When I navigate away from the page (by pressing on a link) and return back to the page (by pressing the "back" button), the alert() is not called (IPad 2, iOS 5.1).

What am I doing wrong please? Any other event I need to bind to?

PS: interesting that pagehide is received properly when navigating away from the page.

BreakPhreak
  • 10,940
  • 26
  • 72
  • 108

7 Answers7

11

You can check the persisted property of the pageshow event. It is set to false on initial page load. When page is loaded from cache it is set to true.

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("back to page");
    }
};

For some reason jQuery does not have this property in the event. You can find it from original event though.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
      alert("back to page");
    }
};
Mika Tuupola
  • 19,877
  • 5
  • 42
  • 49
  • 3
    It appears this is supposed to be the correct answer, but the browsers I have tried (Safari 7 and Firefox 26 on Mac OS 10.9) never set persisted to true, even though they aren't actually reloading from the server. (At this point I'm not even willing to trust their own developer tools, so I used Wireshark to verify. I'm sending cache-control headers to make a page non-cacheable, and Safari claims it's not using the cache, but Wireshark shows no traffic to the server when I click Back.) – giskard22 Dec 13 '13 at 19:09
  • Something has changed in Safari 7 then. Just tested and event.persisted is set to true in Safari 6. – Mika Tuupola Dec 16 '13 at 16:46
  • 2
    It looks like onpageshow event does not trigger at all with 6.1.1. when clicking back button... – Mika Tuupola Dec 18 '13 at 16:09
  • @giskard22 how did you fix it.. I am having the same issue. – Dilip Rajkumar Jul 07 '15 at 13:44
  • 1
    Just leaving a message to let you know this issue persist on Safari for iOS 9.3, no valid answer found yet. – Anon Dev May 03 '16 at 13:24
  • @MikaTuupola do you know of a list of all the Safari versions that do not support the `persisted` check on `pageshow`? This would allow me to disable nonsupporting versions (via css browser detection) the layer of that spinner I am trying to hide. – MeSo2 Jan 30 '23 at 16:35
7

This is likely a caching issue. When you go back to the page via the "back" button, the page is being pulled from the cache (behavior is dependent on the browser). Because of this, your JS will not fire since the page is already rendered in the cache and re-running your js could be detrimental to layout and such.

You should be able to overcome this by tweaking your caching headers in your response or using a handful of browser tricks.

Here are some links on the issue:

EDIT

These are all pulled from the above links:

  • history.navigationMode = 'compatible';
  • <body onunload=""><!-- This does the trick -->
  • "Firefox 1.5+ and some next version of Safari (which contains the fix for bug 28758) supports special events called pageshow and pagehide."
  • Using jQuery's $(document).ready(handler)
  • window.onunload = function(){};
Community
  • 1
  • 1
Brandon Boone
  • 16,281
  • 4
  • 73
  • 100
  • Thanks. I've suspected that it happens because of the caching issues. Also, IF I am right - the *pageload* and *pagehide* are just the "tricks" that are supposed to do the job (but they don't seem to work), can you please be more specific on other tricks I don't know? Ah, and I can't modify the caching headers in my case. – BreakPhreak Apr 11 '12 at 14:21
6

What you're doing there is binding the return value of alert("back to page") as a callback. That won't work. You need to bind a function instead:

$(window).bind('pageshow', function() { alert("back to page"); });
Matthew
  • 15,464
  • 2
  • 37
  • 31
  • sorry, thanks for the correction - tried it as well with no success (actually, my home-brewed example included a callback function, not the actual call). main question edited. – BreakPhreak Apr 11 '12 at 13:21
  • Finally, something that worked for the iPhone Safari back button. Thanks. – lox Apr 28 '12 at 21:48
  • This is a valuable insight. Thank you. – jfroom Jul 25 '12 at 22:39
2

I add the same problem where iOS does not always post the "pageshow" event when going back.

If not, safari resumes executing JS on the page so I though a timer would continue to fire.

So I came with this solution:

var timer;

function onPageBack() { alert("back to page"); }

window.addEventListener('pageshow', function() {
    if (event.persisted)
        onPageBack();

    // avoid calling onPageBack twice if 'pageshow' event has been fired...
    if (timer)
        clearInterval(timer);
});

// when page is hidden, start timer that will fire when going back to the page...
window.addEventListener('pagehide', function() {
    timer = setInterval(function() {
        clearInterval(timer);
        onPageBack(); 
    }, 100); 
});
0

I solved that issue like that;

$(window).bind("pageshow", function () {

    setTimeout(function () {
        back();
    }, 1000);

});

function back() {
   //YOUR CODES
}
Can Ürek
  • 641
  • 12
  • 24
  • Will this coded still work for Safari if having multiple iFrames. See @Bob's comment _The Safari "`pageshow`" / "`pagehide`" events don't get fired more than once IF an iFrame is present on the page. In my case it's the Facebook "Like button" iFrame._ ? – MeSo2 Jan 28 '23 at 20:39
  • I'm not sure, and this was a very old situation for me. Unfortunately, you should try it to be sure. – Can Ürek Jan 30 '23 at 14:20
0

you should checkout you page is has iFrame component? i dont know why , but i delete iFrame component to solve this question

0

The only way I got this to work across ALL web browsers is to disallow the caching of the page you are returning to. I know -- it is a bit radical; it would be nice to get it to work using JavaScript, but I could figure it out.

I added a Cache-Control header in my .asp pages a helpful list of most options available to add the header..

My test.asp page

<%@language="VBSCRIPT" CODEPAGE="65001" LCID=1033%>
<%
Option Explicit
SetLocale(1033)
Response.ContentType = "text/html"
Response.CharSet = "UTF-8"

Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate" ' HTTP 1.1.
Response.addHeader "Pragma", "no-cache" ' HTTP 1.0.
Response.addHeader "Expires", "0" ' Proxies.
    
%><html>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<style>
body {margin: 50px auto;text-align: center;}
a {padding: 5px;}
#spinner {width: 100%;height: 100%;background: green;position: absolute;top: 0;display:none;}
</style>
<head>
</head>
<body style="min-height: 100vh;">
Hello World!<br>
<h3 id="pagevalue"></h3>
<a href="test.asp?page=1" onclick="showSpinner();">page 1</a>
<a href="test.asp?page=2" onclick="showSpinner();">page 2</a>
<a href="test.asp?page=3" onclick="showSpinner();">page 3</a>
<div id="spinner"></div>
<script>
function showSpinner(){
    document.getElementById("spinner").style.display = "block";
}
var getUrlParameter = function getUrlParameter(sParam) {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        i;

    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');

        if (sParameterName[0] === sParam) {
            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
        }
    }
    return false;
};
document.getElementById("pagevalue").innerHTML = "page "+getUrlParameter("page");
</script>
</body>
</html>

To complete your

alert("back to page")

request, I suggest you add a tracking mechanism that keeps track of the clicks.

MeSo2
  • 450
  • 1
  • 7
  • 18