Preserve dynamically changed HTML on back button

It's amazing, I constantly see this working in other sites but never in sites that I'm working on.

I'm bringing in new content with ajax, I know about history.js and the History API, I do not want to change the URL, just have the browser cache the new HTML content so when a user leaves the page and comes back using the back button, it still has the updated HTML.

I see this working all the time in other sites without URL changes or using the hash #.
Is there a trick to get it to work or is it randomly decided by the browser?
If I don't want to use the URL to have this information, is there an easy alternative?


Solution 1:

For about a decade and half now, I have been using two tricks that I once discovered by painful trial and error: Input field values - especially 'hidden' ones - are preserved in the browser's history along with the URL - AND - the onLoad event is called when returning to the page by the back (or forward) buttons.

This means that you can store as much 'state' as you like - in hidden fields (remember to put them in a form), and then 'redo' the changes on 'onLoad'. I usually make the 'render' part a separate function... In other words, at the time that the dynamicness is occurring, I first write to the hidden fields - then call the render function. Then I gather together all the various render functions for the various bits of dynamicness and call them from the onLoad.

I would stress that I have never gone hunting for this in any manuals - so cannot offer any assurances - but I have been using it reliably for a good while (since Netscape!!!) It works with 'many' browsers (all the IEs, chrome, FF - but as for the others, I've never tried.)

If anyone has a more 'correct' - and less tedious - way, I for one, will be very glad to hear about it. But this does seem to do the trick.

Solution 2:

Author of RES here, found your question in /r/javascript

Apparently, Firefox recently added functionality to do this on its own, but there's no "good" way to do this when the browser doesn't do it for you.

What RES used to do is add a #page=n marker where n was your page number. That way, on pageload, RES knows you must've come from the back button if there's already a location.hash -- unfortunately, this particular behavior borked up ctrl-f find in both Firefox and Chrome when a find caused you to scroll to another page (page = n+1), because a hashchange would close the find dialog which annoyed users...

So now RES does some ugly and imperfect gymnastics to guess whether or not you arrived at the page via the back button. Any time it loads a new page, it saves that number in sessionStorage (like localStorage, but local to the tab), and upon showing up via the back button it fires off a request for that page number.

However: recently I tested in FF and Chrome and it seems that hash changes no longer "cancel" the ctrl-f find dialog, so my suggestion would be that you use that. Upon pageload, if there's a hash present, load the relevant data determined by that hash.

You can, if you want to get really crazy, store the actual HTML content in localStorage and reload it on pageload via back button as well. This might not be the most efficient way of doing things, and would almost certainly cause conflicts with javascript that relies on the DOM, though, so tread with caution!

The "best" solution really depends on what exactly your site is doing / what that content looks / behaves like.

Solution 3:

You can achieve your goal using History.js like this:

function manageHistory(data){

    var History = window.History;
    if ( !History.enabled ) { return false; }        
    History.replaceState({myData: data}, null);
}

$('select.select').change(function(e) { // I am using select tag here to give an example of an HTML action triggerer

    e.preventDefault(); 

    // get data from your select tag

    manageHistory( data)


});

History.Adapter.bind(window, 'statechange', function() { 
    var State = History.getState();

    // Launch the ajax call and update DOM using State.data.myData
});

According documentation about History on Mozilla site, the PushState third parameter is:

URL — ....... This parameter is optional; if it isn't specified, it's set to the document's current URL.