2 * Accordion 1.5 - jQuery menu widget
\r
4 * Copyright (c) 2007 Jörn Zaefferer, Frank Marcia
\r
6 * http://bassistance.de/jquery-plugins/jquery-plugin-accordion/
\r
8 * Dual licensed under the MIT and GPL licenses:
\r
9 * http://www.opensource.org/licenses/mit-license.php
\r
10 * http://www.gnu.org/licenses/gpl.html
\r
12 * Revision: $Id: jquery.accordion.js 2951 2007-08-28 07:21:13Z joern.zaefferer $
\r
20 $.ui.accordion = {};
\r
21 $.extend($.ui.accordion, {
\r
23 selectedClass: "selected",
\r
30 slide: function(settings, additions) {
\r
31 settings = $.extend({
\r
34 }, settings, additions);
\r
35 if ( !settings.toHide.size() ) {
\r
36 settings.toShow.animate({height: "show"}, {
\r
37 duration: settings.duration,
\r
38 easing: settings.easing,
\r
39 complete: settings.finished
\r
43 var hideHeight = settings.toHide.height(),
\r
44 showHeight = settings.toShow.height(),
\r
45 difference = showHeight / hideHeight;
\r
46 settings.toShow.css({ height: 0, overflow: 'hidden' }).show();
\r
47 settings.toHide.filter(":hidden").each(settings.finished).end().filter(":visible").animate({height:"hide"},{
\r
49 settings.toShow.height(Math.ceil( (hideHeight - (n)) * difference ));
\r
51 duration: settings.duration,
\r
52 easing: settings.easing,
\r
53 complete: settings.finished
\r
56 bounceslide: function(settings) {
\r
57 this.slide(settings, {
\r
58 easing: settings.down ? "bounceout" : "swing",
\r
59 duration: settings.down ? 1000 : 200
\r
62 easeslide: function(settings) {
\r
63 this.slide(settings, {
\r
64 easing: "easeinout",
\r
72 nextUntil: function(expr) {
\r
75 // We need to figure out which elements to push onto the array
\r
76 this.each(function(){
\r
77 // Traverse through the sibling nodes
\r
78 for( var i = this.nextSibling; i; i = i.nextSibling ) {
\r
79 // Make sure that we're only dealing with elements
\r
80 if ( i.nodeType != 1 ) continue;
\r
82 // If we find a match then we need to stop
\r
83 if ( $.filter( expr, [i] ).r.length ) break;
\r
85 // Otherwise, add it on to the stack
\r
90 return this.pushStack( match );
\r
92 // the plugin method itself
\r
93 accordion: function(settings) {
\r
97 // setup configuration
\r
98 settings = $.extend({}, $.ui.accordion.defaults, settings);
\r
100 if ( settings.navigation ) {
\r
101 var current = this.find("a").filter(function() { return this.href == location.href; });
\r
102 if ( current.length ) {
\r
103 if ( current.filter(settings.header).length ) {
\r
104 settings.active = current;
\r
106 settings.active = current.parent().parent().prev();
\r
107 current.addClass("current");
\r
112 // calculate active if not specified, using the first header
\r
113 var container = this,
\r
114 headers = container.find(settings.header),
\r
115 active = findActive(settings.active),
\r
118 if ( settings.fillSpace ) {
\r
119 var maxHeight = this.parent().height();
\r
120 headers.each(function() {
\r
121 maxHeight -= $(this).outerHeight();
\r
123 var maxPadding = 0;
\r
124 headers.nextUntil(settings.header).each(function() {
\r
125 maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
\r
126 }).height(maxHeight - maxPadding);
\r
127 } else if ( settings.autoheight ) {
\r
129 headers.nextUntil(settings.header).each(function() {
\r
130 maxHeight = Math.max(maxHeight, $(this).height());
\r
131 }).height(maxHeight);
\r
136 .nextUntil(settings.header)
\r
138 active.parent().andSelf().addClass(settings.selectedClass);
\r
141 function findActive(selector) {
\r
142 return selector != undefined
\r
143 ? typeof selector == "number"
\r
144 ? headers.filter(":eq(" + selector + ")")
\r
145 : headers.not(headers.not(selector))
\r
146 : selector === false
\r
148 : headers.filter(":eq(0)");
\r
151 function toggle(toShow, toHide, data, clickedActive, down) {
\r
152 var finished = function(cancel) {
\r
153 running = cancel ? 0 : --running;
\r
156 // trigger custom change event
\r
157 container.trigger("change", data);
\r
160 // count elements to animate
\r
161 running = toHide.size() == 0 ? toShow.size() : toHide.size();
\r
163 if ( settings.animated ) {
\r
164 if ( !settings.alwaysOpen && clickedActive ) {
\r
165 toShow.slideToggle(settings.animated);
\r
168 $.ui.accordion.animations[settings.animated]({
\r
171 finished: finished,
\r
176 if ( !settings.alwaysOpen && clickedActive ) {
\r
186 function clickHandler(event) {
\r
187 // called only when using activate(false) to close all parts programmatically
\r
188 if ( !event.target && !settings.alwaysOpen ) {
\r
189 active.toggleClass(settings.selectedClass);
\r
190 var toHide = active.nextUntil(settings.header);
\r
191 var toShow = active = $([]);
\r
192 toggle( toShow, toHide );
\r
195 // get the click target
\r
196 var clicked = $(event.target);
\r
198 // due to the event delegation model, we have to check if one
\r
199 // of the parent elements is our actual header, and find that
\r
200 if ( clicked.parents(settings.header).length )
\r
201 while ( !clicked.is(settings.header) )
\r
202 clicked = clicked.parent();
\r
204 var clickedActive = clicked[0] == active[0];
\r
206 // if animations are still active, or the active header is the target, ignore click
\r
207 if(running || (settings.alwaysOpen && clickedActive) || !clicked.is(settings.header))
\r
211 active.parent().andSelf().toggleClass(settings.selectedClass);
\r
212 if ( !clickedActive ) {
\r
213 clicked.parent().andSelf().addClass(settings.selectedClass);
\r
216 // find elements to show and hide
\r
217 var toShow = clicked.nextUntil(settings.header),
\r
218 toHide = active.nextUntil(settings.header),
\r
219 data = [clicked, active, toShow, toHide],
\r
220 down = headers.index( active[0] ) > headers.index( clicked[0] );
\r
222 active = clickedActive ? $([]) : clicked;
\r
223 toggle( toShow, toHide, data, clickedActive, down );
\r
225 return !toShow.length;
\r
227 function activateHandler(event, index) {
\r
228 // IE manages to call activateHandler on normal clicks
\r
229 if ( arguments.length == 1 )
\r
231 // call clickHandler with custom event
\r
233 target: findActive(index)[0]
\r
238 .bind(settings.event, clickHandler)
\r
239 .bind("activate", activateHandler);
\r
241 activate: function(index) {
\r
242 return this.trigger('activate', [index]);
\r