Code: PE tabs

Chapter 9 - Advanced Web Performance Optimization

Without JavaScript, the page is still accessible, showing the default content. Artz starts with the default content using standard XHTML to define the content module and uses CSS to style and position the presentation:

<link rel="stylesheet" href="/artz/a.css" type="text/css" media="screen" />
</head>
...
<div id="main"><h2>tab box</h2>
<div class="module-container">
<script type="text/javascript" src="tab-box.js"></script>
<p><a href="javascript:void(0)" class="artz-switch"></a></p>
<div id="sports-bloggers-live" class="artz-tb">
    <div class="head"><h2>SPORTS BLOGGERS LIVE</h2></div>
    <div class="desc">
        <a href="#"><img class="photo" src="i/sasha.jpg" alt="image of snowboarder
        width="75" height="75" /></a>
        <h4>'If He Wants to Ski Drunk, Then Let Him'</h4>
        <p>SBL previews Turin with figure skaters Johnny Weir and Sasha Cohen,
        snowboarder Shaun White and many more.
        <p><a href="http://sports.aol.com/bloggerslive">Hear Sports Bloggers Live</
        a> | <a href="http://journals.aol.com/dcsportsguy/mrirrelevant/entries/2262"
        target="new">Watch the SBL Video</a></p>
</div>...

Next, Artz inserts the tabs dynamically with JavaScript. The code is commented here for reference when styling, but these elements are created with JavaScript based on the text of the <h3>s in the document (the real function is abbreviated). Here is the HTML:

<!-- DYNAMICALLY INSERTED HTML (artz_tabbox_init)
    <ul class="dtabs">
        <li onclick="artz_tabbox_set(e)" class="on">SBL Audio Clips</li>
        <li onclick="artz_tabbox_set(e)">Blog Buzz</li>
        <li onclick="artz_tabbox_set(e)">Top Blogs</li>
        <li onclick="artz_tabbox_set(e)">Podcasts</li>
    </ul>
END DHTML -->

The JavaScript to add these tabs follows:

for (var i=0;i<l;i++){
    var li=ce('li');  // create a new list item (<li>) element
    li.className = c; // assign the class name to the <li> element
    c='';             // clear the class name for the future
    ac(li,ct(h3s[i].firstChild.data)) // grab the text of the <h3> element and append it to the <li>
    ae(li,'click',artz.tb.set); // assign the tb.set( ) function to the <li>'s click event
    ac(f,li); // append the <li> to the unordered list <ul>
}

Next, he displays the default tabs and matching content all within a single unordered list item (<li>) like so:

<ul class="tabs">
    <li class="tab on">
    <h3>SBL Audio Clips</h3>
    <p>Five recent guests on AOL's Sports Bloggers Live podcast:</p>
        <ul>
            <li><a href="http://us.video.aol.com/audio.full.
            adp?pmmsid=1462037" target="_blank">Dave's Football Celebrates 'One for the Thumb'</
            a></li>
            <li><a href="http://us.video.aol.com/audio.full.
            adp?pmmsid=1462036" target="_blank">The 12th Man Complains About Refs and Detroit</a>
            </li>
            ...
        </ul>
    </li>

Note the <li class="tab on"> here to set visibility to "on" for this list item with CSS. Next, Artz includes the code for the other three tabs in a similar fashion. The only difference is the lack of an “on” class to hide these tabs.

    <li class="tab">
        <h3>Blog Buzz</h3>...</li>

Now when a user clicks on another tab, JavaScript toggles the selected tab to be visible, and turns the other tabs off, completing the effect:

<li onclick="artz_tabbox_set(e)">Blog Buzz</li>

One tricky part is the "Enable AOL Accessibility" link:

<p><a href="javascript:void(0)" class="artz-switch"></a></p>

This link is dynamically updated with JavaScript to an "on" or "off" state. When accessibility is switched on with a click on the link, the following code finds the element associated with the artz-switch a(nchor) with getElementById and a class (using the custom function getElementsByClassName to manipulate elements by class and tag) and removes and adds the event listener from the accessibility links:

if (artz.toggle == null || typeof(artz.toggle) != "object") artz.toggle = new Object(
);
    artz.toggle = {

        init: function ( ) {
            var on='Enable AOL Accessibility', off='Disable AOL Accessibility';
            var s,sw;
            artz.on( )?s=off:s=on;
            sw = gc('artz-switch','a',' ');
            for (var i=0,l=sw.length;i<l;i++) {
                re(sw[i],'click',artz.toggle.set);
                ae(sw[i],'click',artz.toggle.set);
                !sw[i].hasChildNodes( )?ac(sw[i],ct(s)):sw[i].firstChild.data=s;
            }
        }

Another tricky thing that Artz did was dynamically apply an outer class, artz, to the tab box module with JavaScript. This turns on the following styles:

/* Dynamically enabled classes (artz_tabbox_init) */
.artz .artz-tb .tabs h3, .artz .artz-tb .tabs .tab {display:none;}
.artz .artz-tb .tabs .on, .artz .dtabs {display: inline;}

So, if you do not have JavaScript, the artz class never gets applied, and thus these styles never get applied. The beauty of this technique is that all of the CSS stays in the CSS, and JavaScript toggles accessibility and applies the artz class that controls visibility. The following code does that trick:

tb.parentNode.className+=' artz';
tb.className+=' artz';

For a working example and other accessible progressive enhancement techniques, see http://www.artzstudio.com/artz/ and http://en.wikipedia.org/wiki/Progressive_enhancement.