How can I use jQuery to auto-generate a menu/contents based on the headings?

In a basic XHTML document which contains some information, I’d like to have a “quick-jump” type menu of sections to be able to go to the relevant section quickly.

This is a static XHTML document, so I want all the dynamic stuff done by the browser, not the server. I figured jQuery was the way to go.

I’ve looked at the jQuery UI stuff and accordion is the closest thing I can find, but I don’t want the sections to collapse away – I want all the content showing and just a floating contents/menu.

From this:

<h2>Section 1</h2>
<p>Some information</p>
<h2>Section 2</h2>
<p>More great info</p>

I’d like to produce something like:

<ul id="menu">
  <li><a target="_blank" rel="nofollow" href="#section1">First section</a></li>
  <li><a target="_blank" rel="nofollow" href="#section2">Another section</a></li>
</ul>
<a name="section1"><h2>First section</h2></a>
<p>Some information</p>
<a name="section2"><h2>Another section</h2></a>
<p>More great info</p>

I don’t mind wrapping each individual section in a div with a class or similar, but would like the process as automated as possible, so I only need to change the actual content when I amend the document.

Any ideas?

Thanks, F.



If you want to just be able to call a function to automatically create the wrappers you could do something like this:

<ul id="menu"></ul>
<div id="sectionInfo"></div>

function addSection(name, anchor, info) {
   $("#menu").append("<li><a href='" + anchor+ "'>" + name + "</a></li>");
   $("#sectionInfo").append("<a name='" + anchor + "'><h2>" + name + "</h2></a><p>" + info + "</p>");
}

The HTML defines the containers for the sections, then the function itself adds the content with the wrappers you want. This would work well for simple text but if your section information has HTML in it as well it could get a bit messy. In that case, you might want to look into storing sections and their info in a database.

Usage:

addSection("First section", "section1", "Some information with great content");

Edit

You could then extend this to traverse the document when it’s loaded to auto call this “addSection” function.

You’ll need to define your sections with a more rigid structure so it’s easier to traverse. I’d suggest something like this:

<ul id="menu"></ul>
<div id="content"></div>

<div id='sections' style='display:none;'>
    <div>
        <h2>Section 1</h2>
        <p>Some information</p>
    </div>
    <div>
        <h2>Section 2</h2>
        <p>More great info</p>
    </div>
</div>

Then once the page is loaded, loop through the defined sections and call addSection() which transforms their content into what ever you want it to look like:

<script>
    $(document).ready(function() {
       $("#sections div").each(function() {
            addSection($(this).find("h2").first().html(), $(this).find("p").first().html());
       });
    });

    function addSection(name, info) {
       var anchor = name.replace(/ /g,'');
       $("#menu").append("<li><a href='" + anchor+ "'>" + name + "</a></li>");
       $("#content").append("<a name='" + anchor + "'><h2>" + name + "</h2></a><p>" + info + "</p>");
    }
</script>

This code is untested, but the concept should work. You could make it more efficient by moving the elements instead of copying their HTML.

Sounds like you are looking for a piece of JavaScript that generates content based on the results of a selector. Doesn’t need anything fancy to accomplish, either: