How to Make JQuery UI Tabs Linkable and Bookmarkable

2009 April 30
by kevin

With JQuery UI Tabs v.3 there isn’t an option to make the tabs bookmarkable. In other words when you click on the tabs the URL does not change therefore you can’t link or bookmark anything other than the default tab.

Here is how I solved the problem… [UPDATED!]

The old way that I solved this follows but it is such crap I should just delete it. However, I think I will keep it just to show the workings of the iterative development process - if at first you don’t succeed elegantly, try, try again!

The new way I solved this is entirely without any framework intervention - purely in javascript. And it fits the HTML paradigm better as it uses anchors (#) in the URL to reference the tabs!

Here is my entire new initTabs method (see well below for the old method where I show the HTML code snippet that goes along with this code):

function initTabs(){
  var tabIndex = {'info':0,'reviews':1,'ratings':2}
  var re = /#w+$/; // This will match the anchor tag in the URL i.e. http://here.com/page#anchor
  var match = re.exec(document.location.toString());
  if (match != null) var anchor = match[0].substr(1);
  for (key in tabIndex) {
    if (anchor == key) {
      selectedTab = tabIndex[key];
      break;
    }
    else selectedTab = 0;
  }
  tabs = $("#tabs").tabs({selected:selectedTab}); // render the tabs
        tabs.bind('tabsshow', function(event, ui) { // when tab is shown update the URL
        var re = /#w+$/;
        var url = document.location.toString();
        // to make bookmarkable
        document.location = url.replace(re, "#"+ui.panel.id);
        });
}

The following is the old way …

First off, you can’t be doing this in static HTML. You have to be working with a framework that gives you some control over what URL runs which code. I am using my own framework, pyroxide, which allows me to map URLs to controllers in python. Therefore, when I call http://somedomain.com/someplace/tab2 I map someplace to a controller and then pass in tab2 as a parameter. Now that that is done I can conditionally create HTML based on the parameter to mimic an actual unique URL for a tab on the page.

Let’s say we have the following for our tabs:

....
  <script type="text/javascript">
      $(function() {
          $("#tabs").tabs();
      });
  </script>
  <script type="text/javascript" tal:content="selectTab"></script>
<div id="tabs">
<ul>
  <li><a href="#info">info</a></li>
  <li><a href="#reviews">reviews</a></li>
  <li><a href="#ratings">ratings</a></li>
</ul>
</div>
....

If you notice the second javascript block, that is where my conditional code is going to be placed. In my case I am using simpleTAL templating so the tal:content= piece will pass in something from my code. It is just a matter of setting what I want to pass in within the context of the template.

Therefore, if I receive reviews as the parameter for the controller, meaning that the URL was http://mydomain.com/whatevercontroller/reviews I set what I want to pass in to the template as the following:

$(function(){$("#tabs").tabs("select","#reviews");});

That way, when the page is loaded JQuery UI will render the tabs and then when the second block of javascript is read it will select the “reviews” tab.

10 Responses leave one →
  1. 2009 July 6

    Hi! Could you please elaborate on how to include your newest method in an actual html file? Because im kinda new at this, but I need it desperately.

  2. 2009 July 29
    Mark Yoon permalink

    jQuery can make this even more concise (in 4 lines here for readability)

    var anchor = $(document).attr(’location’).hash; // the anchor in the URL
    var index = $(’#tabs div.ui-tabs-panel’).index($(anchor)); // in tab index of the anchor in the URL
    $(’#tabs’).tabs(’select’, index); // select the tab
    $(’#tabs’).bind(’tabsshow’, function(event, ui){document.location = $(document).attr(’location’).pathname + “#” + ui.panel.id;}); // change the url anchor when we click on a tab

  3. 2009 October 2
    Ahsan permalink

    thanks man.

  4. 2009 October 9

    your welcome!

  5. 2010 February 16
    sami permalink

    thanks for pointing me to the right direction. here’s my 2 cents to the matter.
    short n sweet ;)

    $(’#my_selector’).tabs({
    ’select’: function(){$(this).index($(document.location.hash));},
    ‘load’: function(event, ui){document.location.hash = ui.panel.id;}
    });

    i used load instead of show, since show had a strange anchoring feature, that i couldn’t override.

  6. 2010 April 21
    Stacey permalink

    Thanks. This article is a great help! I ended up using Sami’s suggested code. Mark Yoon’s suggestion worked, but I ran into the same weird anchor problem that Sami did (page would scroll).

  7. 2010 April 21
    Stacey permalink

    I take my previous comment back. Sami’s suggestion doesn’t seem to work — nothing is passed to the url when I click different tabs. Mark Yoon’s suggested solution works, but it is annoying because the tab menu links behave like anchors in that the page scrolls to the top of the ui-tabs-panel div (hides the top of my page).

  8. 2010 May 10

    Here is a solution I came up with, based on solutions posted above, and using the ‘address’ jQuery plugin: http://www.asual.com/blog/jquery/2009/04/28/introducing-jquery-address.html

    Using tabsselect on the bind removes the scrolling issue. Bookmarking, url hash replacement, and autoload from an inline anchor are supported…

    var tabs;
    tabs = $(’#tabs’);
    tabs.tabs(); // initialize tabs

    tabs.bind(’tabsselect’, function(event, ui){document.location = $(document).attr(’location’).pathname + “#” + ui.panel.id;});
    // change the url anchor when we click on a tab

    //add anchor and bookmark support to the ui tabs
    $.address.externalChange(function(event) {
    // back/forward button handler
    var i = $.address.value();
    if(i!=”/”){
    tabs.tabs(’select’, i);
    } else {
    tabs.tabs(’select’, 0);
    }
    });

  9. 2010 May 21
    Sneha S permalink

    I’ve used Sami’s solution but only one anchor is working. But others aren’t. I’ll try the last one.

Trackbacks & Pingbacks

  1. Bart's notes » Blog Archive » JQuery UI tabs with selected by #location.hash

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS