123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- * Accordion 1.5 - jQuery menu widget
- *
- * Copyright (c) 2007 Jörn Zaefferer, Frank Marcia
- *
- * http://bassistance.de/jquery-plugins/jquery-plugin-accordion/
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- * Revision: $Id: jquery.accordion.js 2951 2007-08-28 07:21:13Z joern.zaefferer $
- *
- */
- (function($) {
- $.ui = $.ui || {}
- $.ui.accordion = {};
- $.extend($.ui.accordion, {
- defaults: {
- selectedClass: "selected",
- alwaysOpen: true,
- animated: 'slide',
- event: "click",
- header: "a"
- },
- animations: {
- slide: function(settings, additions) {
- settings = $.extend({
- easing: "swing",
- duration: 300
- }, settings, additions);
- if ( !settings.toHide.size() ) {
- settings.toShow.animate({height: "show"}, {
- duration: settings.duration,
- easing: settings.easing,
- complete: settings.finished
- });
- return;
- }
- var hideHeight = settings.toHide.height(),
- showHeight = settings.toShow.height(),
- difference = showHeight / hideHeight;
- settings.toShow.css({ height: 0, overflow: 'hidden' }).show();
- settings.toHide.filter(":hidden").each(settings.finished).end().filter(":visible").animate({height:"hide"},{
- step: function(n){
- settings.toShow.height(Math.ceil( (hideHeight - (n)) * difference ));
- },
- duration: settings.duration,
- easing: settings.easing,
- complete: settings.finished
- });
- },
- bounceslide: function(settings) {
- this.slide(settings, {
- easing: settings.down ? "bounceout" : "swing",
- duration: settings.down ? 1000 : 200
- });
- },
- easeslide: function(settings) {
- this.slide(settings, {
- easing: "easeinout",
- duration: 700
- })
- }
- }
- });
- $.fn.extend({
- nextUntil: function(expr) {
- var match = [];
-
- // We need to figure out which elements to push onto the array
- this.each(function(){
- // Traverse through the sibling nodes
- for( var i = this.nextSibling; i; i = i.nextSibling ) {
- // Make sure that we're only dealing with elements
- if ( i.nodeType != 1 ) continue;
-
- // If we find a match then we need to stop
- if ( $.filter( expr, [i] ).r.length ) break;
-
- // Otherwise, add it on to the stack
- match.push( i );
- }
- });
-
- return this.pushStack( match );
- },
- // the plugin method itself
- accordion: function(settings) {
- if ( !this.length )
- return this;
-
- // setup configuration
- settings = $.extend({}, $.ui.accordion.defaults, settings);
-
- if ( settings.navigation ) {
- var current = this.find("a").filter(function() { return this.href == location.href; });
- if ( current.length ) {
- if ( current.filter(settings.header).length ) {
- settings.active = current;
- } else {
- settings.active = current.parent().parent().prev();
- current.addClass("current");
- }
- }
- }
-
- // calculate active if not specified, using the first header
- var container = this,
- headers = container.find(settings.header),
- active = findActive(settings.active),
- running = 0;
- if ( settings.fillSpace ) {
- var maxHeight = this.parent().height();
- headers.each(function() {
- maxHeight -= $(this).outerHeight();
- });
- var maxPadding = 0;
- headers.nextUntil(settings.header).each(function() {
- maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
- }).height(maxHeight - maxPadding);
- } else if ( settings.autoheight ) {
- var maxHeight = 0;
- headers.nextUntil(settings.header).each(function() {
- maxHeight = Math.max(maxHeight, $(this).height());
- }).height(maxHeight);
- }
- headers
- .not(active || "")
- .nextUntil(settings.header)
- .hide();
- active.parent().andSelf().addClass(settings.selectedClass);
-
-
- function findActive(selector) {
- return selector != undefined
- ? typeof selector == "number"
- ? headers.filter(":eq(" + selector + ")")
- : headers.not(headers.not(selector))
- : selector === false
- ? $("<div>")
- : headers.filter(":eq(0)");
- }
-
- function toggle(toShow, toHide, data, clickedActive, down) {
- var finished = function(cancel) {
- running = cancel ? 0 : --running;
- if ( running )
- return;
- // trigger custom change event
- container.trigger("change", data);
- };
-
- // count elements to animate
- running = toHide.size() == 0 ? toShow.size() : toHide.size();
-
- if ( settings.animated ) {
- if ( !settings.alwaysOpen && clickedActive ) {
- toShow.slideToggle(settings.animated);
- finished(true);
- } else {
- $.ui.accordion.animations[settings.animated]({
- toShow: toShow,
- toHide: toHide,
- finished: finished,
- down: down
- });
- }
- } else {
- if ( !settings.alwaysOpen && clickedActive ) {
- toShow.toggle();
- } else {
- toHide.hide();
- toShow.show();
- }
- finished(true);
- }
- }
-
- function clickHandler(event) {
- // called only when using activate(false) to close all parts programmatically
- if ( !event.target && !settings.alwaysOpen ) {
- active.toggleClass(settings.selectedClass);
- var toHide = active.nextUntil(settings.header);
- var toShow = active = $([]);
- toggle( toShow, toHide );
- return;
- }
- // get the click target
- var clicked = $(event.target);
-
- // due to the event delegation model, we have to check if one
- // of the parent elements is our actual header, and find that
- if ( clicked.parents(settings.header).length )
- while ( !clicked.is(settings.header) )
- clicked = clicked.parent();
-
- var clickedActive = clicked[0] == active[0];
-
- // if animations are still active, or the active header is the target, ignore click
- if(running || (settings.alwaysOpen && clickedActive) || !clicked.is(settings.header))
- return;
- // switch classes
- active.parent().andSelf().toggleClass(settings.selectedClass);
- if ( !clickedActive ) {
- clicked.parent().andSelf().addClass(settings.selectedClass);
- }
- // find elements to show and hide
- var toShow = clicked.nextUntil(settings.header),
- toHide = active.nextUntil(settings.header),
- data = [clicked, active, toShow, toHide],
- down = headers.index( active[0] ) > headers.index( clicked[0] );
-
- active = clickedActive ? $([]) : clicked;
- toggle( toShow, toHide, data, clickedActive, down );
- return !toShow.length;
- };
- function activateHandler(event, index) {
- // IE manages to call activateHandler on normal clicks
- if ( arguments.length == 1 )
- return;
- // call clickHandler with custom event
- clickHandler({
- target: findActive(index)[0]
- });
- };
- return container
- .bind(settings.event, clickHandler)
- .bind("activate", activateHandler);
- },
- activate: function(index) {
- return this.trigger('activate', [index]);
- }
- });
- })(jQuery);
|