Create a Dynamic Table of Contents Using MooTools 1.2

You've probably noticed that I shy away from writing really long articles. Here are a few reasons why:

Most site visitors are coming from Google and just want a straight to the point, bail-me-out ASAP answer to a question.

I've noticed that I have a hard time reading long articles. Short attention span, I guess.

When the article is long, I tend to see less comments -- both on my blog and others.

Quite frankly, if the article bombs, I feel like I wasted a bunch of time.

Say I did put together a lengthy article -- I'd want to automate a table of contents, right? Well, here's how I would do it.

The XHTML

<h1>Article Title</h1><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h2>Article Title 2 (1)</h2><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h3>Article Title 3 (1)</h3><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h3>Article Title 3 (2)</h3><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h3>Article Title 3 (3)</h3><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h2>Article Title 2 (2)</h2><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h2>Article Title 2 (3)</h2><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p> <h3>Article Title 3 (4)</h3><p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.....</p>

As you can see, the above content is really just rubbish for our example. Note the order of the "h" tags.

The CSS

#toc { float:right; border:1px solid #fc0; background:#fffea1; padding:10px; font-family:tahoma, arial; margin:0 0 20px 20px; } #toc a { display:block; margin:3px; } #toc .h1 { color:#090; } #toc .h2 { padding:0 0 0 10px; font-size:11px; } #toc .h3 { color:#f00; font-size:10px; padding:0 0 0 30px; }

The above CSS applies only to the table of contents DIV we'll be building. The JavaScript will add the "h{x}" class to the generated link to that section. Note that the TOC will start hidden.

The MooTools JavaScript

//once the dom is set... window.addEvent('domready', function() { //initial vars var finders = ['h1','h2','h3','h4','h5','h6']; var matches = []; //find the h1, which is the article title $('article-area').getElements('*').each(function(el,i) { //do we want this? if(finders.contains(el.get('tag'))) { //create anchor var anchor = new Element('a', { 'class': el.get('tag'), 'text': el.get('text'), 'href': 'javascript:;' }); //click event anchor.addEvent('click', function() { var go = new Fx.Scroll(window).toElement(el); }); //add into our matches array matches.include(anchor); } }); //should we show the toc? if(matches.length) { //create toc div, inject var toc = new Element('div', { 'id': 'toc', 'html': '<strong>Table of Contents</strong><br />' }).inject('article-area','before'); //inject the matches matches.each(function(el) { el.inject(toc); }); } });

There's a lot going on here so let me break it down. First, I initialize a few vars. The most important is "finders," which allows us to set the tags to be included in the table of contents. Next, we grab all elements inside my designated "article-area" element. If the element is in our "finders" list, we create an anchor for it, attach smooth scrolling to the anchor's "click" event, and store the anchor in our "matches" array. In the end, if we find any matches, we create the DIV and float it to the right. If not, the TOC never displays. Sweet!

Notes