Back in the days when I used moofx I wrote a tutorial about horizontal and vertical accordions. Now moofx is part of the mootools framework so it’s time for a new tutorial.

Before I start I want you to think about when accordions are useful. When you have a huge document to split it up I recommend using tabs. Here’s an example so you can see what I mean (please wait till the page is fully loaded).

accordions + huge content = ugly / not user friendly / has low accessibility
tabs + huge content = better

Well, that’s my opinion. The moofx website instead is a great example of using an accordion the right way. That’s all, let’s start with a basic Accordion.

Example: basic accordion

An accordion basically needs two groups of elements. First we need a group of ‘toggler’ elements. These elements are the ones on which we can click on. In this example I gave this group of elements the classname ‘accToggler’. The other group is the group of ‘content’ elements which I gave classname ‘accContent’. The following javascript can be used to select the different groups:

var accordionTogglers = document.getElementsByClassName('accToggler');
var accordionContents = document.getElementsByClassName('accContent');

So accordionTogglers is an array of elements with classname ‘accToggler’ and accordionContents is an array of elements with classname ‘accordionContents’. Now all we have to do is call the accordion constructor with the accordionTogglers and accordionContents as parameters, and our accordion is ready to shine:

new Fx.Accordion(accordionTogglers, accordionContents);

You can see it working at example page 1.
NOTE: Make sure all of the code above is called in the window.onload function(). When you’re calling document.getElementsByClassName() when the page is not finished loading yet the returned array probably will be empty.

Accordion options

Now I’ll explain some of the options.

  • duration: the duration of the effect in milliseconds. The default is 500.
  • fps: The frames per second for the transition. It’s default value is set to 30.
  • onStart/onComplete: The function to execute when the transition starts/ends. No function is executed by default.
  • onActive/onBackground: The function to execute when an element starts to show/hide. No function is executed by default.
  • start: Either ‘open-first’ or ‘first-open’. This options sets whether there’s a transitions is shown for the first open content element when the accordion is initialized. When set to ‘open-first’ the transition is shown and when set to ‘first-open’ the content element will be opened when the accordion is initialized. (default is ‘open-first’)
  • alwaysHide: When this boolean is set to true, you can close the only open item. The default is false.
  • width: When set to true this option adds a width transition to the accordion. With the use of some css we can make a vertical accordion. I’ll explain this in another post.

I covered most of the options, but there are more, they’re explained in the mootools doc.

Example: more advanced accordion

In the following example we’ll play with the options. I assume you understand how accordions are initialized by know. The example accordion will be initialized with the following options:

new Fx.Accordion(accordionTogglers, accordionContents,{start:'first-open',alwaysHide:true,onActive:function(){alert('Hi, I'm onActive!')}});

See it working on this example page.
When the page is loaded you can see the first tab is already opened, that’s because of start:'first-open'. You can also see that all items can be closed (alwaysHide:true). The best thing you can learn from this example is the difference between onActive and onStart. Whenever you click on a toggler the onStart function is called, but the onActive function is only called when the toggler opens a content element.

Some extra eyecandy

It’s possible to have a color transition when a toggler element is pressed. The moofx website is using the effect. It’s quite easy.

var accordion;
var accordionTogglers;
var accordionContents;

window.onload = function() {
  accordionTogglers = document.getElementsByClassName('accToggler');

  accordionTogglers.each(function(toggler){
    //remember the original color
    toggler.origColor = toggler.getStyle('background-color');
    //set the effect
    toggler.fx = new Fx.Style(toggler, 'background-color');
  });

  accordionContents = document.getElementsByClassName('accContent');

  accordion = new Fx.Accordion(accordionTogglers, accordionContents,{
    //when an element is opened change the background color to blue
    onActive: function(toggler){
      toggler.fx.start('#6899CE');
    },
    onBackground: function(toggler){
      //change the background color to the original (green)
      //color when another toggler is pressed
      toggler.setStyle('background-color', toggler.origColor);
    }
  });
};

A working example is here. When a toggler element is pressed and the content element is opened the onActive function is called. The function has a parameter that is the toggler element. Then the background color is changed to green. When an element is closed the onBackground function is called and the background color is changed to it’s original background color.

Prerequisites

The following modules are used in the examples:

  • Core files (Moo.js and Utility.js)
  • String.js, Array.js, Element.js and Function.js
  • Common.js
  • Fx.Base.js, Fx.CSS.js, Fx.Style.js and Fx.Elements
  • Accordion.js
  • Dom.js (optional: may be used for selecting toggler/content elements)

Phew, the examples are working again

A few weeks ago the examples stopped working after I updated mootools to revision 83. After doing some research I found out the DOM selectors were returning empty arrays. The classname I used were ‘accordion-toggler’ and ‘accordion-content’ for the toggler/content elements. I think it has something to do with the ‘-’ in the classnames. I changed every ‘accordion-content’ to ‘accContent’ and ‘accordion-toggler’ to ‘accToggler’ and the DOM selectors are doing their job again.

document.getElementsByClassname('accordion-content'); //=> returned []
//=> replaced by document.getElementsByClassname('accContent');
document.getElementsByClassname('accordion-toggler'); //=> returned []
//=> replaced by document.getElementsByClassname('accToggler');