When the back button triggers popState how can I prevent a page refresh?

56,595

Solution 1

You have to make sure there is always a history state you've pushed from the current page on the history to prevent the back button from performing a page load.

If you're trying to keep the user "contained" in your web app so the back button always provides some kind of function, you need to push at least two states onto the stack and then make sure to push another state from your popstate handler.

var foo = {foo: true}; // state object
history.pushState(foo, "unused argument", "#newInitialUri");
...
var bar = {bar: true}
history.pushState(bar, "unused argument", "#newStateOfWebApp");
...
window.onpopstate = function(event){
    ...
    var baz = {baz: true}
    history.pushState(baz, "unused argument", "#baseState");
};

In the above example say we loaded '/'. The script starts executing and the browser window URI changes to '/#newInitialUri' but no page load occurs. Then immediately after, the browser URI changes to '/#newStateOfWebApp' and no page load occurs.

The user pushes the back button on their browser. Your popstate handler fires. During your handler, event.state equals foo and the browser uri is '/#newInitialUri'. No page load occurs. The handler finishes completing, calling history.pushState and now the browser uri is '/#baseState'. No page load occurs. If the user clicks back again, your popstate event will fire again, event.state will equal foo (again), the browser uri will be '/#newInitialUri' (no page load) and then it will be '/#baseState' again (no page load).

The important thing to remember is that the event.state in your popstate handler always contains the state object for the URI you've just come back to, not the one you just came from. This was confusing to me at first, but made sense when I thought about it. For example, the user may have just come back to your page after perhaps having gone off to Google. The state object is your opportunity to communicate the status of your app to your code.

Keep in mind that some browsers fire the popstate event on page load (which is what's supposed to happen according to the spec from my understanding). Be sure to check for your state object in your handler before executing your code to make sure you don't run code you don't intend to on a page load.

One final note: if you're using jQuery to handle events, you'll need to use event.originalEvent.state to refer to the state object.

Solution 2

This may help

The unload event is sent to the window element when the user navigates away from the page. This could mean one of many things. The user could have clicked on a link to leave the page, or typed in a new URL in the address bar. The forward and back buttons will trigger the event. Closing the browser window will cause the event to be triggered. Even a page reload will first create an unload event.

Reference

http://api.jquery.com/unload/

untested

    $(window).unload(function(e){    
        e.preventDefault();
        $(window).trigger('popstate ');      

    });    

    $(window).bind('popstate ',function(){

   //your ajax call here 
    });

and finally here is a DEMO click on browser's back button to see it working

update

you are right the unload be canceled but you can do some thing like

$(window).unload(function(e){
    e.preventDefault();
    $(window).trigger('beforeunload');   

});


$(window).bind('beforeunload',function(){

alert('call your ajax here');
    return '';
});

yet another DEMO

Share:
56,595
GhotiPhud
Author by

GhotiPhud

Web and Application developer mainly working in the .NET stack.

Updated on July 09, 2022

Comments

  • GhotiPhud
    GhotiPhud almost 2 years

    I am trying to modify the content in my page without a reload. Currently my code reads:

    window.onpopstate = function(event){
        // Ajax Request the Page and replace content with new content
    };
    

    This works when I push a state then trigger the popstate event, but if I press the back button in the browser it navigates to the url instead of calling my onpopstate event. How can I prevent a page refresh and update the page with my ajax call instead?

    edit: I am trying to update with pushState and popstate. I was hoping to keep my urls hash free.