views:

56

answers:

5

I've got a website set up with well structured pages, eg. <h1> for the website name, <h2> for the page name and <h3> for the different sections on the page.

Anyway, I was looking to set a bunch of the really long pages (an FAQ page for example) up with an "accordion" effect, with the <h3> elements being the toggle and the content directly following being toggled. But the collapsible content needs to be in it's own <div class="draw"> (or similar) and this isn't how the content is set up currently. I was hoping this was possible without touching the existing HTML and just somehow changing the DOM with JS (with jQuery assistance?) to accommodate.

I thought maybe wrapping content between the <h3> elements in a classed <div> might work but wouldn't know how to get this done. Help?

A: 

The jQuery documentation on the accordion widget is very easy to use. http://docs.jquery.com/UI/Accordion. But using the jQuery method only works if you have the structure they describe in the docs. In other words (as far as I know) it is impossible to use the jQuery accordion widget without touching your HTML. This is the structure:

<div id="accordion">
    <h3><a href="#">Tab 1</a></h3>
    <div>
        First tab content
    </div>
    <h3><a href="#">Tab 2</a></h3>
    <div>
         Tab two content
    </div>
    <h3><a href="#">Tab 3</a></h3>
    <div>
         Tab three content
    </div>
</div>

Then you would create the widget using the line of javascript:

$("#accordion").accordion();

If you wanted to use jQuery to format your HTML for you, you still need a way to select and parse your HTML. Each tab's content needs to be selectable some how. If your HTML already has the tabs separated somehow, then you need to take a look at this page http://docs.jquery.com/Manipulation. It should be pretty straightforward.

Samuel
Yeah, what I'm trying to do is create this structure unobtrusively before calling <code>$("#accordion").accordion();</code>.
Marcel
A: 

Here's one way to do it that doesn't rely on traversable DOM elements between the h3 tags. I'm not sure how efficient it is to swap out the entire contents of the body tag like this on every load though...

$(document).ready(function(){
    var content = $('body').html();
    content = content.replace(/(<\/h3>)((.|\n|\r)*?)(<h\d>|$)/gi, "$1<div class=\"draw\">$2</div>$4");
    $('body').html(content);
});

I tested this out on content formatted like so:

<body>
<h1>Title</h1>
<h2>Sub-Title</h2>
<h3>Section Title</h3>
this is some content

<h1>Title</h1>
<h2>Sub-Title</h2>
<h3>Section Title</h3>
this is some content
...
</body>
Rudism
Thanks, exactly what I was looking for. If not efficient (I've restricted it to the content area at least), it gets the job done. Regex to the rescue!
Marcel
A: 

If you're willing to consider non-JS alternatives, Stu Nicholls has some interesting html/css (no js) options on his CSS Play website:

  1. http://www.cssplay.co.uk/menu/gallery3l
  2. http://www.cssplay.co.uk/menus/tabmenu.html

(Among others)

David Thomas
A: 

I suppose it looks like this:

<html>
    <h1>site name</h1>
    <h2>page name</h2>
    <h3>section</h3>
    <p>some stuff</p>
    <p>different paragraph</p>
    <ul><li>a list</li></ul>
    <h3>next section</h3>
    <p>different stuff</p>
    ...
</html>

you could iterate over all direct children of html. At first h3 you start collection all subsequent items until the next h3. if a next h3 comes or page end you create a div, and add it after the starting h3 all collected elements should be removed from their parent (the html) and added as children of the div.

looking at http://docs.jquery.com/Traversing this should be easy. I'm not an expert on jquery, but it should be doable.

squiddle
A: 

Dave Ward of Encosia has great 10 minute tutorial on jQuery, Firebug and selectors that builds exactly what you looking for.

David Robbins