So I have managed to create a recursive mootools accordion, which is something I have wanted to get done for a long time.
The secret ingredient to get this made up was some CSS3 selectors and a bit of recursion.
You basically just pass in a class for the toggles, a class for the elements, and a parent container to reference.
The usage ends up fairly simple:
new rAccordion('container', 'toggle', 'element');
In the example, container is the id of the parent that the classes are in, toggle is the class that each toggle has, and element is the class that each element has. A fourth argument can be passed, which is the options argument for the mootools Accordion class.
There are some kinks thatstill need working out. There are inherit problems with just jamming accordions inside of each other. The way mootools creates the accordion requires quite a bit of inline styles, which include defined heights. These heights become problematic when accordions inside accordions need to expand or contract, but their parent element has a defined height and overflow which will not allow the newly expanded portion to be seen.
I do have something of a solution in place, but it feels a little hacky, but I am not sure it will get any better unless I rewrite the accordion.
If anyone has any ideas on how to address this issue, please drop me a comment.
Here is the class:
var rAccordion = new Class({
initialize: function(container, toggleClass, elementClass, options){
this.container = container;
this.tClass = toggleClass;
this.eClass = elementClass;
this.options = options;
this.selector = '#' + this.container + ' > .';
this.makeAccordion();
},
makeAccordion: function(){
new Accordion(
$$(this.selector+this.tClass),
$$(this.selector+this.eClass),
this.options
).addEvents({
// The onActive and onComplete events added to the stack here to
// attempt to address some of the css issues.
'onActive': function(toggle){
if(toggle.getParent().getStyle('height') != 0)
toggle.getParent().setStyle('height', '');
},
'onComplete': function(a){
if ($defined(a)) {
var height = 0;
a.getParent().getChildren().each(function(e){
height = height + e.offsetHeight;
});
if(height != a.getParent().offsetHeight && a.getParent().offsetHeight != 0)
a.getParent().setStyle('height','');
}
}
});
this.selector += this.eClass + ' > .';
if($defined($$(this.selector)[0]))
this.makeAccordion();
}
});
August 4th, 2008 at 8:29 am
I think a cure for you overflow ailment with slide/accordion might lie in an ‘extend’ of the class. This is a great way to let Fx.Slide do overflow auto (it is set to hidden automatically too, annoying!), for refrence:
http://we.designandco.de/2008/06/10/mootools-fxslide-flicker-bug/
http://we.designandco.de/2008/06/20/mootools-fxslide-flicker-bug-ii/
I am not sure if internally Accordion is dependent on Slide for its actions, but anyhow, ‘extend’ use could give you the option I believe that you desire without actually rewriting the Accordion class.
This script is well done, I’ll be using it in the next few days, thanks!
- Daniel
August 4th, 2008 at 12:15 pm
@Daniel, the accordion class does not use Fx.Slide, but rather is extending the Fx class directly. I read it over and I think there are some clues to how to fix this, so I will be investigation those further.
November 13th, 2008 at 7:33 pm
Hi atom, thanks for this great script.
I’m trying to save the active state via cookie, but I don’t get it to work.
Is it possible to make the menu stay open at a certain place when invoked? (ie. if you opened the first nest and clicked an item, when you went to its page, the menu would stay open at that item)
This would really help for knowing where you are on a website if this menu was used on it
November 13th, 2008 at 7:39 pm
My first though is no, mostly because this is intended to work with however many accordions you have.
However, it can probably be done without too much work, so I will probably have a look at it and see what I can do without making this too complicated.
November 20th, 2008 at 5:39 am
Hi there, just a little short question: what would a piece of extra code look like, to use a mouseover event for the accordion instaead of a click??
November 20th, 2008 at 6:14 am
@Thorsten,
It wouldn’t be too difficult really, but you would have to work with the actual Accordion class that this is utilizing.
After creating the accordions, you would need to add a mouseover event to each toggler bound to the accordion’s display function, and remove the click events.
November 24th, 2008 at 10:19 am
@atom,
well, I’m not so good with js but a friend helped me out. Last question: do I have to change your js in order to use plain list elements (ul li)?? I tried that with the same names for the classes but nothing was working. Maybe I’m too stupid. Could you help me out?
February 14th, 2009 at 3:26 pm
Hi there, I’m learning to work with mootools and This example is exactly what I have tried to achieve for the past 1 week but to no avail! Thanks for sharing this!
There are two problems that I’ve encountered while working with the script.
1. The expanding and collapsing is not consistent. sometimes the whole menu collapse and sometimes it doesn’t.
2. changing the css style of the 2nd class of toggle. For eg.
Toggle 1
> Toggle 2
> element 3
> Toggle 2a
I have tried to play around with the script but i can’t change the style of Toggle 2 or Toggle 2a.
Any idea if question 2 can be fixed?
Thanks!
February 14th, 2009 at 3:29 pm
Toggle 1
>> Toggle 2
>>>> Element 3
>> Toggle 2.a
>>>> Element 4
After posting the above post, i realised the indent is omited. To prevent confusion, here is what i meant of the toggle 2.
May 18th, 2009 at 8:01 pm
hi atom thanks for the great script.
I am also trying to get the menu to stay open when invoked. has this been developed? I have been trying out some if statements within the raccordion definition (creating a class “current” and then having the display option depend on it) without any luck.
May 19th, 2009 at 10:06 am
Hi, I’m also trying to get the menu to stay open. Has anyone had any luck?
Also can’t change the active style of the second level.
Thanks
July 15th, 2009 at 11:06 pm
Hi,
I have some problem with the height. When it firts load the page the height of the first accordion did not wrapped exactly with the content it hide it. what is the solution or workaroud can i do with this problem.
Thanks for any help!
jR.
September 30th, 2009 at 8:33 am
@atom, thank you very much for this! I am in dire need to get the active state working! Please email me if you have implemented it. Thank you!
December 4th, 2009 at 11:59 am
@with script to close all sub-levels
December 4th, 2009 at 12:04 pm
@sorry…
December 4th, 2009 at 12:52 pm
@v1.0.545 – lol
ok… the code are not completed.
the difference are:
Good work!
January 18th, 2010 at 8:26 pm
Very slick looking. Is it possible to have more than one element per toggle? It’s breaking it when I try.
January 26th, 2010 at 8:55 am
济南二手房(esf.jnol.cn)网来博客参观过了,呵呵,有空多多交流哈。
February 1st, 2010 at 7:40 am
很不错的博客哦,来过踩踩,欢迎回访~