- uploading 1.1 in tags
[mootools.git] / Plugins / Accordion.js
blob39a280644d0cc12c4f1063ad6ce888ec7451759c
1 /*
2 Script: Accordion.js
3         Contains <Accordion>
5 License:
6         MIT-style license.
7 */
9 /*
10 Class: Accordion
11         The Accordion class creates a group of elements that are toggled when their handles are clicked. When one elements toggles in, the others toggles back.
12         
13 Note:
14         The Accordion requires an XHTML doctype.
16 Arguments:
17         togglers - required, a collection of elements, the elements handlers that will be clickable.
18         elements - required, a collection of elements the transitions will be applied to.
19         options - optional, see options below, and <Fx.Base> options.
21 Options:
22         show - integer, the Index of the element to show at start.
23         display - integer, the Index of the element to show at start (with a transition). defaults to 0.
24         fixedHeight - integer, if you want the elements to have a fixed height. defaults to false.
25         fixedWidth - integer, if you want the elements to have a fixed width. defaults to false.
26         onActive - function to execute when an element starts to show
27         onBackground - function to execute when an element starts to hide
28         height - boolean, will add a height transition to the accordion if true. defaults to true.
29         opacity - boolean, will add an opacity transition to the accordion if true. defaults to true.
30         width - boolean, will add a width transition to the accordion if true. defaults to false, css mastery is required to make this work!
31         alwaysHide - boolean, will allow to hide all elements if true, instead of always keeping one element shown. defaults to false.
34 var Accordion = Fx.Elements.extend({
36         options: {
37                 onActive: Class.empty,
38                 onBackground: Class.empty,
39                 display: 0,
40                 show: false,
41                 height: true,
42                 width: false,
43                 opacity: true,
44                 fixedHeight: false,
45                 fixedWidth: false,
46                 wait: false,
47                 alwaysHide: false
48         },
50         initialize: function(){
51                 var options, togglers, elements, container;
52                 $each(arguments, function(argument, i){
53                         switch($type(argument)){
54                                 case 'object': options = argument; break;
55                                 case 'element': container = $(argument); break;
56                                 default:
57                                         var temp = $$(argument);
58                                         if (!togglers) togglers = temp;
59                                         else elements = temp;
60                         }
61                 });
62                 this.togglers = togglers || [];
63                 this.elements = elements || [];
64                 this.container = $(container);
65                 this.setOptions(options);
66                 this.previous = -1;
67                 if (this.options.alwaysHide) this.options.wait = true;
68                 if ($chk(this.options.show)){
69                         this.options.display = false;
70                         this.previous = this.options.show;
71                 }
72                 if (this.options.start){
73                         this.options.display = false;
74                         this.options.show = false;
75                 }
76                 this.effects = {};
77                 if (this.options.opacity) this.effects.opacity = 'fullOpacity';
78                 if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
79                 if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
80                 for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
81                 this.elements.each(function(el, i){
82                         if (this.options.show === i) this.fireEvent('onActive', [this.togglers[i], el]);
83                         else for (var fx in this.effects) el.setStyle(fx, 0);
84                 }, this);
85                 this.parent(this.elements);
86                 if ($chk(this.options.display)) this.display(this.options.display);
87         },
89         addSection: function(toggler, element, pos){
90                 toggler = $(toggler);
91                 element = $(element);
92                 var test = this.togglers.contains(toggler);
93                 var len = this.togglers.length;
94                 this.togglers.include(toggler);
95                 this.elements.include(element);
96                 if (len && (!test || pos)){
97                         pos = $pick(pos, len - 1);
98                         toggler.injectBefore(this.togglers[pos]);
99                         element.injectAfter(toggler);
100                 } else if (this.container && !test){
101                         toggler.inject(this.container);
102                         element.inject(this.container);
103                 }
104                 var idx = this.togglers.indexOf(toggler);
105                 toggler.addEvent('click', this.display.bind(this, idx));
106                 if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
107                 if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
108                 element.fullOpacity = 1;
109                 if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
110                 if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
111                 element.setStyle('overflow', 'hidden');
112                 if (!test) for (var fx in this.effects) element.setStyle(fx, 0);
113                 return this;
114         },
116         /*
117         Property: display
118                 Shows a specific section and hides all others. Useful when triggering an accordion from outside.
120         Arguments:
121                 index - integer, the index of the item to show, or the actual element to show.
122         */
124         display: function(index){
125                 index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
126                 if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
127                 this.previous = index;
128                 var obj = {};
129                 this.elements.each(function(el, i){
130                         obj[i] = {};
131                         if ((i != index) || (this.options.alwaysHide && (el.offsetHeight > 0))){
132                                 this.fireEvent('onBackground', [this.togglers[i], el]);
133                                 for (var fx in this.effects) obj[i][fx] = 0;
134                         } else {
135                                 this.fireEvent('onActive', [this.togglers[i], el]);
136                                 for (var fx in this.effects) obj[i][fx] = el[this.effects[fx]];
137                         }
138                 }, this);
139                 return this.start(obj);
140         },
142         showThisHideOpen: function(index){return this.display(index)}
146 Fx.Accordion = Accordion;