Modifying browser history with Javascript
We lost the browser state when we replaced our Charts UI w/AJAX manipulation. While it’s possible to maintain state using an anchor ala Gmail (ie – gmail.com/mail?#inbox/THREAD), it breaks the separation between business and view logic. The server cannot access the state information contained in the anchor – it’s only accessible from the browser.
To maintain state, we’d need a combination of Javascript parsing and additional requests to retrieve chart data. Our views would be a confusing mess of logic. I’m glad we punted – we can maintain state in 3 lines of Javascript now.
pushState() and replaceState()
Modern browsers now allow you to modify the browser history via Javascript. Here’s an example, shamelessly lifted from Mozilla:
Suppose http://mozilla.org/foo.html executes the following JavaScript:
history.pushState(stateObj, "page 2", "bar.html");
This will cause the URL bar to display http://mozilla.org/bar.html, but won’t cause the browser to load bar.html or even check that bar.html exists.
We’re using replaceState()
, which modifies the current history item. It doesn’t create a new one. Why not pushState()
?
replaceState()
meets our needs: sharing the location in the URL bar and refreshing the page should reflect the current state of the chart.- We didn’t want small chart tweaks to pollute the browser history.
pushState()
would still require business logic in our views to support the back button. While it’s easier to access the data through thestateObj
than parsing from the anchor tag, it’s not worth the complexity in our case.
The implementation
It’s a beautiful three-liner considering past alternatives:
history.replaceState({}, 'Scout ~ Chart', '/charts?'+Chart.params());
}
Wrapup
These window.history
functions are supported in Firefox 4, Chrome 6, Safari 5, and Mobile Safari on iOS 4+.
A big thanks goes out to Rails Machine CTO Jesse Newland (and his gorgeous mane of hair) for the suggestion.