About

jQuery History allows you to easily track changes of the pages state by tracking URL Hashes. Supports changes triggered by bookmarks and back & forward buttons, as well as cross browser support.

This demo shows it in action, as well as providing you with tutorials and examples on how YOU can write great jQuery plugins which are configurable, extensible and translatable in minutes instead of hours.

Using jQuery History

Seeing it work

jQuery History is all about tracking URL hash changes, so to see it in action, click through the following links:

Apricots are small and orange.
Bananas are long and yellow.
Coconuts are round and hairy.

As you clicked through these, you would have noticed the the result kept changing. If you have a eye for detail, you may have noticed that the page title also changes with these state changes. All these changes happen because we have bound events to handle the changes of state happening in our web page/application.

The code responsible

The HTML:

		<div id="demo">
			<ul id="menu">
				<li><a href="#/apricots">Learn about Apricots</a></li>
				<li><a href="#/bananas">Lean about Bananas</a></li>
				<li><a href="#/coconuts">Learn about Coconuts</a></li>
			</ul>
			<div id="result">
				<div id="content">
					<div id="apricots">
						Apricots are small and orange.
					</div>
					<div id="bananas">
						Bananas are long and yellow.
					</div>
					<div id="coconuts">
						Coconuts are round and hairy.
					</div>
				</div>
				<div id="current"></div>
			</div>
		<div>
		

The JavaScript:

		$(function(){
			// Fetch the elements
			var $result = $('#result'),
				$menu = $('#menu'),
				$content = $('#content'),
				$apricots = $('#apricots'),
				$bananas = $('#bananas'),
				$coconuts = $('#coconuts'),
				$current = $('#current');
			
			// Get the tabs
			var $tabs = $content.children();
			
			// Hide all our tabs initially
			$tabs.hide();
			
			// Fetch our original document title
			var document_title = document.title;
			
			// Define our update menu function - as this is used a lot
			var updateMenu = function(state){
				// Update out tab menu
				$menu.children('li:has(a[href="#'+state+'"])').addClass('active').siblings('.active').removeClass('active');
			};
			
			// Bind a handler for ALL hash/state changes
			$.History.bind(function(state){
				// Update the current element to indicate which state we are now on
				$current.text('Our current state is: ['+state+']');
				// Update the page's title with our current state on the end
				document.title = document_title + ' | ' + state;
			});
			
			// Bind a handler for state: apricots
			$.History.bind('/apricots',function(state){
				// Update Menu
				updateMenu(state);
				// Show apricots tab, hide the other tabs
				$tabs.hide();
				$apricots.stop(true,true).fadeIn(200);
			});
		
			// Bind a handler for state: bananas
			$.History.bind('/bananas',function(state){
				// Update Menu
				updateMenu(state);
				// Show bananas tab, hide the other tabs
				$tabs.hide();
				$bananas.stop(true,true).fadeIn(200);
			});
			
			// Bind a handler for state: coconuts
			$.History.bind('/coconuts',function(state){
				// Update Menu
				updateMenu(state);
				// Show coconuts tab, hide the other tabs
				$tabs.hide();
				$coconuts.stop(true,true).fadeIn(200);
			});
		});
		

Perhaps the most important thing to take note of here, is instead of binding events to the tab menu elements directly, we instead bind to the states they cause! This is a very important design change, as by binding to the state we can now support state changes in our application - such has back and forward buttons, manual hash changes, bookmarking with states, and page refreshes - all of which will load the correct state appropriately. Whereas if we just bound to the tab menu elements directly, none of what we just listed would be possible! This design change is the core to building rich web applications!

It's also important to note why we have decided to prefix our states with a forward slash /. This is to avoid the browser from scrolling to elements which have a particular state as their ID attribute when the state is changed - this can become quite problematic. Another added benefit of using the forward slash is that Google and other major search engines are then able to recognise it as a state of your application, and thus improve your website's SEO ability. Whereas without the forward slash, Search Engines just view it as a in-page-anchor and discard it. Isn't that smart!

So that's all you need to know to get cracking. You can see installation details below. Or you can send us feedback using the button on the right. There are also a bunch of other links right up the top, and some advanced use cases down the bottom such as integration with Ajax. Good Luck and Happy Coding! :-)

Installation

Step 1. Download jQuery History, and extract it to your hard drive

As everyones extraction process is a little bit different be sure of the following:

Step 2. Move the jquery-history directory to somewhere on your webserver

Be sure to always keep the entire jquery-history directory intact; this means if you were to only move some of the files instead of moving the entire directory, then you would run into problems due to the cross directory references would no longer be working.

Step 3. Include jQuery (insert into your page's head tag)

If your page already has jQuery included then you can skip this step.

			<!-- Include jQuery (History Requirement) -->
			<script type="text/javascript" src="http://www.yoursite.com/somewhere/on/your/webserver/jquery-history/scripts/jquery-1.4.2.min.js"></script>
		

Step 4. Include jQuery History (insert into your page's head tag)

			<!-- Include History (Production) -->
			<script type="text/javascript" src="http://www.yoursite.com/somewhere/on/your/webserver/jquery-history/scripts/jquery.history.min.js"></script>
		

Advanced Usage with jQuery History

Change the State Manually

We can also change the state manually within our code by using $.History.go(state). Here is an example of this below:

		$(function(){
			$('#zucchini').click(function(){
				// Make it so when the zucchini element is clicked
				// We go to the state: /zucchini
				// We do this rather than setting the href="#/zucchini" as the element by be a DIV not a A
				$.History.go('/zucchini');
			});
		});
		

Trigger a State Handler Manually

We can also trigger a state handler manually within our code by using $.History.trigger(state). Here is an example of this below:

		$(function(){
			$('#zucchini').click(function(){
				// Make it so when the zucchini element is clicked
				// We trigger the state: /zucchini
				// However we do not change to the state. Perhaps this state should remain secret to the user?
				//  Or by changing one state, we want to change another - for instance change the main page, and change the sidebar
				$.History.trigger('/zucchini');
			});
		});
		

Using it with Ajax

There's nothing stopping us right now from using jQuery History with Ajax, such that we can truly say we are Web 2.0 gurus. But there are many complicated issue that can arise. Such as:

These are just some of the really complicated issues you may come across which are inherent in all Web 2.0 Ajax applications. Luckily we have another project which extends jQuery History to achieve Ajax functionality, solving those complicated issues (and some others that are more difficult to explain) and remaining easy to use. We call it jQuery Ajaxy and you can find it here.

Enjoy!!!

If anything isn't working the way you want it to, or if you would like to request a feature or provide praise or general feedback then be sure to click the feedback button to the right, or the "Get Support" link up the top of this page.

This work is powered by coffee and distributed for free. Donations are how we afford our coffee. Coffee is how we stay awake after our day job hours to work on things like this free open-source project which you're looking at. So go ahead, and get that warm fuzzy feeling knowing you just helped some poor fellow working after hours for free to buy his coffee. You only need to spare a few dollars, or as much as you feel this piece of work is worth. Thanks so much. Alternatively; if you are not in a donating mood, then spreading the word about this project on twitter, your blog, or whatever is just as good. You can also give praise by clicking the feedback button or visiting our "Get Support" link. Thanks a bunch, we appreciate the help deeply.

This work is licensed under a GNU Affero General Public License.