Tuesday 28 June 2011

A .NET tab list control for content managed sites

Overview

Most websites these days seem to contain tabbed content; it's a way for more information to be displayed on a page whilst still technically being above the fold, and it's historically been a very good way of organising and pooling content together. However, having a tabbed layout on your website can create a few problems too, such as:
  • How search spiders crawl your content
  • How you URL-rewrite your content so that you can drop users onto a specific page with a specific tab pre-selected for them to look at.
Possible solutions

How tabs are handled from an ASP.NET technical perspective depends largely on the content that you're displaying.

In some cases, tabbed content is minimal in size, and you can get away with creating a very fast user interface by pulling all of the content for each tab in on the preload, and then showing and hiding the containers holding the content.

In this case, if you have five tabs, you could create five hidden divs and show or hide them depending on which tab has been clicked. This approach also has the benefit of allowing search spiders to crawl all of your tabbed information in one hit, as it's held in one page.

In other cases, sites will need several tabs, each containing a LOT of content. In cases like these, it's better to call this information when it's required, ie when a user has clicked on the tab they want to see. In cases like these, it's better to pull the content in using AJAX (be it via JQuery, or via .NET update panels). I'm choosing update panels.

Pre-selecting your tab

A good idea to begin with, is that when you enter a URL such as

/this-page?tab=your-tab-name-here

Your tab should be automatically selected and loaded in. This allows users a method of getting straight into a particular part of your content, and the tabs aren't an obstruction. You can do this by checking the URL you came in on in the page_load event, and popping your active tab in the update panel.

if (!Page.IsPostBack)
{
hidValue.Value
= (0).ToString();
if (Request.Params["Tab"] != null)
{
TabName
= Request.Params["Tab"].ToString();
//ContentPageId is a global integer to hold the ID of my tab
hidValue.Value = ContentPageId.ToString();
}
}
else
{
//on postback set content type to hidden field value
ContentPageId = Int16.Parse(hidValue.Value);
}
Repeater1.DataBind();


We call the databind method for the Repeater1 object because that's what's binding our tabs to our update panel. The repeater will grab the ContentPageId, determine what tab you want to show, and set that as the active tab accordingly.

Binding our clickable tabs

Each tab within the repeater has a href with a link of /?tab=your-tab-name-here, and an onclick attribute that fires a javascript function that updates a hidden input value which will hold the ID that you can use to reference your content. This attribute then returns false so as not to get the href to fire.

So your javascript function might look something like this:

function SetHidValue(value) {
document.getElementById(
"hiddenInput").value = value;
document.getElementById(
"SubmitButton").click();
}


Each anchor tag in the repeater will look something like this:

<a href="/?tab=your-tab-here" onclick="javascript:setHidValue(14)">Tab title</a>


Where the argument passed into setHidValue() is the dynamically populated ID of the tab you're after. The methodology of using tab IDs is required in my case because I'm using a content management solution (It could be EPiServer or Umbraco for example), which will require a page ID to grab the relevant page object when I know which tab has been asked for.

Our click() event in the javascript function fires a submit button that'll trigger a postback within the scope of the update panel. Your page_load should then check to see if you've got a hidden input value, and if so, you know which tab to show. If you don't have one, the second choice should be your tab= querystring parameter.

What this means, is if you don't have javascript (or you're a search spider and you want to crawl individual tabs without the help of javascript), you can use the querystring URLs instead.

This post is going to end up being quite complicated, so if you have any suggestions or questions, please pop them in a comment, and I'll try to address them.

No comments: