title: JQuery UI Tabs: nested Tabs, AJAX loading and Back button
body: <p>I'm loading JQuery UI tabs using AJAX.</p>
  
  <p>I have 3 levels of nested UI tabs:</p>
  
  <ol>
  <li>vertical</li>
  <li>horizontal</li>
  <li>horizontal</li>
  </ol>
  
  <p>Most of the stuff is only 2 levels deep but some are 3. The issue is the 3rd level. I followed this: </p>
  
  <p><a href="http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/" rel="nofollow">http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/</a></p>
  
  <p>But it does not cover nesting of tabs.</p>
  
  <p>The layout of the page is like this:</p>
  
  <pre><code>&lt;script type="text/javascript"&gt;
      var tabs;
      var tab_a_selector;
      var tab_a_vertical_selector;
  
      $(function() {              
  
          $("#menuTabs").tabs({
              ajaxOptions: {
                  cache: false
              }
          }).addClass("ui-tabs-vertical ui-helper-clearfix"); 
          $("#menuTabs li").removeClass('ui-corner-top').addClass('ui-corner-left');
          $(".ui-tabs-vertical .ui-tabs-nav").removeClass("ui-tabs-nav").addClass("ui-tabs-nav-vert")
  
          $("#menuItem0").tabs();
          $("#menuItem1").tabs(); 
          //...
  
          /* -- enables Back button for nested tabs -- */
  
          // The "tab widgets" to handle.
          tabs = $('.tabs');
  
          // This selector will be reused when selecting actual tab widget A elements.
          tab_a_selector = 'ul.ui-tabs-nav a';
          tab_a_vertical_selector = 'ul.ui-tabs-nav-vert 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 new state
              // This is done as below to remove any state from deeper levels of nested tabs.
              state ['menuTabs'] = $.bbq.getState('menuTabs');
              state[ id ] = idx;                  
              $.bbq.pushState( state, 2 );
          });
          tabs.find(tab_a_vertical_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;  
  
              // 2 -&gt; replaces old state with new state. meaning indexes of nested tabs are removed
              $.bbq.pushState( state, 2 ); 
          });
  
          // 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' );
                  $(this).find( tab_a_vertical_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' );
  
          /* -- END enables Back button for nested tabs -- */
      });
  &lt;/script&gt;
  
  &lt;div id="menuTabs" class="tabs"&gt;
      &lt;ul&gt;
          &lt;li&gt;&lt;a href="#menuItem0"&gt;menuItem0&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#menuItem1"&gt;menuItem1&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href="#menuItem2"&gt;menuItem2&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
  
      &lt;div id="menuItem0" class="tabs"&gt;
          &lt;ul&gt;
              &lt;li&gt;&lt;a href="content/menuItem0/Intro.html"&gt;Intro&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;                       
      &lt;/div&gt;
      &lt;div id="menuItem1" class="tabs"&gt;
          &lt;ul&gt;
              &lt;li&gt;&lt;a href="content/menuItem1/Intro.html"&gt;Introduction&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href="content/menuItem1/Guide.html"&gt;Guide&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href="content/menuItem1/abc.html"&gt;abc&lt;/a&gt;&lt;/li&gt;                       
          &lt;/ul&gt;                       
      &lt;/div&gt;
      &lt;!--...--&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>The 3rd level of tabs is in the above html pages, as example in abc.html:</p>
  
  <pre><code>&lt;script type="text/javascript"&gt; 
  
      var rNumberTabs = $("#rNumber").tabs(); 
      rNumberTabs.tabs({ event: 'change' });
      rNumberTabs.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 );
      });
      tabs = tabs.add(grNumberTabs);
      // If this is triggered it leads to an infinte loop,
      // if not, I can't even browse to any other tab than the first
      // one on he third level, eg. it automatically jumps back
      // to first one.
      $(window).trigger( 'hashchange' );
  &lt;/script&gt;
  &lt;div id="rNumber" class="tabs"&gt;
      &lt;ul&gt;
          &lt;li&gt;&lt;a href="#layout"&gt;Layout&lt;/a&gt;&lt;/li&gt;       
          &lt;li&gt;&lt;a href="#prefix"&gt;Prefix&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;div id="layout"&gt;
          &lt;!-- Content here --&gt;
      &lt;/div&gt;
      &lt;div id="prefix"&gt;
          &lt;!-- Content here --&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>Any ideas how I can solve? </p>