175

I need to somehow detect that the user has pressed a browsers back button and reload the page with refresh (reloading the content and CSS) using jquery.

How to detect such action via jquery?

Because right now some elements are not reloaded if I use the back button in a browser. But if I use links in the website everything is refreshed and showed correctly.

IMPORTANT!

Some people have probably misunderstood what I want. I don't want to refresh the current page. I want to refresh the page that is loaded after I press the back button. here is what I mean in a more detailed way:

  1. user is visiting page1.
  2. while on page1 - he clicks on a link to page2.
  3. he is redirected to the page2
  4. now (Important part!) he clicks on the back button in browser because he wants to go back to page1
  5. he is back on the page1 - and now the page1 is being reloaded and something is alerted like "You are back!"
Bob Kaufman
  • 12,864
  • 16
  • 78
  • 107
John Doeherskij
  • 2,269
  • 3
  • 13
  • 19
  • Instead of hacking normal user behavior why don't you try to understand why your code is not working on page load and you need the page to reload? – Lelio Faieta Mar 27 '17 at 10:59
  • 6
    @LelioFaieta I change classes to show changes. If user clicks on something the value changes in the database via ajax. When the ajax is done css class cahnge for example from `on` to `off`. And it's ok, it's saved in db, users see everything correctly. Now he clicks on some other link. For example about us page, right? Now, he is on the about us page. Be decides to go back to the previous page and clicks the back button in browser. And when he is back, he sees the changes on the page as the browser showed the page (probably some browser cahing) before he triggerd the ajax (on/off classes) – John Doeherskij Mar 27 '17 at 11:10
  • 1
    Are you using get or post for your Ajax call? – Lelio Faieta Mar 27 '17 at 11:13
  • 2
    @LelioFaieta part2.. I use also data attribute and it has no effect. Everything would be great if the page was reloaded. If I press F5 on that page the values he changed via ajax are shown. I think this is some browser chaching related issue, when the css/html part is not fully reloaded. It reloads only after pressing f5 – John Doeherskij Mar 27 '17 at 11:14
  • @LelioFaieta `$.ajax({ url: url, method: 'post', processData: false, contentType: false, cache: false, dataType: 'json', data: formData, })` Do you think that this could be by ajax? it would be great if this was the case. – John Doeherskij Mar 27 '17 at 11:15

18 Answers18

159

You can use pageshow event to handle situation when browser navigates to your page through history traversal:

window.addEventListener( "pageshow", function ( event ) {
  var historyTraversal = event.persisted || 
                         ( typeof window.performance != "undefined" && 
                              window.performance.navigation.type === 2 );
  if ( historyTraversal ) {
    // Handle page restore.
    window.location.reload();
  }
});

Note that HTTP cache may be involved too. You need to set proper cache related HTTP headers on server to cache only those resources that need to be cached. You can also do forced reload to instuct browser to ignore HTTP cache: window.location.reload( true ). But I don't think that it is best solution.

For more information check:

Ratul Sharker
  • 7,484
  • 4
  • 35
  • 44
