Peter Cullen Peter Cullen - 3 months ago 21
Ajax Question

How to store the state of a page between reloads?

I have a website that loads its content by the user clicking a button, then the clicks calls a javascript function that updates just the content of a central

<div>
element by changing its inner html with AJAX and jQuery.

So for example, when the visitor wants to go to my contact page, they click the contact button, and the div's content is updated to the contact form by pulling that content from an external file and using it to replace the div's
innerHTML
. The actual address of the entire page doesnt change, as the entire page isnt being reloaded, just the
innerHTML
of the div.

Further to this, my site uses PHP, and I've coded it such that various content can be populated in the div on page load by passing variables in the url. For example,
index.php?page=home
will tell the PHP script to load the home page content from an external file, while
index.php?page=contact
will load the contact form. This way search engines can find each page and their content by following these links in my sitemap.

My problem is that if a visitor clicks a button and loads different content into the div, then clicks the reload button of their browser or presses CTRL+R, the entire page reloads and the div of course reverts to its original content.

My question is, is there a way to load a particular page when the browser refreshes? For example, if the visitor has loaded the page
index.php?page=home
then clicked on the contact button and updated the div content, then pressed the refresh button of their browser, can i somehow write a script that will load
index.php?page=contact
instead, preserving the look of the page and the content?

Answer

Option 1: location.hash

Easier, but not as robust. Worth taking a look at, but if you want to store the states of multiple elements, you probably want option 2.

Here's a demonstration of the code below.

Example:

function onHashChange() {
    var hash = window.location.hash;
    // Load the appropriate content based on the hash.
}

$(window).on('hashchange', onHashChange);
$(document).on('load', onHashChange);

$('#button').click(function(){
    window.location.hash = "home";
});

This way, all you need to do is change the hash on button change and handle the page load using the hashchange event.


Option 2: History API using History.js

A little harder to implement (but not much!), but infinitely more robust. Relies on a widely used framework.

Another, and perhaps a cleaner way of doing this would be to use the History API. It allows you to change window.location without refreshing the page, allowing you to handle those changes using JavaScript.

Not all browsers support the API yet though, but you could use History.js, which provides location.hash fallbacks if needed. Here's a demo.

From History.js's github page:

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.

Example of History.js:

function onStateChange() {
    var state = window.History.getState();
    // Handle state accordingly.

    // Fetch the data passed with pushState.
    var data = state.data;
    var title = state.title;
    var url = state.url;
}

// Check the initial state.
$('document').on('load', onStateChange);

// Listen for state changes.
window.History.Adapter.bind(window, 'statechange', onStateChange);

// Any data you want to be passed with the state change.
var stateObj = { variable : 'value' } 

// Change state using pushState()
window.History.pushState(stateObj, "State name", "/page.html");

The state name is ignored by most browsers. The third parameter is the bit that gets added to the URL.