As most of us probably are aware, a significant part of the HTML5 spec is the expansion of the History API.
This post will not be a super extensive discussion of this subject, especially since it’s something that I’m only now just getting into understanding better. But I thought I would put down the main components of the API, for my own quick reference, and I hope it will prove useful to my readers and those searching via Google.
Also, if you want a good introduction to the History API, including what its benefits are, see the links near the end of this post.
history.length
The length
property on the history
object tells you how many entries are in the session history. So if you’ve visited 7 pages, then arrived at another page that displays the history length, you should see 8 entries displayed (7 plus the current page, which is also part of the session).
We can prepare a silly demonstration of the length
property using the following awful code:
<a href="#" onclick="this.innerHTML = '# of items in your history: ' + history.length; return false">Click to View history.length</a>
And here’s a live version of it:
The result of clicking that link will be different for everyone, since everyone will have a different number of entries in their session history. Again, I emphasize, that’s bad code — don’t do inline click handlers like that. But it’s an easy way to demonstrate this simple property.
history.go()
This method has existed since before HTML5. The go
method takes a an integer value that tells the browser how many pages forward or backward to “go”.
So if you have the following:
history.go(3);
The browser will go forwards three entries in the current session’s history. While:
history.go(-1);
Will go back one entry in the current session’s history. If the value given is out of range, nothing will happen and there will be no error thrown. Oddly, some versions of IE allow a URL string to be used instead of an integer, indicating which exact URL in the history stack to navigate to.
Finally, the following example will reload the current page.
history.go(0);
history.back() & history.forward()
These two methods (which likewise existed prior to HTML5) do not take any arguments and do exactly what their names imply: Go back or go forward in the history stack. If there is no back or forward to go to, it will do nothing, similar to history.go()
.
As you probably guessed history.forward()
is equivalent to history.go(1)
and history.back()
is equivalent to history.go(-1)
.
history.pushState()
Here’s where we get into the real meat of the history object. This method “pushes” the provided data onto the session’s history stack, essentially adding a history item. This method takes three parameters:
- A state object, in JSON format, or another format that can be serialized. In most cases you won’t be passing any state info, but this can be useful for advanced applications.
- A page title. This will change the current page title when the history item is added. I believe browser support for this is limited; an alternative is to add the title to the state parameter and read it from there.
- The URL you want to appear in the location bar. This will not cause a page refresh (which is really the whole point of using the History API)
So you might see this:
history.pushState(null, null, 'http://www.domain.com/whatever');
As shown above, a value of null
is used for the first two parameters if you’re not passing data or a title.
history.replaceState()
The replaceState()
method does exactly the same thing as the pushState
method, using the same parameters, but the difference is that instead of adding to the history stack, it replaces the current (or most recent) entry in the history stack with the one specified.
So let’s say you visited the following URLs in the order shown:
http://www.impressivewebs.com/#one
http://www.impressivewebs.com/#two
http://www.impressivewebs.com/#three
Then you called the following code while still at the third URL:
history.replaceState(null, null, 'http://www.impressivewebs.com/#threeGone');
This will remove the third URL from the session history, replacing it with the one passed as the third value in the parameters list.
Enabling the Back Button
Of course, a lot of this would be of limited use if navigating the page using the History API disabled the back and forward buttons. By default, when history items are added and replaced, while the URL changes will be placed in the session’s history, the actual change on the page will not. But you can deal with this by listening for a popstate
event, like this:
window.addEventListener('popstate', function(e) { // do stuff here });
A popstate
event fires each time the user navigates with the back and forward buttons. So, you can listen for these events, then change the parts of your application that you want to change, depending on what URL is navigated to, what data is passed, and so forth.
history.state
Finally, the last item in this post is the state
property of the history object. Remember that the pushState
and replaceState
methods take as a first parameter a state object. After this object is passed and one of those methods is executed, you can read the data that’s passed by accessing the state
property.
Relevant Links
I’ve only briefly touched on the practical uses for these methods and properties. I highly recommend the following links for further reading on this:
- Manipulating History for Fun & Profit (Dive Into HTML5)
- Manipulating the browser history (MDN)
- A First Look at the HTML5 History API (Nettuts+)
Browser Support
You can view browser support for these features on Can I Use.
This is very nice site for me
Thanks for the interesting post. Lots learn from it
Unfortunately only ie10 support means that is too early to use this.
I’ve been using it for over a year – one just needs to make sure that there are other ways for older browsers… for me it was easy because I was just doing something simple and didn’t need to use the popstate event, so it was pretty much already retrocompatible without me doing anything (as I made my AJAX with normal link support for those who don’t use javascript, so that infrastructure was preexistent).
Thanks for this article! This is the first place that I found that detailed the state object in a practical manner :)
Shawn is right… It’s not to early. There are quite some solutions on github that can help you with the (older) browser that don’t support the History API. They will just fall back to AJAX hash banging. I use this one and it works like a charm.
https://github.com/devote/HTML5-History-API