Wednesday, June 4, 2008

A Simple YUI-Powered Accordion Widget

Accordion menus are all the rage at the moment (as are Carousels and Sliders). I wanted a snazzy way to show my resume during my recent job search so I went looking for an accordion-style menu. I had these requirements in mind:

1) be lightweight
2) use unobtrusive Javascript techniques (ie not have scattered Javascript all over the markup)
3) use simple CSS to make it look nice
4) needed to support both single and multiple sections opened at a time.

My search came up short. Most were overly complicated, or they required libraries other than what I already have running on my sites. Too much bloat. I guess I'd have to write my own. Since I already use the *radical* YUI libraries on my sites, making it YUI-powered was the way to go for me. I set my goal to <100 lines of good OO unobtrusive Javascript. The current version sits at 80 LOC with lots of comments. Here's what it looks like:
**note that the size of the menu is dynamic, however to embed it in a blogger post I had to use the ol <iframe> trick.

JILS_accordion will make an unordered list <ul> of your choice into a spiffy animated accordion menu. These are the steps to get it going on your site:

Massage the Markup:


While any <ul> will work, you need to make sure it has an id.
Next you need to create two divs inside of each <li>. One div for the title with class accordionTitleDiv, and one for the content with class accordionContentDiv The markup should look like this:
*Note it is not necessary for the individual <li> elements to have id's

Include the JS & CSS Files, initialize the JILS_accordion object:



The first argument for the constructor function is an object that can be left empty '{}' or you can specify things like {multiSelect:true, sectionExpandedSize:10}, etc. The code is heavily commented so most front end guys will be able to figure it out.

Open accordion example in a new page

Updated to v 1.1b following a heads up from Satyam that the widget was broken in IE. Turned out to be a different bug. A 'dangling' comma after the last item in my callback object definition was the culprit, but I still wrapped the init methods using YAHOO.util.Event.onDOMReady() -- just in case. Thanks Satyam!

Update #2 v1.2b A few performance tweaks: Switched to using the YUI aggregate file utilities.js, which includes everything we need in one line AND loads faster with a single HTTP request. Updated the initializing code to show how onDOMReady() can be used as an alternative to onload(). YUI's onDOMReady() makes sure the DOM is ready to go, but doesn't wait for images to be loaded for a snappier page load. The last tweak was to the default animation speed... now with 1/2 the Saturated Fat!

Update #3 v1.3 Per some user requests, the accordion should now toggle only when clicking on the title section, not the content. If you want the old behavior, set "onlyCollapseOnTitleClick" to true in the constructor args.

19 comments:

  1. Have you tried it in IE? Its not working for me. The code in the sample page tries to execute when the rest of the library and your own component has not fully loaded. Try enclosing the script in your sample page in a call to onDOMReady

    ReplyDelete
  2. Thanks satyam! The bug actually was a dangling comma after the last property in my callback object inside the helper I use to retrieve div contents. I went ahead and wrapped it with onDOMReady just to be safe.

    BTW, are you the same "satyam" from the YUI mailing list?

    ReplyDelete
  3. Yes, the very same Satyam. You might want to check Eric's post of your app in the YUI blog, someone else noted the IE issue and commented it there, you might want to state that it's been fixed. By the way, I was wondering where are you? I'm in Sitges, close to Barcelona

    ReplyDelete
  4. It's really very slick, well done, but pleeease make it faster by default! Faster faster faster! I hate waiting around for animations, even if they're pretty - Lightbox made my broadband feel like dialup, and I'd hate for this to inspire the same frustration and impatience.

    ReplyDelete
  5. If one wanted to use this menu for site navigation what extra needs to be added?

    In particular the problem of remembering menu state (ie which menu div is visible) as one navigates the site comes to mind.

    ReplyDelete
  6. The component is excellent. It works on both IE and Mozilla. But, I need the accordion to collapse only when i click on Title section, not on the content area. How can I do that ?

    Gandhi Basnet
    Kathmandu, Nepal

    ReplyDelete
  7. Is it possible to set the sectionExpandedSize to 100%? I have incorporated your accordion with YUI autocomplete, and I would like it to adjust accordingly. Great Accordion though!

    ReplyDelete
  8. Yeah, I'm having the same issue as mackster25, I can't seem to figure out how to get the sections to expand to fit around the content.

    Is this hard to do?

    Really nice app though.

    ReplyDelete
  9. Instead of having the 100% ExpandedSize, I just incorporated YUI datatable. So I have a fixed height with my accordion content, and then I just have my data scrolling. It definitely a solid accordion. Once again, nice work!

    ReplyDelete
  10. I actually fixed the issue by just setting the accordionContentDiv to Overflow: Scroll, but it's still a little funky and I'm still trying to find a way to have it just re-size around the content.

    ReplyDelete
  11. hey - a nice component and fits me very well since I use the yui too.
    Is it free to use by the way ?
    There isn't any license in the code ...

    Let me know if you have some time at : marin (and here you put the `at` sign) underplot.com

    ReplyDelete
  12. Is it possible to have one section opened by default? I'd like the first section expanded on loading. Ideally I'd like a way to expand any of the sections by choice or parameters.

    var listeners = YAHOO.util.Event.getListeners(e,"click");
    ..
    listener.fn.call(e);
    }
    (doesnt work)

    and

    YAHOO.util.UserAction.click(e,{shiftKey: true });

    (doesnt work)

    Any ideas?

    ReplyDelete
  13. OK - I was being lazy - I'm using this for accordion menus with subitems, I have done a version which eapands to the limit of the number of subitems and also has an expand collapse all mode.

    Yours is the ONLY accordion substructure which doesnt flicker in IE 7...Well done!

    ReplyDelete
  14. ..and you can also select which item gets expanded first...

    ReplyDelete
  15. .. but it only works in IE5.5+...

    ReplyDelete
  16. Thanks for the comments folks. If interest is high enough, perhaps I'll throw this up on SVN for easier collaboration and code-browsing.

    ReplyDelete
  17. Hello!

    Nice piece of Code! Thank you! But... ;-)
    Is there a way to expand the accordion to the full extent of the text loaded (like mackster25 asked above?) That would be great, because the text I load can have big differences in length, from a few rows up to 40 or even more, so the workaround with overflow: scroll is a little cumbersome...
    I played already a little bit around with the code, but with no success...

    BTW: A public repository would be a good idea!

    Alas, Thank you for publishing this code,
    best wishes, Albin

    ReplyDelete
  18. Hi JIL,
    Is your accordion open source? I might like to use the accordion for commercial purposes...
    Thanks,
    Lenny.

    ReplyDelete
  19. yep. Open Source. I just ask you keep the original author comment at the top of the source.

    ReplyDelete