Expand/Hide accordion feature explained

July 4th, 2009 by Tobias Leave a reply »

During the last weeks several people have asked me about the Expand/Hide functionality on the WP-Table Reloaded plugin page and the documentation page:


Example Content of Example Section

Some people asked whether it is a WordPress plugin or if I could explain how it works. That’s why I decided to write this article, so all of you can benefit from it.

The mentioned plugin and documentation pages have a lot of information on them that is divided into several sections or paragraphs as they deal with different aspects of the plugin. For readers who come to one of these pages, this information might at first be too much as they probably are not interested in all of it and just want a certain piece of information. So, why bother them with stuff they don’t want?
As I’m currently getting into the nice JavaScript framework jQuery a little bit, this seemed perfect for it. Additionally I had read the nice articles about Accordion Madness on learningjquery.com which nicely explain the usage of the functions.

So I adapted some of that code to fit my needs, with one addition: I wanted a “fall-back” for people with browsers where JavaScript is not enabled. For them the functionality should just be hidden, including the “hide” or “expand” links which wouldn’t work for them anyway. This means that I’d have to add those by the JavaScript code, and I’d also have to hide the contents with it. That way people without JavaScript will just see the complete page with all content (and possibly the stuff they don’t need).

Ok, now let me get to some code, to show you how it works and to give you an idea on how to implement it on your site, if you want.
As I said, the content of the pages is divided into sections (like “Download”, “Features”, “Screenshots”, “Demo” and so on). To group them, we’ll just enclose the content in a HTML <div> tag while the section heading will go into a <h3> tag. (It doesn’t necessarily have to be a <h3> tag, but that’s probably the most fitting on most blogs, as the <h1> and <h2> tags are probably already used for the blog and post titles.)
The result looks like this (with some arbitrary content):

<h3>Heading 1</h3>
<div class="slide">
Content of Section 1
<h3>Heading 2</h3>
<div class="slide">
Content of Section 2

Note that the <div> tags also got the CSS class “slide”. I’ll be using that as a jQuery selector later. And of course you can add as many of those sections as you want, as long as they have this structure.

Additionally to the HTML code we need to load the jQuery library and our custom JavaScript into the page. I recommend to put all code (which I’ll be showing) into a script called “page.js” which is stored in the theme folder of your WordPress. To load the files, put the following lines at the end of your page:

<script type='text/javascript' src='/wp-includes/js/jquery/jquery.js'></script>
<script type='text/javascript' src='/wp-content/themes/YOUR-THEME/page.js'></script>

Note: This is actually not the best way to load jQuery on a WordPress powered site, as e.g. a plugin might have already loaded it. So make sure this is not the case and eventually remove that line from the code above. Also, the path to the page.js needs to be changed to the correct location on your server.

Ok, let me sum up to this point: Nothing has really happened yet to users with JavaScript enabled. Nothing is “expanding” or “hiding” so far, there are not even “hide” or “expand” links, but we have laid the foundation for our JavaScript code.
This JavaScript code will add those links, hide the content that shall initially be hidden and add the actual toggle functionality.
So, here it is, the content of the page.js:

    var expandhide_text = '<span class="expand">expand</span><span class="hide">hide</span>';
    $('h3').click(function() {
        return false;

Expected more? Well, sorry to disappoint you :-)

Ok, this is not yet quite it. We have one more thing to do, but that’s CSS.
But let me first explain what the above code does.
Everything is enclosed in a jQuery(document).ready(); function block. This is a very important jQuery command, basically meaning that the enclosed code will be run as soon as the frame of the page is loaded and everything we need is available. Note that I used the complete jQuery() function instead the shortcut $(). This is to prevent errors if a second JavaScript library, like Prototype, is loaded.

The first two lines in the code then add the “expand” and “hide” links to the heading (defined as HTML in the variable expandhide_text). This HTML is appended to every <h3> tag infront of a <div> tag with the “slide” class – but only after hiding those (as they shall be hidden initially). Now, one might want that a section is not initially hidden, but still has the Hide/Expand feature. You can see that for the “Download” section on the plugin page of WP-Table Reloaded for example. But to keep things simple for now, I’ll not include how to achieve this in this post but maybe in a later one.

The next lines actually contain the magic: It tells all <h3> headings what to do, if someone clicks on them: Toggle two CSS classes (which we’ll need later) and then toggle the next DOM element (which is the <div> with the content we want to show or hide).

So, we’ve come pretty far now: If the user has JavaScript enabled, all content in a “slide”-<div> will be hidden and can be toggled when clicking on the <h3> heading above it. For this he well see an “expand” and a “hide” link next to the heading.
Well, and that’s some sort of problem: Right now, the user will see both of those links, which doesn’t make sense. And that’s where the CSS and the two mentioned CSS classes kick in. We could also have done this with JavaScript, but, hey, why not use the methods already available?!

We just need to add the following lines to the CSS (probably the file “style.css” in your theme folder):

h3 {padding-top:10px; border-top:dashed gray 1px; cursor:pointer;}
h3 span {display:none;position: absolute; right: 10px; font-size: 12px; color: gray;}
h3.slidehidden .expand {display:inline;}
h3.slidehidden .hide {display:none;}
h3.slidevisible .expand {display:none;}
h3.slidevisible .hide {display:inline;}

This code will format our <h3> headings and the “expand”/”hide” links a little bit (I just copied this from my page. It’s possible that this won’t really look good in other theme, that’s why you’ll probably have to experiment a little bit with the colors and borders.)
The first line adds a dashed border to the <h3>, to visually separate the sections a little bit. It also sets the cursor to “pointer” (usually that’s the “hand” that you see when hovering over a link). We need to do this, because we actually don’t use real <a>-links but we want to give the user the feeling we did :-)
The second line hides all <span>s that are contained in a <h3> heading. More importantly it also positions them: On my page I wanted them to be aligned to the right of the heading, be a little bit smaller and a different color.
And finally the remaining lines tell the <span>s (or better the “expand” and “hide” links) when to be visible and when to be hidden: The “hide” link shall be visible when the content is visible, and it shall be hidden, when the content is hidden. The same applies for the “expand” link, just vice versa.

And that’s basically it.
To sum up:
We created some HTML markup (<h3> headings and <div>s) for the content sections and their headings. They got some CSS classes for easier selection in CSS and JavaScript.
Then we added some JavaScript using the jQuery library. This will add the “expand”/”hide” links (Remember that we don’t need those, if JavaScript is disabled, which is the reason why we use JavaScript to add them to the page.) And it will give the <h3> headings (and the <span>s within it) their behaviour: When clicked, the content <div>s below them will be shown or hidden.
The CSS is used to show or hide the links.

I already mentioned that I have a few additional lines of code in the actual page.js used on my site, to be able to mark <div>s that shall not be automatically hidden once the page is loaded. It did not include this in my description in this post to not confuse you. But, if there’s interest, I’ll gladly write a second post on this! Just tell me.

If you have any questions, please feel free to ask or leave a comment! Also feel free to use the code whereever you like. Please keep in mind though, that I can not give support if you want to add this to your site. I just don’t have the time. Thanks for your understanding.

And one more recommendation: If you want to do this on your site, I strongly advise to use the “HTML editor” in WordPress and NOT the “visual editor” (called TinyMCE) as it most certainly will break the HTML that we need.

If you find this post useful, why not have a look at my wishlist or make a donation?