Skip to content

A podcast for those who design, develop and run websites.

Boagworld is the personal website of Paul (the Wurzel) Boag who lives in the heart of rural Dorset. He produces a weekly podcast along with Marcus (pop star) Lillington on all things relating to building and running websites.

Latest shows

144. Scale
On this week’s show Paul talks to Joe Stump from Digg about scalable websites, we review the best apps for web designers and investigate services for sending bulk emails.
143. Partnership
On this week’s show Paul and Marcus discuss how to promote your web application, ways to improve the client/designer relationship and tools for managing your font library.
142. Community
In this week’s show Ryan and Stanton cover the news in Paul’s absence, we’re joined by Mark Boulton to discuss design by community and Marcus reminds us to keep positive.
141. Feedback
In this week's show, Paul Annett joins us to discuss how he pushes the boundaries of CSS and we look at how to improve your website through user feedback.
140. Launch
In this week's show GetSignOff has finally launched, we talk about how to use web stats to improve your site and we answer your questions about roles with web design and should you help clients with hosting.

or view all shows

Have your say

Leave a message for the show...

Buy my book: The website owners manual. A book for all those involved in designing, developing or running websites on a daily basis.

Question: Headscape tabs

Published on: May 16, 2008 by Paul Boag

David Bridle writes: How did you get the tabbed menu to work in the headscape website? 

The navigation on the Headscape website is built using the Javascript library jQuery. I have mentioned jQuery a number of times before so I won’t bother to repeat myself here. 

I don’t claim to be a javascript expert but I have made Headscape as accessible as I know how. I am sure there will be people out there that could have done a better job but I will share what I did (for better or worse). 

I am not going to get into too much code as I am not the right person to teach that. I also think it is more important to show you the techniques rather than post code that can be copy and paste into your own site. If you want to learn how to actually reproduce what I have done then I recommend the excellent documentation on the jQuery site or the designers guide to jQuery.

Choosing AJAX

It was important to me that the content found under each tab was accessible with Javascript disabled. My initial thought was to include all of the tabs in the page load. However, it quickly became obvious that this would make the download too large and would not allow for adding content in the future.

Eventually I concluded that I wanted to use AJAX. Using Jeremy Keith’s HIJAX approach I built one page for each of the case studies found under the tabs. I then linked to these from the homepage tabs using normal hrefs. Clicking on each tab would load the appropriate page.

Screenshot of Headscape website with Javascript disabled

Each of these individual pages were complete with a header and footer as well as the content I wanted to include on the homepage. 

The Javascript

The next step was to create some javascript which prevented the default action of loading the entire page, and instead load only the portion I wanted.

This was achieved with a function that was triggered on clicking each tab. The function was attached unobtrusively (rather than included in the HTML itself) so I could easily remove it later if I wanted to alter the way the site worked.

The function carried out the following actions:

  • It captured the url of each link
    $("#csMenu a").href
  • Append to the links the specific element I wanted to import using AJAX
    var addr = $("#csMenu a").href + " #caseStudies
  • Load that content into the appropriate place on the page (which had the id = csCont)
    $("#csCont").load(addr)
  • Applied some of the inbuilt effects in jQuery to make the animation fade in and out.
  • Prevented the default action
    return false;

In reality it was slightly more complex because I needed to trigger additional functions to add a popup facility to some of the links within the imported content. However, fundamentally that was it.

The problem with AJAX

The only problem that remained were screen readers. Although the site worked with Javascript disabled the use of AJAX would confuse screen readers. Without getting too technical Screen readers are able to run Javascript but don’t always realize when AJAX has updated the page.

A lot of people cleverer than me have been struggling with this issue and failed to come up with a solution. That is why some developers such as Brothercake recommend against the use of AJAX.

I had good reasons for the choice of AJAX (which I won’t get into here) and so had to find a solution. This ended up being a simple hidden message telling screen reader users to disable Javascript. Thisl enable them to navigate the additional pages without problem. This message was the first item within the body tag and was hidden using CSS so it was only heard by Screen reader users.

No doubt I will receive criticism for this decision and to some extent rightly so. It presumes users know how to disable Javascript in their screen reader. Even if they do, it is not an ideal solution. Users should not be required to change preferences before they can view a site. However, the state of screen readers is far from ideal either, and it is was the best compromise I could find.

So there you have it. That is how I produced the tabs on the Headscape website. I would be fascinated to hear what other approaches people would have used. How could I have done it better?

Comments