Leonid Vasilev
  • 11,910
  • 4
  • 36
  • 50
  • Could you help the user Dhiraj he is on the right track but it's reloading two times. By the way, I have tried `window.addEventListener( "unload", function() {} );` but it's doing nothing, the back button works as before, no change whatsoever ;( – John Doeherskij Mar 27 '17 at 10:34
  • How to unload BFCache? Could you update your code with more specific info? This line `window.addEventListener( "unload", function() {} );` doesn't work. Is it complete? – John Doeherskij Mar 27 '17 at 10:48
  • Chrome history traversal is somewhat confusing. Please try `pageshow` solution. – Leonid Vasilev Mar 27 '17 at 10:53
  • Please, could you update your code with pageshow example how to refresh the page on going back with browser button? There is not much info on that page you have linked. Thank you. – John Doeherskij Mar 27 '17 at 10:55
  • What do you mean exactly by _refresh the page on going back with browser button_? – Leonid Vasilev Mar 27 '17 at 10:58
  • 1
    I still see a double load ;( Once the default Firefox (shows the old page; from browser cache perhaps?) and then the script fires again. The script will reload it to the stage that is actual, but I still see the old state for a second or so ;( I have the code inside `$(document).ready( function() { /* code here */ });` – John Doeherskij Mar 27 '17 at 11:01
  • `What do you mean exactly by refresh the page on going back with browser button?` Please, read my updated original question, I have described it in detail in 5. steps. – John Doeherskij Mar 27 '17 at 11:03
  • I want to refresh the content of the page because if I don';t the things I have changed via ajax previously are not changed for some reason when I use the back button. When I use links it shows OK. – John Doeherskij Mar 27 '17 at 11:05
  • 11
    `window.performance.navigation` is deprecated. To check the navigation type I used `window.performance.getEntriesByType("navigation")[0].type === "back_forward"` – secondbreakfast Jan 12 '20 at 23:59
  • 3
    DOES NOT work with chrome (09/2022, Chrome 105.0): `window.performance.getEntriesByType("navigation")[0].type` tells how the page was initially loaded BEFORE clicking on a link then on BackButton. If I navigate to the page, then to another, then back, I get type="navigate". If I reload, then click on a link, then back, I get type="reload". I never, ever get "back_forward" like in any other decent browser (works perfectly in FFox or Edge). Can someone help me for Chrome or is a new question needed? – fpierrat Sep 22 '22 at 13:25
81

It's been a while since this was posted but I found a more elegant solution if you are not needing to support old browsers.

You can do a check with

performance.navigation.type

Documentation including browser support is here: https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation

So to see if the page was loaded from history using back you can do

if(performance.navigation.type == 2){
   location.reload(true);
}

The 2 indicates the page was accessed by navigating into the history. Other possibilities are-

0:The page was accessed by following a link, a bookmark, a form submission, or a script, or by typing the URL in the address bar.

1:The page was accessed by clicking the Reload button or via the Location.reload() method.

255: Any other way

These are detailed here: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation


Note Performance.navigation.type is now deprecated in favour of PerformanceNavigationTiming.type which returns 'navigate' / 'reload' / 'back_forward' / 'prerender': https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/type

ChrisV
  • 8,748
  • 3
  • 48
  • 38
Lotok
  • 4,517
  • 1
  • 34
  • 44
49

Since performance.navigation is now deprecated, you can try this:

var perfEntries = performance.getEntriesByType("navigation");

if (perfEntries[0].type === "back_forward") {
    location.reload();
}
run_the_race
  • 1,344
  • 2
  • 36
  • 62
luthier
  • 2,674
  • 4
  • 32
  • 35
  • 1
    This is the most up to date answer – kvothe__ Jun 18 '20 at 05:33
  • 1
    This code needs to be combined with the code in Leonid's answer above. – gornvix Sep 16 '20 at 09:32
  • This is working fine for me. I tested in latest Chrome, Firefox, IE and Edge. Didn't check on Safari on Mac. – Tasawar Hussain Nov 12 '20 at 10:58
  • Has anyone tested this with iOS? I replaced the older performance.navigation.type method with the performance.getEntriesByType("navigation") method, and all the JS on my page stopped working on iOS. – Ben in CA Mar 05 '21 at 17:42
  • location.reload' is deprecated – anandhu Jul 19 '21 at 11:25
  • Other possible values are `reload` and `navigate`: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming/type – run_the_race Feb 16 '22 at 09:30
  • 1
    @BeninCA I have tried it in iOS. It doesn't bork the other js on my page, but it also doesn't force a reload for back button navigation – Les Nightingill Jun 30 '22 at 21:32
  • 2023, For me with Chrome its like it caches the type on the initial page load, so when you click back, it reports the original type (e.g. "navigate" or "reload"), and not that it was a "back_forward" – run_the_race Jan 25 '23 at 13:27
  • Working fine for me in Chrome 110... – John M Mar 03 '23 at 13:42
  • It's 2023 and this no longer works on Chrome... It used to work in the past. Any updated solutions? – collimarco Apr 06 '23 at 10:42
  • I know this in an update for https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation , but how do you check in the mozilla page that this answer is to be used instead of deprecated method? – Mr. Kenneth Aug 04 '23 at 00:24
34
jQuery( document ).ready(function( $ ) {
    
   //Use this inside your document ready jQuery 
   $(window).on('popstate', function() {
       location.reload(true);
   });
    
 });

This will work 100% when back or forward button has been clicked; also if using ajax.

If it doesn't -- there must be a misconfiguration in a different part of the script.

For example: it might not reload the page if some page (in the previous post) is setting the state to:

window.history.pushState('', null, './');`

so when you do use history.pushState(); make sure you use it properly!

In most cases you will use:

history.pushState(url, '', url); 

Not window.history ... and make sure url is defined.

MeSo2
  • 450
  • 1
  • 7
  • 18
Francesco
  • 539
  • 5
  • 16
  • This does NOT work in IE. https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/3740423/ – RitchieD Jan 02 '18 at 15:04
  • @RitchieD - As of today, this works well in IE11 on Windows 10. Note: I am not using EDGE. – Dan G Feb 01 '18 at 16:14
  • 1
    I would remove "true" from reload to use the HTTP cache. There's no point of reloading the assets for most cases. – konyak Feb 28 '19 at 18:22
12

An alternative that solved the problem to me is to disable cache for the page. That make the browser to get the page from the server instead of using a cached version:

Response.AppendHeader("Cache-Control","no-cache, no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "0");
Marlon
  • 1,719
  • 3
  • 20
  • 42
  • Best solution, but here is the version that I used. `Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetMaxAge(TimeSpan.Zero); Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); Response.Cache.SetNoStore();` – zeal Oct 11 '19 at 20:52
  • 2
    This looks like a server-side command. Which language is this written in? – Eric McWinNEr Mar 23 '21 at 10:38
  • 1
    At least for Firefox, `no-store` makes the difference – claasz Apr 05 '22 at 12:19
  • In ASP.NET Core 3.1 you can use attributes on the controller action: [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)], from https://stackoverflow.com/questions/36838078/back-button-issue-in-mvc-6-after-login-and-logout – AGB May 27 '22 at 15:52
11

I tried all the solutions from the previous answers. No one worked.

Finally I found this solution, which did worked:

(function () {
    window.onpageshow = function(event) {
        if (event.persisted) {
            window.location.reload();
        }
    };
})();
sipi09
  • 389
  • 4
  • 7
9

Currently this is the most up to date way reload page if the user clicks the back button.

const [entry] = performance.getEntriesByType("navigation");

// Show it in a nice table in the developer console
console.table(entry.toJSON());

if (entry["type"] === "back_forward")
    location.reload();

See here for source

kvothe__
  • 591
  • 4
  • 10
  • Has anyone tested this with iOS? I replaced the older performance.navigation.type method with the performance.getEntriesByType("navigation") method, and all the JS on my page stopped working on iOS. – Ben in CA Mar 05 '21 at 17:43
  • Is not working in Chrome. Did not try Safari. – MeSo2 Jan 29 '23 at 22:08
7

You should use a hidden input as a refresh indicator, with a value of "no":

<input type="hidden" id="refresh" value="no">

Now using jQuery, you can check its value:

$(document).ready(function(e) {
    var $input = $('#refresh');

    $input.val() == 'yes' ? location.reload(true) : $input.val('yes');
});

When you click on the back button, the values in hidden fields retain the same value as when you originally left the page.

So the first time you load the page, the input's value would be "no". When you return to the page, it'll be "yes" and your JavaScript code will trigger a refresh.

Dhiraj
  • 1,430
  • 11
  • 21
  • 2
    It doesn't work. I havetried Firefox and Chrome and it's not working. – John Doeherskij Mar 27 '17 at 10:02
  • Please, check my updated question, perhaps you and others misunderstood me. It's much more clearer now, what I want to accomplish. Thank you. – John Doeherskij Mar 27 '17 at 10:17
  • Yes i did misunderstood, Thanks for updating question in detail. – Dhiraj Mar 27 '17 at 10:18
  • now it works. However it's reloading 2 times and it looks a little weird. First time it reloads. nothing - this is the defaut browser behavior probably. The second time it reloads - via your script - the values are refreshed as it should be, but it looks bad , because it reloads two times. Any idea how to improve it a little, so the reloading looks better or reloads only once? It looks better in Chrome than Firefox, the reloading is faster, but I still see the original back state (for a second or half a second) and the script reload is only after that. – John Doeherskij Mar 27 '17 at 10:28
  • Any new idea how to fix the "double load"? – John Doeherskij Mar 27 '17 at 10:48
  • Looking for it. I am also trying to come up with some solution. I will drop a comment if i get something – Dhiraj Mar 27 '17 at 10:54
  • @JohnDoeherskij I've added a solution below as an answer that works in Safari – paulo77 Dec 01 '22 at 03:58
4

JS Solution That Works On Most Browsers

None of the many other approaches on this page worked for me, perhaps because the "bfcache" is preventing anything from happening when the user navigates back to the page. However, I found that registering a window.onbeforeunload handler works for me in most browsers, and I believe it works because it implicitly invalidates the "bfcache". Here's the code:

window.onbeforeunload = function() {
  window.location.reload(true);
}

This event may be triggered in other cases than "back" button navigation, but it my case that doesn't matter. I tested this on the following platforms on recent versions of the listed browsers in August 2021:

  • Linux: works in Chrome and Firefox.
  • Android: works in Chrome, Firefox, and Opera.
  • OS X: works in Chrome and Safari.
  • iOS: doesn't work in Safari.

In my case I don't really care about mobile. I do care about IE, but don't have access to IE, so I couldn't test it. If someone tries this on IE and can report the result in the comments that would be helpful.

Server Side Response Headers That Fix iOS Safari

I found that iOS Safari also works if I invalidate the browser cache using Cache-Control response header. I.e. sending

Cache-Control: no-store, must-revalidate

fixes iOS Safari. See this SO answer for how to set the Cache-Control response header on various platforms.

ntc2
  • 11,203
  • 7
  • 53
  • 70
2

This works in Nov 21 in latest Firefox and Chrome.

    window.addEventListener( "pageshow", function ( event ) {
     var perfEntries = performance.getEntriesByType("navigation");
     if (perfEntries[0].type === "back_forward") {
       location.reload();
     }
    });
Andi
  • 35
  • 6
  • This combination of listening for the `'pageshow'` event and then inspecting `PerformanceNavigationTiming` entries for a `'back_forward'` entry works for me whereas the other suggestions do not. – geogeo Aug 09 '23 at 19:07
1

Reload is easy. You should use:

location.reload(true);

And detecting back is :

window.history.pushState('', null, './');
  $(window).on('popstate', function() {
   location.reload(true);
});
Anton Stepanenkov
  • 1,026
  • 8
  • 15
  • Not working ;( I have tried `alert('test');` instead of `location.reload(true);` but still nothing. I have tried firefox and chrome but nothing. I have tried inside document ready, outside , but nothing works. if I try simple alert() or any jquery code tht works. I have a lot of jquery code on my page and it works. – John Doeherskij Mar 27 '17 at 10:01
  • I've edited answer, try new solution. Thing is you need to push state before, or you won't get popstate event. – Anton Stepanenkov Mar 27 '17 at 10:11
  • You have probably misunderstood whan I want. I have updated my question with a more detailed description. Please, check it again if you have time, thank you. – John Doeherskij Mar 27 '17 at 10:15
1

I had the same problem, back-button would update the url shown in location field but page-content did not change.

As pointed out by others it is possible to detect whether a change in document.location is caused by back-button or something else, by catching the 'pageshow' -event.

But my problem was that 'pageshow' did not trigger at all when I clicked the back-button. Only thing that happened was the url in location-field changed (like it should) but page-content did not change. Why?

I found the key to understanding what was causing this from: https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event .

It says 'pageshow' -event is caused among other things by "Navigating to the page from another page in the same window or tab" or by "Returning to the page using the browser's forward or back buttons"

That made me ask: "Am I returning to the page, really?". "What identifies a page?". If my back-button did something else than "returning to the page" then of course 'showpage' would not trigger at all. So was I really "returning to a page"? OR was I perhaps staying on the same "page" all the time? What is a "page"? How is a page identified? By a URL?

Turns out me clicking the back-button did NOT "change the page" I was on. It just changed the HASH (the # + something) that was part of my url. Seems the browser does not consider it a different page when the only thing that changes in the URL is the hash.

So I modified the code that manipulates my urls upon clicking of my buttons. In addition to changing the hash I also added a query parameter for which I gave the same value as the hash, without the '#'. So my new URLs look like:

/someUrl?id=something#something

Every page that my app considers to be a "different page" now has a different value for its query-string parameter 'id'. As far as the browser is concerned they are different "pages". This solved the problem. 'Pageshow' -event started triggering and back-button working.

Panu Logic
  • 2,193
  • 1
  • 17
  • 21
1

Here is a version that detects for Safari, and if detected executes the older code that is officially deprecated (but is still in Safari).

let isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
navigator.userAgent &&
navigator.userAgent.indexOf('CriOS') == -1 &&
navigator.userAgent.indexOf('FxiOS') == -1;

if(isSafari) {
    window.addEventListener( "pageshow", function ( event ) {
        let historyTraversal = event.persisted || 
                            ( typeof window.performance != "undefined" && 
                                window.performance.navigation.type === 2 );
        if (historyTraversal) {
        // Handle page restore.
        window.location.reload();
        }
    });
} else {
    let perfEntries = performance.getEntriesByType("navigation")
    if (perfEntries[0].type === "back_forward") {
        window.location.reload(true);
    }
}
paulo77
  • 174
  • 14
1

Here's a version that seems to work in older and newer mobile and desktop browsers:

window.addEventListener("pageshow", function (event) {
  var historyTraversal = event.persisted,
    perf = window.performance,
    perfEntries =
      perf && perf.getEntriesByType && perf.getEntriesByType("navigation"),
    perfEntryType = perfEntries && perfEntries[0] && perfEntries[0].type,
    navigationType = perf && perf.navigation && perf.navigation.type;
  if (
    historyTraversal ||
    perfEntryType === "back_forward" ||
    navigationType === 2 
  ) {
    // Handle page restore.
    window.location.reload();
  }
});
Mike Godin
  • 3,727
  • 3
  • 27
  • 29
0

Use following meta tag in your html header file, This works for me.

<meta http-equiv="Pragma" content="no-cache">
0

In Chrome 96 perfEntries[0].type is 'reload', when you use the back button

Andi
  • 35
  • 6
0

I recently faced the same kind of issue in one of my React applications.

Whenever you're clicking on the button to visit page 2 if you're using the history.push(url) method inside that visit page 2 button function, and then clicking on the browser back button will change the URL only, but it'll not reload that page.

To reload the page while clicking on the back button, you can use window.location.assign(url) method inside that visit page 2 button function.

example:

import {useHistory} from 'react-router-dom'

const App = () => {

const history = useHistory()

const handleClick = () => {
  // history.push('/page-2-url') // Don't use this
  window.location.assign('/page-2-url') // use this
}

  return <div>
    <button onClick={handleClick}>Go to Page 2</button>
  </div>
}

export default App;
imjoymhnt
  • 1,011
  • 11
  • 14
-1

I found the best answer and it is working perfectly for me

just use this simple script in your link

<A HREF="javascript:history.go(0)">next page</A>

or the button click event

<INPUT TYPE="button" onClick="history.go(0)" VALUE="next page">

when you use this, you refresh your page first and then go to next page, when you return back it will be having the last refreshed state.

I have used it in a CAS login and gives me what I want. Hope it helps .......

details found from here

muhammed aslam
  • 44
  • 1
  • 11