9

Please Note: I am not trying to detect that the back button was clicked. I don't care about that.

I just want to know that they page was loaded on a back navigation. I want to display a warning to my user in one place of my application if they click the back button advising them to refresh.

Edits:

1) I do want my pages to cache. We live in a mobile world now. Not caching is a bad practice.

2) I would like this feature to be URL agnostic. Decoupling is good practice.

Jordan
  • 9,642
  • 10
  • 71
  • 141
  • If you know the URL of the page they would have clicked back from, you could check the value of [document.referer](https://developer.mozilla.org/en-US/docs/Web/API/Document/referrer). Otherwise I don't know that this is possible. There is a [window.history](https://developer.mozilla.org/en-US/docs/Web/API/Window/history) element but I don't think there's any way to tell if the current state is the last one in the history or not. – Hayden Schiff Mar 18 '15 at 15:21
  • Have a look at [window.onpopstate](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onpopstate), I think that is as close as you can get to a behaviour like the one you are describing – Danilo Mar 18 '15 at 15:27
  • I would rather have something that is decoupled from the URLs. – Jordan Mar 18 '15 at 15:31
  • You should look on js history libraries, that allow you to save states and handle forward/back navigation – Hacketo Mar 18 '15 at 15:39
  • Is there a forward stack in the history API? – Jordan Mar 18 '15 at 15:50
  • It would seem that this is not currently possible unless you can associate some data with an element in the history journal. That is the scope I would need to work with to accomplish this, a revisit on this page at this time that is not also a refresh. – Jordan Mar 18 '15 at 15:57

6 Answers6

5
<script>
if (history.state !== null  &&  +history.state < history.length)
{
    alert("refresh needed");
    history.replaceState(null, "", window.location.href);
}
else
{
    history.replaceState(history.length, "", window.location.href);
}
</script>

The first time the page loads, this stores the current length of the history (which is also the page's position in the history) into the history itself, without changing the browser's location or otherwise modifying the history. On a revisit, it checks whether that position is at the end of the history - if not, there's been some back-navigation. It then alerts and clears the stored position.

Pros:

  • Does not trigger alert on refresh.

  • Does not trigger alert if page is visited again later, either in the same tab or a different one.

Cons:

  • Cannot distinguish between forward-navigation and back-navigation. I.e., if the user goes back further than this page and then navigates forward to it, it will still alert, because some back-navigation was used to get here. However, I would think that even in this situation, you would want the user to refresh.

  • Only alerts once. If the user then goes forward and back again, it won't alert again. Since the user has already been notified, perhaps this is not important.

radiaph
  • 4,001
  • 1
  • 16
  • 19
  • I'm not doing any alerts. I'm going to be showing a bootstrap alert. So these cons might not be a big deal. I'm going to try this out. – Jordan Mar 18 '15 at 17:32
  • Clearing the state is necessary to prevent the alert from occurring again after refresh. A refresh doesn't change the page's position in the history, so the stored position would still be less than history.length. – radiaph Mar 18 '15 at 17:59
  • This is by far the best answer out there! – shramee May 08 '18 at 18:15
5

Here is a simple method. It will detect the page was loaded from both back and forward navigation though.

if(window.performance.navigation.type === 2) {
   // the page was navigated to via the forward or back button
   // refresh
}

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation

  • This probably would have worked, but I don't even work for that company any more let alone on that project. So I can't really test it. :) – Jordan May 11 '18 at 20:16
  • lt's worth noting that Performance.navigation is deprecated now – Leon Segal Jun 17 '22 at 10:00
2

@jQuery.PHP.Magento.com beat me to it, but you can use localStorage without needing to track particular URLs:

<script>
window.onbeforeunload = function()
{
    localStorage.setItem("beenHere", true);
}

if (localStorage.getItem("beenHere"))
{
    alert("Please refresh");
    localStorage.removeItem("beenHere");
}
</script>

"beenHere" would need to be a different string for different pages, but can be symbolic, not a precise URL.

EDIT: Wait, noticed a problem: this will alert when you refresh. Will have to think about it more.

radiaph
  • 4,001
  • 1
  • 16
  • 19
  • Great answer :) Plus one ! :) – Pratik Joshi Mar 18 '15 at 15:43
  • But you are not detecting page back navigation at all. You are detecting revisit which is something totally different. Say for example someone goes to this page, then goes away for some time, then on a different work unit comes back to this page. No back navigation happened, but they would still get this message. – Jordan Mar 18 '15 at 15:46
  • I do not believe there is a cut and dry solution that uses local storage. Local storage is the wrong scope. – Jordan Mar 18 '15 at 15:49
  • @Jordan , then what would you suggest? – Pratik Joshi Mar 18 '15 at 15:49
1

Use following:

On 2nd page only use :

localStorage.setItem("urlnow", document.URL);

On 1st page check

if(localStorage.getItem("urlnow") == Your_URL_OF_Next_Page)){
 window.location.reload()
}

There is no such method to check Next page url.Just you can have document.referrer which is not useful in your case, so you need to hardcode Next page url to check if the localstorage variable was set. Means the user went on that page. You can destroy localstorage too as per your requirement.

Edit : Better way

On 2nd page use :

$(document).ready(function(){

    localStorage.setItem("nextPageHit",1));

})

On 1st page

$(document).ready(function(){

    if(localStorage.getItem("nextPageHit")){
         window.location.reload();//Forcible reload.

        localStorage.setItem("nextPageHit",0);
    }

})
Pratik Joshi
  • 11,485
  • 7
  • 41
  • 73
  • Don't want to have to know urls. Sorry, I should have put that requirement in my question. – Jordan Mar 18 '15 at 15:34
  • Dont you know url of next page ? – Pratik Joshi Mar 18 '15 at 15:35
  • It is known as decoupling. I want to write something that I can use on any page in any order. – Jordan Mar 18 '15 at 15:38
  • @Jordan , what issue you are experiencing now from my New edited solution ? – Pratik Joshi Mar 18 '15 at 15:52
  • Local storage is the wrong scope. Someone hits this page again in a separate work unit and it will warn them. Refresh and it will warn them. Local storage is not the answer it is too persistent. I need something that sticks with this page at this time. And something that won't trigger when the user refreshes. – Jordan Mar 18 '15 at 15:53
  • But when user refreshes then your issue is solved. See, user will goto page 2 , then localStorage is set, he comes back then his PAGE is reloaded.You will reload for him. If you **Really** want to reload the page ,**Do it**, dont wait for user's response. – Pratik Joshi Mar 18 '15 at 15:56
  • @Jordan check solution now, force reload, its simple. – Pratik Joshi Mar 18 '15 at 15:57
  • That violates requirement 2 above. I don't want to do that for the same reason I don't want to turn off caching. I don't want to reload the page. I just want to advise the user to do this. You never turn off caching or automatically reload pages when you have mobile users that potentially have restricted bandwidth and download caps. – Jordan Mar 18 '15 at 16:03
0

It might be better to not cache the pages so the user doesn't need a refresh. Adding the following tag in your disables caching of the page.

<meta http-equiv="Cache-Control" content="no-store" /> 
0

You need to say the browser not to save the cache of this page by setting the response headers.
Using Ruby on Rails:

response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate' # HTTP 1.1.  
response.headers['Pragma'] = 'no-cache' # HTTP 1.0.  
response.headers['Expires'] = '0' # Proxies.  
Shiva
  • 11,485
  • 2
  • 67
  • 84
  • you can refer to this question for more details http://stackoverflow.com/questions/19098663/auto-loading-lib-files-in-rails-4 – Shiva Mar 18 '15 at 15:35