window.onhashchange, jQuery hashchange, history.pushState and History.js

If you wish to make your AJAX website bookmark and back button friendly, you will need to use location.hash or history.pushState. Below are some short examples of how it all works.

1. Before HTML5, we needed to use onhashchange. Here’s an example of how this works. Notice we start the hash with a “!” to enable Google AJAX crawling.

<!DOCTYPE html>
<html>
<head>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script>
		$(function() {
			window.onhashchange = function () {
				alert("onhashchange = " + window.location.hash); // do something on click
			}

			alert("onload = " + window.location.hash); // do something onload

			$('#link').click(function(e) {
				e.preventDefault();
				window.location.hash = '!hello';
			});
		});
	</script>
</head>
<body>
	<a href="#" id="link">change</a>
</body>
</html>

2. If you would like a jQuery solution, you can use the jQuery hashchange plugin.

<!DOCTYPE html>
<html>
<head>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script src="http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js"></script>
	<script>
		$(function() {
			$(window).hashchange(function() {
				alert("hashchange = " + window.location.hash); // do something on hashchange
			})

			$(window).hashchange(); // force hashchange onload

			$('#link').click(function(e) {
				e.preventDefault();
				window.location.hash = '!hello';
			});
		});
	</script>
</head>
<body>
	<a href="#" id="link">change</a>
</body>
</html>

3. HTML5 introduced history.pushState, which allows you to change URLs without using hashes.

<!DOCTYPE html>
<html>
<head>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script>
		$(function() {
			window.onpopstate = function() {
				alert("onpopstate = " + window.location.href); // do something onpopstate
			};

			alert("onload = " + window.location.href); // do something on load

			$('#link').click(function(e) {
				e.preventDefault();
				history.pushState(null, null, 'hello.html');
				alert("pushState = " + window.location.href); // do something on click
			});
		});
	</script>
</head>
<body>
	<a href="#" id="link">change</a>
</body>
</html>

Don’t try this by opening a local HTML, where you see file:// in the browser URL, or you might get some security issues. The onload alert is needed on Firefox, but is redundant in Chrome and Safari.

4. If you would like a solution that will use history.pushState for modern browsers but fallback to onhashchange if history.pushState is not supported, try History.js. Make sure you first download and make jquery.history.js available, and don’t test this on a URL that starts with file://.

<!DOCTYPE html>
<html>
<head>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
	<script src="history.js/scripts/bundled/html4%2Bhtml5/jquery.history.js"></script>
	<script>
		$(function() {
			window.History.Adapter.bind(window, 'statechange', function() {
				alert("statechange = " + window.location.href); // do something on statechange
			});

			alert("load = " + window.location.href); // do something on load

			$('#link').click(function(e) {
				e.preventDefault();
				window.History.pushState(null, null, 'hello.html');
			});
		});
	</script>
</head>
<body>
	<a href="#" id="link">change</a>
</body>
</html>

Now you got a glimpse of how these work, I suggest you read Must-Know URL Hash Techniques for AJAX Applications, which gives an overview of the whole workflow.