Comments are for the discussion of this post. If you have other questions / comments then post them to the forum or send me an email

  • Post by Andrew Green on May 16, 2008 9:58 AM

    An approach that we're planning on using for Buy Our Honeymoon (but haven't yet done so) is to have a switch on an Accessibility Options page that will set a "no-ajax" cookie.

    Assuming then that the main pages aren't static HTML, the site will check for the presence of this cookie and, if it's there, omit the Javascript for the Ajax functions from the delivered page. That way you can retain some useful progressive enhancement with Javascript, whilst allowing users to disable the Ajax stuff if they want to.

    Of course, the link to the Accessibility Options page needs to be non-Ajax itself in the first place!

    Cheers,
    Andrew.

  • Post by Cole Henley on May 16, 2008 11:26 AM

    Interesting post Paul.
    The simplicity and power of jQuery is making me much more experimental in my use of ajax. One question/thought - if your message for screenreaders relates to the use of javascript on the site then why not use javascript to add it so that with javascript disabled screen reader users won't get a message that doesn't relate to them?
    Have seen this a lot where message relating to behaviour are hard-coded into the HTML (as a handle to be manioulated by javascript) when every other aspect of a site's behaviour has been carefully separated/progressively enhanced/gracefully degraded (insert catchphrase of choice).
    Just a thought,

    Cole

  • Post by Warren Buckley on May 16, 2008 11:32 AM

    Hi Paul,
    I have learnt something new about the jQuery library which is the ".load" event. I like the idea of how you loaded in external content from another page of your site.

    I like that this will degrade gracefully if JavaScript is disabled. In my personal opinion I think you should only do optimisation for screenreaders if your stats show you that people are browsing to your site using a screen reader.

    Additionally I don't think many screenreader users will be reading a site about managing websites in my opinion, your audience will be people who will most likely be running the latest browser versions and operating systems, due to the background of the subject.

    Anyway my 2 cents worth, as always keep up the good work.

    Thanks,
    Warren

  • Post by Cole Henley on May 16, 2008 11:49 AM

    @warren

    Nice thought but web stats won't pick up screen reader use. Screen readers do not themselves view web sites (the exception perhaps being the use of text-based browsers such as Lynx) but rather sit over the users web browser of choice.
    Therefore, the header requests that generate your server stats (or alternatively the javascript requests that generate client-sided web traffic statistics) will only show the web browser being used and not the tool that is being used to interpret what the browser returns,

    Cole

  • Post by Paul Boag on May 16, 2008 3:59 PM

    @Andrew... love the cookie approach. I'll have to think about it some more but at first glance it sounds like a winner.

  • Post by Rory Fitzpatrick on May 18, 2008 1:10 PM

    Thanks for the post Paul, some responsible scripting techniques on the go there!

    I had thought that screen readers wouldn't pay attention to hidden content, but on closer inspection you've used some nifty negative positioning which I assume will work?

    For an accessible approach to Ajax, check out the W3C ARIA spec (http://www.w3.org/WAI/intro/aria), it allows you to mark an area of a page that might be updated via Ajax and alert the browser to when this happens. Its not got very wide implementation yet, only FF3 and Webkit as far as I know, but its a promising solution.

    Cheers
    Rory

  • Post by Simon Griffiths on May 20, 2008 2:11 PM

    I'm not sure why you didn't use CSS to do this in the first place but I am guessig it is because of browser compatibility. Have you had a look at the menu system developed by Steve Gibson that does the SecurityNow podcast? He has opensourced the code at http://www.grc.com/menu2/invitro.htm.

    The interesting thing about this is that it is pure CSS, and is compatible with all browsers pretty much (look at the code and you will see he has spent a lot of time on this). In theory you could use this to do pretty much the same thing, with no scripting at all, and therefore maximum accessibility.

  • Post by Damien Lebrun on May 22, 2008 3:48 PM

    @Simon: the Ajax solution scales better.

    Each case study has its own page, and the home page will display only 6 of them. The Ajax solution avoid duplicate content without page reload.

    @Paul: a solution that might work would be to use a fragment identifier:

    - Here's a typical case study link href: "/clients/xyz.htm";
    - with js on, it becomes "#studycase:xyz";
    - when the link is clicked "/clients/xyz.htm" is loaded and inserted in an element with the id "studycase:xyz" and the even should not be cancelled so that the browser focus on the "studycase:xyz" element.

    If the focus can happen after the new content is inserted (is it possible?), the feedback won't only be visual and it should be working with a screen reader as well.

    Also using something like the history plug-in (http://plugins.jquery.com/project/history) it won't break the back button and will allow bookmarking the case study.

  • Post by Gilbert on May 23, 2008 8:08 AM

    I was wondering what sort of effect the single page site approach was having on your stats? Specifically pgae views in the traditional sense.

    The AJAX approach of loading the case study fragment from another page would mean that in things like Google Analytics, looking at a case study wouldn't register as a page view.

    I guess if you're using stats from log files, looking at a case study would register as a page view.

    Then I guess you could also just look at where people were actually clicking on the page.

    There you go I've answered my own question I think.

  • Post by Ralph Brandi on May 30, 2008 8:25 AM

    Paul,

    Rather than setting up a separate accessibility page as Andrew suggests, perhaps a better approach would be to just place the option of whether to use Ajax or not at the head of the page. This is the approach I took on a site for the North American Shortwave Association. One section of the site contains a database of shortwave radio stations that the club's members have heard over the years. I used the opportunity of creating the site a couple of years ago to teach myself Ajax, but part of the audience for the site is blind, so I had to make sure it was accessible. My solution was to put a couple of radio buttons at the top of the page asking users if they wanted to open the details within the page or in a new page. Then the event handler for each item checks to see if the choice to open within the page is checked. If it is, the Ajax query is used; if it's not, the PHP-based query is used. I also set a cookie when the radio buttons are checked so that the chosen option is retained. You could throw this option off the edge of the page; I chose to leave it visible for everyone. I also use the selection of option to define whether sorting of the table is done in page or with a page refresh (but don't mention that in the radio buttons; the label would get too long if I did).

    You can see this in action on the NASWA site at http://www.naswa.net/logs/. Search for a country like "United Kingdom" and you'll get a number of results, along with the radio buttons I mentioned. I would probably write the Javascript there a little differently if I were creating the site today, but you'll get the idea.

Leave a comment

Additional Information

Supporting boagworld

Boagworld only exists thanks to the kind support of the following people. Check them out.

Speaking and writing

View Paul's current location, speaking engagements and various online ramblings:

Succoured by feed.informer.com