October 1, 2008 Ajax and the Back Button (Ben Dillard)
The problem:
How to deal with the back button when the URL never changes
How to allow bookmarking to work properly, resume processes
The Basic Concept
- browser history is guided by no specification, just information browser agreement
- window.history object has properties back, forward, go, and length (pages accessed in the current browser session)
- the URL needs to incorporate information about an Ajax application’s state
- doing this is basically a hack, way to create entries in the history stack without changing the url
- in most browsers, changing the #whatever in the url adds an entry to the history stack without hitting the server
- IE6 and IE7 don’t do this ![]()
- in those, we have to use a hidden iframe and load our documents into it, creating a history entry
- can use fact that, in most browsers, unsubmitted forms retain their values throughout the current session
Steps in the Process
- Trick the browser into creating a new entry in the history stack
- Stash meaningful data in that history state (in the hash token or iframe title)
- Create a timer function that waits for the hash/iframe to change as a result of user action
- Set up a callback that grabs the stashed data and passes it back into your application
- Write your application to use that data to alter its state
- Internal queue of history states is written to an internal form field, to take advantage of form persistance
Browser Issues
- Opera 9: broken timers
- Safari 2: broken history.length
- Safari 3 Win: just plain broken (3.1 is workable)
- IE8: starts to implement HTML5 history, uses the hash, browser event called onhashchange (good!)
- Chrome: doesn’t implement form persistance
Really Simple History
- the first and oldest browser history manager
- not tied to any larger framework
- uses hidden form fields to work within a session, even with interruptions
- stores state as key:value pairs
- keys live in the browser hash or an iframe
- values are JSON data stashed in a hidden form field
- so keys last across sessions, but values last only within a session
- most people get around this by just sticking everything in the hash in query-string format
dsHistory
- uses iframes across all browsers
- updates hash only to allow bookmarking
- binds functions, rather than data, to each history point
- responsibility for knowing what to do is in the history manager, not in your application
- suited for handling multiple, radically different changes of state
- doesn’t support Safari 2 or any Opera
JavaScript State Manager
- rewrite and optimization of Really Simple History
- currently jQuery plugin
- optimized for common use cases (content changes based on ajax calls)
- relies on literal ajax calls
- adds support for ajax form requests
Lessons Learned from RSH
- don’t couple too tightly to current browser limitations
- foster a broader community (than one person)
- along with that, design modularly so that different people can take different parts (in this case, different browsers)
- cover the common cases, leave bells and whistles to plugins
- Zach Leatherman has a CSS-based approach that doesn’t use setInterval
Problems
- problems with document title - gets messed up when you start using it (current document title gets inserted)
- manual URL changes aren’t handled properly in IE6/7
- in IE6/7, when you leave the site, all history menu entries for your site get collapsed
- issues with multiple iframes in complex apps
HTML5 History Specification
- it has one! yay!
- onhashchange event from the browser (implemented in IE8)
- history.pushState, history.clearState (not implemented anywhere yet)
- title changes will be able to be handled