Skip to content
Share this..

Link to element IDs inside a jQuery tabs – read “Stateless”

2011 April 26
by Eddie

I recently implemented JQuery’s Tabs feature into a site I am building for a client.  My first though was “wow, that was easy.”  And then the usability issues starting making themselves apparent.

 I like stateless web. Everything is linkable and bookmarkable, and once you have something the way you want, you should be able to share it with nothing more then the unique and repeatable url.

WHat do I mean by usability issues, let me explain with a few scenarios.

Problems

Problem 1: Switching tabs is not reflected by the URL, making the page stateful

Ugh, we hate stateful web sites!

  1. Your visitor lands on PageA that has 3 tabs: Main content, Dynamic Map, and User comments.
  2. To see the maps, user clicks on “Tab2″. (URL remains unchanged)
  3. User wants to share map, and sends link to a friend, but all they see is the welcome content – OOps!

In this case user A would need to supply User B with a link, and instructions to get to the right tab. This violates the principle that the web should be stateless, and repeatable.  If content changes, the URL should too.

Problem 2:  Elements inside hidden tabs are not reachable by URL alone

  1. User A is reading the comments tab “Tab3″ and decides she wants to add her own.
  2. After supplying her info, and the CAPTCHA she submits the form
  3. Let’s suppose the user forgot to add her actual comment, and the form tries to re-render with the validation message – OOps!

Here User A expected to see the comment form again, and instead sees the page re-rendered, but Tab1, the default tab, is shown. She has no awareness that the form (on Tab3) failed, and assumes her comment was submitted.

But what if she had successfully submitted her comment? The same problem will crop up when the comment widget tries to redirect our user to her submitted comment (mysite.com/pageA#YourNewComment) Because the ID “YourNewComment” is part of the hidden content of Tab3, the page will just load Tab1, and leave our user curious.

 

Solution

Fortunately it only takes a few lines of clever jQuery code to solve these usability issues.

  1. If the current tab changes, we update the URL with the correct anchor (mysite.com/PageA#Tab2)
  2. If a URL contains the anchor of a tab, we make that tab active
  3. <The icing> If the URL contains an anchor for an element that resides inside a tab, we make the parent tab active and scroll to the specified element

I need to thank Mark Yoon for numbers 1&2 that are based on a comment he left somewhere (i;ve been googling this issue alot!)

Number 3 was my own addition, and the most critical to me, because it allows existing widgets to work inside the tabs, and makes the tabs transparent from a URLs perspective.

 

 

Alright, assume the following HTML:

<div id="tabs" style="clear:both;"> 
	<ul> 
		<li><a href="#Tab1">Tab1</a></li> 
		<li><a href="#Tab2">Tab2</a></li> 
	</ul> 
	<div id="Tab1"> 
		Content for Tab one, active by default
	</div> 
	<div id="Tab2"> 
		Content for Tab two, hidden by default
		<div id="comment-form"> A simple form to submit comments</div>
		<div id="com3"> The third comment, hidden by default</div>
		<div id="com2"> The second comment, hidden by default</div>
		<div id="com1"> The first comment, hidden by default</div>
	</div> 
</div>

So we could supply a URL for the default tab: PageA.html#Tab1.

We could supply a URL for the inactive tab: PageA.html#Tab2.

We can also supply a URL for the hidden comment #3 on Tab2: PageA.html#com3

And! If a user lands on tab1, but switches to tab2, we update the URL instantly so they can share the right tab with friends.

 

The Code

I included this code right under the call to initialize my tabs, which is also shown for illustration purposes.

				<script>
	$(function() {
		//initiate tabs
		$( "#tabs" ).tabs();
 
		//Determine is the URL contains an Anchor, and what the value is
		var anchor = $(document).attr('location').hash; // the anchor in the URL- Thanks Mike!
 
		//now the 3 scenarios we need to handle
		if($("#Tab2").find( anchor).size()>0){
			//the anchor lives in Tab2
			$("#tabs").tabs('select', 1);
		}else if($("#Tab1").find( anchor).size()>0){
			//the anchor lives in Tab1
			$("#tabs").tabs('select', 0);
		}else{
		    var index = $('#tabs div.ui-tabs-panel').index($(anchor)); //Thanks Mike! 
		    if(index >=0){
			//the anchor _is_ tab 1 or 2
			$('#tabs').tabs('select', index); 
		    }
		}
		//anchor resides outside tabs, or doesn't exist, take no action
 
 
		//This line will update our URL anytime a tab is selected - Thanks Mike!
		//setting this before now will cause odd behavior
		$("#tabs").bind('tabsshow', function(event, ui){document.location =$(document).attr('location').pathname + "#" + ui.panel.id; });
 
	});
 
</script>

That’s it! You can now ignore the tabs as far as URLs are concerned, and point to any valid element’s ID on the page!

Please let me know if anyone has found a better way to achieve these 3 goals.

7 Responses leave one →
  1. May 9, 2011

    This is the EXACT thing I was needing as well for my UI…..thanks for plugging the UI gap!

    I’m using your script above as I’m trying to link to anchor within a page with tabs from a completely other page/URL. When I click the link with the anchor tag indicated, it doesn’t find the appropriate content within the tab.

    For example:
    destination link: index.html; targeting an h3 element with id=”customItem” on tab 2
    source link: otherPage.html; a link with this target – href=index.html#customItem

    Result: I’m brought to the main content on index.html, but not brought to any subtab or the anchor I’m targeting.

    Am i understanding the purpose of this script properly? Is it not meant to link to an anchor within a tab if you are linking from a completely other page?

    Thanks…

  2. Eddie permalink*
    May 9, 2011

    Exactly right!
    Glad it helped you too

  3. November 21, 2011

    I don’t suppose you could explain in a little more detail? Does the above code depend on the exact number of tabs being known?

    I’ve got a tab setup that is generated depending on available content. My issue is a WordPress comment form inside a tab #feedback – this is the only tab I need to have this functionality

  4. Eddie permalink*
    January 14, 2012

    It does, but you could remove the else-if block, and rename the first if block to be #feedback instewad of #tab2.

    Other than that it should fly.

  5. February 4, 2012

    Hey,
    Thanks a lot for sharing this !! It helped we figure out how to deal with these Jquery UI tabs, which are really easy to implement but kind of hard to customise…

    But I came across something annoying: the JS code works well when you share the URL with the anchor, but when it’s a link within the page, it doesn’t do anything, except adding the anchor to the hash.

    Any idea how to fix that ? Thaaaaaaaanks !!!

  6. Eddie permalink*
    February 7, 2012

    Ahh, yes – an odd little side-effect of how browsers treat #hash links. Instead of making a new request to the server they just change the presentation of the current page (scroll).

    And this solution indeed depends on the onLoad event after a requested page had loaded the dom. No request from the browser means this code never gets executed. You can verify that with some logging, but I believe that was the case.

    My primary use case was showing a user’s comment after submission, which means the redirect occurred and my code were triggered. You might need to hack a solution by adding a class to in-page links (a href=”#goto” class=”class1 in-page”>GoTO! ..)

    Then set a listener on a elements with class in-page, and just flip the tabs and invoke scrollTo().

    HTH get you started, let me know what you find!!

  7. Malin permalink
    April 27, 2012

    Thanks a lot! Just what I was looking for, and a nice explanation too.

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