Expandolicious Sidebar

You may notice a new functionality in my sidebar. Using a sprinkling of JavaScript, some choice CSS, and a bit of XHTML cleanup, you can now click on the headings in the sidebar to hide or show any of the sections.

Since 72% of this site’s traffic is from yours truly, this enhancement benefits the vast majority of my site’s visitors.

Read on for the juicy details and a bit of how-to. (If you use WordPress to drive your sidebar, then this post might show you a few ways to get away from the “Giant UL” approach.)

Premise

Here’s how it works:

  1. Each H2 in the sidebar has an ID.
  2. After each H2, there’s another element that has a corresponding ID, which is the same as the H2, but with _box appended to the end. If the H2’s ID is something_squishy, then the associated DIV would have an ID of something_squishy_box. When you click on the something_squishy H2, then the something_squishy_box DIV will either appear or disappear.
  3. When the box is showing, the H2 is its usual big mighty self.
  4. When the box isn’t showing, then it’s little and quiet.
  5. Whenever the page loads, it should remember your selections from last time, but we of course can’t have a full page reload every time you click a heading. That’d just be madness.

First Step: Suitable XHTML

The first problem that I ran into is that I had already abandoned the “classic” WordPress sidebar XHTML scheme. That is, a giant UL, in which each LI contains a H2 and another UL. For some things, like my Meta, Feeds, and Author sections, I just use P and DIV tags for cleaner spacing, so I can’t rely on the LI/UL setup being consistent. But, I still want those things to be collapsable.

Also, I’ve wrapped the sidebar’s google adsense column in a floating DIV, and when a floater hovers into a UL in Mozilla Firefox, it makes the whole thing shrink in width to accomodate it, rather than keeping its full width and letting the text wrap, and so if the Pages section was to shrink, it would fubar the whole rest of the sidebar.

In short, the big UL had to go.

This actually satisfies my semantic sensibilities as well. The way I see it, sidebar is more a collection of headings and sections than it is a “list”, per se, and the standard WordPress XHTML never struck me as the most appropriate.

Also, each H2 needed a unique ID, and the box that it’s supposed to control needed a corresponding ID as well.

Breaking out of the UL

As it turns out, most sidebarish things can be done outside of a UL without much trouble. For example, the code for the Pages section changed from:

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/1.php could not be found]

to

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/2.php could not be found]

The other sections were pretty comparable to that. Just remove the LI tags that aren’t needed, and add the proper IDs.

However, the real problem came in when I got to the Links sections. Each bunch of external links has a heading and a UL, and each bunch is automatically nested in a LI. The chunker of it is that it’s all generated by one magic function: get_link_list().

Thankfully, the lovely WordPress dev team created a function just for guys like me to use in just a situation like this, and it’s called get_linkobjects(). Send it a cat_id and a sorting field, and it’ll do its darndest to get you a list of link objects that you can play with to your little heart’s content.

Here’s what I used to replace get_link_list(), which does exactly the same thing, but without the constraint of being inside a UL:

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/3.php could not be found]

The JavaScript

All of the code that I’m referring to can be found in behavior.js script that this page uses.

To recap, here’s what the script is going to do:

  1. Loop through the H2 elements, and attach the appropriate event handlers.
  2. onclick, expand or collapse the appropriate box. That is, add/remove the closed class to/from the box, and switch between the clickable and clickable_closed classes for the heading.
  3. onmouseover, add the hover class to the heading. This wouldn’t be necessary if IE supported the :hover pseudoclass for elements other than A, but alas, we live in a world where IE6 must be supported. <sigh />
  4. onmouseout, remove the hover class from the heading.
  5. Whenever we open or close something, save the state to a cookie. If the user doesn’t allow cookies, no big deal - their settings just won’t be saved, and it’ll fail silently.

expando_sidebar()

This function loops through all the H2 elements contained within the div with an ID of sidebar, attaching events.

Call this puppy in the window.onload handler.

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/4.js could not be found]

You’ll notice that it attaches expando_sidebar to the onlick event, and hoverWithClass and unHoverWithClass to the mouse(over|out) events.

expando_sidebar

This function is the onclick handler, the workhorse of the whole thing. Essentially, all it does is swap out some classes whenever you click on an H2.

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/5.js could not be found]

The Others

The other functions are some handy reusables that I use a lot. I’m not going to go into much detail about each one, but here’s the basic run-down on what they do:

addClass(lnk,cls)
lnk is a node object, and cls is the class that you want it to have. If lnk doesn’t already have cls in the className, then it adds it.
remClass(lnk,cls)
The converse of addClass. If cls appears in lnk’s className, then it removes it.
hoverWithClass
When you mouseover the element, it uses addClass to add hover to the element’s class.
unHoverWithClass
The opposite of hoverWithClass. When you mouseout, it removes hover from the className.
replace(haystack,needle,replacement)
Works just like the str_replace php function we all know and love.
createCookie, readCookie, eraseCookie
These are PPK’s creations. Check them out on QuirksMode.

Tracking the Cookies

At this point, we’ve got the JavaScript that adds/removes the classes at the appropriate times, and sets cookies. But what good is a cookie that never gets eaten up?

So, I tweaked sidebar.php a little further, changing each section so that it looks like this:

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/6.php could not be found]

Note the <?php if( $_COOKIE['schlueterica_sidebar_monthlies'] ) echo ‘ class=”clickable_closed”‘; ?> that is added to the H2 tags, and <?php if( $_COOKIE['schlueterica_sidebar_monthlies'] ) echo ‘ class=”closed”‘; ?> added to the DIV. The cookie name is changed to match each piece, of course.

The rather complicated links section ended up looking like this, with the addition:

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/7.php could not be found]

Note the added bits on lines 14 and 16.

With this addition, the PHP script reads any existing cookies and initializes the classes appropriately. This way, if you close a section and then view another part of the site, it stays closed.

The CSS

All the scripts and funky PHP wizardry comes to naught without the style and grace of CSS. The principle behind this whole thing is:

Clean XHTML to start.
JavaScript that swaps classes.
CSS that defines what the classes actually mean.

I’ve found that doing DHTML like this makes for very readable, manageable code. Every piece is tidy and in its place. If you change the behavior, content, or look/feel, you only have to do it in one place.

Here’s the CSS that got added:

[The requested file /home/yaohytmw/isaacschlueter.com/download/sidebar_revamp/8.css could not be found]

That’s all there is to it! :)

See the JavaScript all together in behavior.js.

87% of all statistics made up on the spot. [back]

Leave a Reply

Comments are moderated like crazy using a variety of plugins. There is a very high likelihood that your comment won't show up right away, especially if you have never commented here before, but it was not deleted.

Please be patient, and do not post your comment more than once. It will show up once it is approved.

You must be logged in to post a comment.