HowTo: Add a jiffy table of contents to a page

When I built this version (the umpteenth) of my personal web site, I wanted to use a few more tricks I’d learned in the past few years, and thought it would be nice to make them do some of the work for me.

If you’ve seen my resume page, you might have noticed the table of contents in the upper right corner.  It’s supposed to help the intrepid wanderer jump to different spots within the page, without having to read the whole darned thing.  (ed. Yes, my resume is long, and yes, I really should do something about that).

Anyhoo…I wanted a Table of Contents, but I didn’t want to have to update it every time I changed my resume.  Ok, I don’t change my resume that often, but bear with me here.

Table of Contents - screenshot

Well, along came Prototype and Scriptaculous.  If you haven’t heard of these, they are both JavaScript “libraries”, or collections of functions and utilities, maintained by a particular community or group, which provide certain higher-level capabilities than if you just wrote JavaScript, yourself.  jQuery is another such library, and between Prototype and jQuery, I still lean toward the former.  jQuery has a more modular architecture, and a tidier core syntax.  However, I have found its extensions lacking in a lot of areas, whereas Scriptaculous, etc, seem to be more flexible.  Maybe I haven’t done enough with jQuery, who knows…

A word about using JavaScript to manipulate a page:  I tend to do this sort of thing only when the content I’m adding is not absolutely critical to the content.  The core page functions and content should always be built right into the HTML, primarily so people who don’t use JavaScript can still read your page, but also, so search engines can still find and read your content.  JavaScript is great for adding little utilities to enhance the user experience, but should rarely be the entire experience.  (I’ve violated this rule a number of times before, usually for expediency, but it ALWAYS hinders the UE, even if it’s just for Safari users =]).

As it happens, one of the neatest things about Prototype (and jQuery, for that matter), is that it’s really easy to look into a page, using JavaScript, move things around, add stuff, remove stuff, and manipulate the page, without having to constantly rewrite your HTML whenever you want to change something.

To make a long-ish post relatively short(er), let me just paste the code that builds my table of contents, and if you’d like to know more, feel free to ask…sound good to you?  Good, here ’tis:

TOC JavaScript:

  <script type="text/javascript" src="scripts/prototype.js"></script>
  <script type="text/javascript" src="scripts/scriptaculous.js?load=effects,controls"></script>
  <script type="text/javascript" src="scripts/lowpro.packed.js"></script>
  <script type="text/javascript">
    TOC = {
      show: function() {
        $("resume").select(".sect").each(function(header) {
            var totop = new Element("a", {href: "#", className: "helper"}).update("[Return to Top]");
            var url = "#"+header.id.split("_")[1];
            var title = "";
            if (header.match('h3')) {
                title = "<strong>"+header.innerHTML+"</strong>";
                header.insert(totop);
            } else {
                title = new Element("div", {className: "indent"}).update(header.innerHTML);
            }
            var entry = new Element("a", {href: url}).update(title);
            $("toc").insert(entry);
        });
      }
    };

  Event.onReady( Toc.show );
</script>

HTML:

<div id="toc"></div>
<div id="resume">
  <h3 class="sect">Summary</h3>
  <p>Twas brillig, and the slithy toves.
  <h4 class="sect">Skills</h4>
  <p>Did gyre and gimbal in the wabe.
  <h3 class="sect">Jabber</h3>
  <p>All mimsy were the borogoves.
  <h4 class="sect">Wock</h4>
  <p>And the mome wraiths outgrabe.
</div>

Walkthrough:

If you’re curious, here’s how the above works:

Event.onReady( Toc.show ); The TOC starts building with the Event.onReady at the bottom of the script. Event.onReady is a shortcut command from Lowpro, which waits until the page loads, then runs the “show” command from the “TOC” JavaScript class. The equivalent (mostly) in Prototype is

Event.observe(window, "load", function() {});
$(“resume”).select(“.sect”).each(function(header) { This command grabs all of the page elements using the CSS class “sect” from the larger container element with the HTML ID called “resume”. Once it has all of these elements, it puts them in an array, and passes the whole bunch to a function to do something with them. The “header” variable holds each one of these array items so the function has something to talk about.
var totop… This variable (totop) creates a hyperlink that will jump to the top of the page
var url… This variable creates a new URL using the ID from the element represented by “header”, and prefixes it with a pound (#) symbol.
if (header.match(‘h3′)) {} else {} This if/else block constructs a link with a certain format, depending whether the “sect” element is a H3 tag or an H4 tag. H3 tags will be displayed in bold and flush left, while H4 tags will be normal weight and indented slightly
var entry = new Element(“a”, {href: url}).update(title); This line just creates a new hyperlink (“a” tag) using the URL and Title generated above. On the page, nothing has actually happened yet
$(“toc”).insert(entry); Ahah! There’s a special DIV tag on the page, with the ID called “TOC”. This line just plunks the above element into it.

Hopefully, you’ll find the above useful, somewhat informative, and if not, vaguely unusual. At any rate, let me know if you like it…or not =]

Tags:

Leave a Reply