Multiple jQuery UI Tabs + fragment + history + bookmarking = Tasty!

With jQuery BBQ you can keep track of state, history and allow bookmarking multiple jQuery UI tab widgets simultaneously.. just click some tabs, use your browser's back and next buttons, reload the page.. and when you're done playing, check out the code!

Like the advanced window.onhashchange example, window.location.hash is used to store a serialized data object representing the state of multiple tab boxes. Due to the flexibility of $.bbq.pushState(), each tab box doesn't need to know the state of any other tab box to push a state change onto the history, only their state needs to be specifed and it will be merged in, creating a new history entry and a page state that is bookmarkable. Of course, if you only want to keep track of a single item on the page, you might want to check out the basic window.onhashchange example.

Savory Shish-Kebabs

This jQuery UI Tabs widget has id "more_tabs"

jQuery BBQ

And there's plenty more where that came from! Don't forget to click
here for some more down-home content.

Sweet Kielbasa

One bite of this kielbasa will have you asking for the recipe, and that's a fact.

Baby-Back Ribs

What's better than a half-rack of ribs? A full rack!

Flame-Broiled Steak

Seasoned and cooked perfectly, this amazing steak aims to please!

The code

Note that a lot of the following code is very similar to the advanced window.onhashchange example. That's intentional! They're functionally very similar, but this example is much less complicated due to jQuery UI Tabs' built-in functionality.

$(function(){
// The "tab widgets" to handle.
var tabs = $('.tabs'),
// This selector will be reused when selecting actual tab widget A elements.
tab_a_selector = 'ul.ui-tabs-nav a';
// Enable tabs on all tab widgets. The `event` property must be overridden so
// that the tabs aren't changed on click, and any custom event name can be
// specified. Note that if you define a callback for the 'select' event, it
// will be executed for the selected tab whenever the hash changes.
tabs.tabs({ event: 'change' });
// Define our own click handler for the tabs, overriding the default.
tabs.find( tab_a_selector ).click(function(){
var state = {},
// Get the id of this tab widget.
id = $(this).closest( '.tabs' ).attr( 'id' ),
// Get the index of this tab.
idx = $(this).parent().prevAll().length;
// Set the state!
state[ id ] = idx;
$.bbq.pushState( state );
});
// Bind an event to window.onhashchange that, when the history state changes,
// iterates over all tab widgets, changing the current tab as necessary.
$(window).bind( 'hashchange', function(e) {
// Iterate over all tab widgets.
tabs.each(function(){
// Get the index for this tab widget from the hash, based on the
// appropriate id property. In jQuery 1.4, you should use e.getState()
// instead of $.bbq.getState(). The second, 'true' argument coerces the
// string value to a number.
var idx = $.bbq.getState( this.id, true ) || 0;
// Select the appropriate tab for this tab widget by triggering the custom
// event specified in the .tabs() init above (you could keep track of what
// tab each widget is on using .data, and only select a tab if it has
// changed).
$(this).find( tab_a_selector ).eq( idx ).triggerHandler( 'change' );
});
})
// Since the event is only triggered when the hash changes, we need to trigger
// the event now, to handle the hash the page may have loaded with.
$(window).trigger( 'hashchange' );
});