/* * jQuery UI Accordion 1.8.12 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Accordion * * Depends: *	jquery.ui.core.js *	jquery.ui.widget.js */(function( $, undefined ) {$.widget( "ui.accordion", {	options: {		active: 0,		animated: "slide",		autoHeight: true,		clearStyle: false,		collapsible: false,		event: "click",		fillSpace: false,		header: "> li > :first-child,> :not(li):even",		icons: {			header: "ui-icon-triangle-1-e",			headerSelected: "ui-icon-triangle-1-s"		},		navigation: false,		navigationFilter: function() {			return this.href.toLowerCase() === location.href.toLowerCase();		}	},	_create: function() {		var self = this,			options = self.options;		self.running = 0;		self.element			.addClass( "ui-accordion ui-widget ui-helper-reset" )			// in lack of child-selectors in CSS			// we need to mark top-LIs in a UL-accordion for some IE-fix			.children( "li" )				.addClass( "ui-accordion-li-fix" );		self.headers = self.element.find( options.header )			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )			.bind( "mouseenter.accordion", function() {				if ( options.disabled ) {					return;				}				$( this ).addClass( "ui-state-hover" );			})			.bind( "mouseleave.accordion", function() {				if ( options.disabled ) {					return;				}				$( this ).removeClass( "ui-state-hover" );			})			.bind( "focus.accordion", function() {				if ( options.disabled ) {					return;				}				$( this ).addClass( "ui-state-focus" );			})			.bind( "blur.accordion", function() {				if ( options.disabled ) {					return;				}				$( this ).removeClass( "ui-state-focus" );			});		self.headers.next()			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );		if ( options.navigation ) {			var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );			if ( current.length ) {				var header = current.closest( ".ui-accordion-header" );				if ( header.length ) {					// anchor within header					self.active = header;				} else {					// anchor within content					self.active = current.closest( ".ui-accordion-content" ).prev();				}			}		}		self.active = self._findActive( self.active || options.active )			.addClass( "ui-state-default ui-state-active" )			.toggleClass( "ui-corner-all" )			.toggleClass( "ui-corner-top" );		self.active.next().addClass( "ui-accordion-content-active" );		self._createIcons();		self.resize();				// ARIA		self.element.attr( "role", "tablist" );		self.headers			.attr( "role", "tab" )			.bind( "keydown.accordion", function( event ) {				return self._keydown( event );			})			.next()				.attr( "role", "tabpanel" );		self.headers			.not( self.active || "" )			.attr({				"aria-expanded": "false",				"aria-selected": "false",				tabIndex: -1			})			.next()				.hide();		// make sure at least one header is in the tab order		if ( !self.active.length ) {			self.headers.eq( 0 ).attr( "tabIndex", 0 );		} else {			self.active				.attr({					"aria-expanded": "true",					"aria-selected": "true",					tabIndex: 0				});		}		// only need links in tab order for Safari		if ( !$.browser.safari ) {			self.headers.find( "a" ).attr( "tabIndex", -1 );		}		if ( options.event ) {			self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {				self._clickHandler.call( self, event, this );				event.preventDefault();			});		}	},	_createIcons: function() {		var options = this.options;		if ( options.icons ) {			$( "<span></span>" )				.addClass( "ui-icon " + options.icons.header )				.prependTo( this.headers );			this.active.children( ".ui-icon" )				.toggleClass(options.icons.header)				.toggleClass(options.icons.headerSelected);			this.element.addClass( "ui-accordion-icons" );		}	},	_destroyIcons: function() {		this.headers.children( ".ui-icon" ).remove();		this.element.removeClass( "ui-accordion-icons" );	},	destroy: function() {		var options = this.options;		this.element			.removeClass( "ui-accordion ui-widget ui-helper-reset" )			.removeAttr( "role" );		this.headers			.unbind( ".accordion" )			.removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )			.removeAttr( "role" )			.removeAttr( "aria-expanded" )			.removeAttr( "aria-selected" )			.removeAttr( "tabIndex" );		this.headers.find( "a" ).removeAttr( "tabIndex" );		this._destroyIcons();		var contents = this.headers.next()			.css( "display", "" )			.removeAttr( "role" )			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );		if ( options.autoHeight || options.fillHeight ) {			contents.css( "height", "" );		}		return $.Widget.prototype.destroy.call( this );	},	_setOption: function( key, value ) {		$.Widget.prototype._setOption.apply( this, arguments );					if ( key == "active" ) {			this.activate( value );		}		if ( key == "icons" ) {			this._destroyIcons();			if ( value ) {				this._createIcons();			}		}		// #5332 - opacity doesn't cascade to positioned elements in IE		// so we need to add the disabled class to the headers and panels		if ( key == "disabled" ) {			this.headers.add(this.headers.next())				[ value ? "addClass" : "removeClass" ](					"ui-accordion-disabled ui-state-disabled" );		}	},	_keydown: function( event ) {		if ( this.options.disabled || event.altKey || event.ctrlKey ) {			return;		}		var keyCode = $.ui.keyCode,			length = this.headers.length,			currentIndex = this.headers.index( event.target ),			toFocus = false;		switch ( event.keyCode ) {			case keyCode.RIGHT:			case keyCode.DOWN:				toFocus = this.headers[ ( currentIndex + 1 ) % length ];				break;			case keyCode.LEFT:			case keyCode.UP:				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];				break;			case keyCode.SPACE:			case keyCode.ENTER:				this._clickHandler( { target: event.target }, event.target );				event.preventDefault();		}		if ( toFocus ) {			$( event.target ).attr( "tabIndex", -1 );			$( toFocus ).attr( "tabIndex", 0 );			toFocus.focus();			return false;		}		return true;	},	resize: function() {		var options = this.options,			maxHeight;		if ( options.fillSpace ) {			if ( $.browser.msie ) {				var defOverflow = this.element.parent().css( "overflow" );				this.element.parent().css( "overflow", "hidden");			}			maxHeight = this.element.parent().height();			if ($.browser.msie) {				this.element.parent().css( "overflow", defOverflow );			}			this.headers.each(function() {				maxHeight -= $( this ).outerHeight( true );			});			this.headers.next()				.each(function() {					$( this ).height( Math.max( 0, maxHeight -						$( this ).innerHeight() + $( this ).height() ) );				})				.css( "overflow", "auto" );		} else if ( options.autoHeight ) {			maxHeight = 0;			this.headers.next()				.each(function() {					maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );				})				.height( maxHeight );		}		return this;	},	activate: function( index ) {		// TODO this gets called on init, changing the option without an explicit call for that		this.options.active = index;		// call clickHandler with custom event		var active = this._findActive( index )[ 0 ];		this._clickHandler( { target: active }, active );		return this;	},	_findActive: function( selector ) {		return selector			? typeof selector === "number"				? this.headers.filter( ":eq(" + selector + ")" )				: this.headers.not( this.headers.not( selector ) )			: selector === false				? $( [] )				: this.headers.filter( ":eq(0)" );	},	// TODO isn't event.target enough? why the separate target argument?	_clickHandler: function( event, target ) {		var options = this.options;		if ( options.disabled ) {			return;		}		// called only when using activate(false) to close all parts programmatically		if ( !event.target ) {			if ( !options.collapsible ) {				return;			}			this.active				.removeClass( "ui-state-active ui-corner-top" )				.addClass( "ui-state-default ui-corner-all" )				.children( ".ui-icon" )					.removeClass( options.icons.headerSelected )					.addClass( options.icons.header );			this.active.next().addClass( "ui-accordion-content-active" );			var toHide = this.active.next(),				data = {					options: options,					newHeader: $( [] ),					oldHeader: options.active,					newContent: $( [] ),					oldContent: toHide				},				toShow = ( this.active = $( [] ) );			this._toggle( toShow, toHide, data );			return;		}		// get the click target		var clicked = $( event.currentTarget || target ),			clickedIsActive = clicked[0] === this.active[0];		// TODO the option is changed, is that correct?		// TODO if it is correct, shouldn't that happen after determining that the click is valid?		options.active = options.collapsible && clickedIsActive ?			false :			this.headers.index( clicked );		// if animations are still active, or the active header is the target, ignore click		if ( this.running || ( !options.collapsible && clickedIsActive ) ) {			return;		}		// find elements to show and hide		var active = this.active,			toShow = clicked.next(),			toHide = this.active.next(),			data = {				options: options,				newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,				oldHeader: this.active,				newContent: clickedIsActive && options.collapsible ? $([]) : toShow,				oldContent: toHide			},			down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );		// when the call to ._toggle() comes after the class changes		// it causes a very odd bug in IE 8 (see #6720)		this.active = clickedIsActive ? $([]) : clicked;		this._toggle( toShow, toHide, data, clickedIsActive, down );		// switch classes		active			.removeClass( "ui-state-active ui-corner-top" )			.addClass( "ui-state-default ui-corner-all" )			.children( ".ui-icon" )				.removeClass( options.icons.headerSelected )				.addClass( options.icons.header );		if ( !clickedIsActive ) {			clicked				.removeClass( "ui-state-default ui-corner-all" )				.addClass( "ui-state-active ui-corner-top" )				.children( ".ui-icon" )					.removeClass( options.icons.header )					.addClass( options.icons.headerSelected );			clicked				.next()				.addClass( "ui-accordion-content-active" );		}		return;	},	_toggle: function( toShow, toHide, data, clickedIsActive, down ) {		var self = this,			options = self.options;		self.toShow = toShow;		self.toHide = toHide;		self.data = data;		var complete = function() {			if ( !self ) {				return;			}			return self._completed.apply( self, arguments );		};		// trigger changestart event		self._trigger( "changestart", null, self.data );		// count elements to animate		self.running = toHide.size() === 0 ? toShow.size() : toHide.size();		if ( options.animated ) {			var animOptions = {};			if ( options.collapsible && clickedIsActive ) {				animOptions = {					toShow: $( [] ),					toHide: toHide,					complete: complete,					down: down,					autoHeight: options.autoHeight || options.fillSpace				};			} else {				animOptions = {					toShow: toShow,					toHide: toHide,					complete: complete,					down: down,					autoHeight: options.autoHeight || options.fillSpace				};			}			if ( !options.proxied ) {				options.proxied = options.animated;			}			if ( !options.proxiedDuration ) {				options.proxiedDuration = options.duration;			}			options.animated = $.isFunction( options.proxied ) ?				options.proxied( animOptions ) :				options.proxied;			options.duration = $.isFunction( options.proxiedDuration ) ?				options.proxiedDuration( animOptions ) :				options.proxiedDuration;			var animations = $.ui.accordion.animations,				duration = options.duration,				easing = options.animated;			if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {				easing = "slide";			}			if ( !animations[ easing ] ) {				animations[ easing ] = function( options ) {					this.slide( options, {						easing: easing,						duration: duration || 700					});				};			}			animations[ easing ]( animOptions );		} else {			if ( options.collapsible && clickedIsActive ) {				toShow.toggle();			} else {				toHide.hide();				toShow.show();			}			complete( true );		}		// TODO assert that the blur and focus triggers are really necessary, remove otherwise		toHide.prev()			.attr({				"aria-expanded": "false",				"aria-selected": "false",				tabIndex: -1			})			.blur();		toShow.prev()			.attr({				"aria-expanded": "true",				"aria-selected": "true",				tabIndex: 0			})			.focus();	},	_completed: function( cancel ) {		this.running = cancel ? 0 : --this.running;		if ( this.running ) {			return;		}		if ( this.options.clearStyle ) {			this.toShow.add( this.toHide ).css({				height: "",				overflow: ""			});		}		// other classes are removed before the animation; this one needs to stay until completed		this.toHide.removeClass( "ui-accordion-content-active" );		// Work around for rendering bug in IE (#5421)		if ( this.toHide.length ) {			this.toHide.parent()[0].className = this.toHide.parent()[0].className;		}		this._trigger( "change", null, this.data );	}});$.extend( $.ui.accordion, {	version: "1.8.12",	animations: {		slide: function( options, additions ) {			options = $.extend({				easing: "swing",				duration: 300			}, options, additions );			if ( !options.toHide.size() ) {				options.toShow.animate({					height: "show",					paddingTop: "show",					paddingBottom: "show"				}, options );				return;			}			if ( !options.toShow.size() ) {				options.toHide.animate({					height: "hide",					paddingTop: "hide",					paddingBottom: "hide"				}, options );				return;			}			var overflow = options.toShow.css( "overflow" ),				percentDone = 0,				showProps = {},				hideProps = {},				fxAttrs = [ "height", "paddingTop", "paddingBottom" ],				originalWidth;			// fix width before calculating height of hidden element			var s = options.toShow;			originalWidth = s[0].style.width;			s.width( parseInt( s.parent().width(), 10 )				- parseInt( s.css( "paddingLeft" ), 10 )				- parseInt( s.css( "paddingRight" ), 10 )				- ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )				- ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );			$.each( fxAttrs, function( i, prop ) {				hideProps[ prop ] = "hide";				var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );				showProps[ prop ] = {					value: parts[ 1 ],					unit: parts[ 2 ] || "px"				};			});			options.toShow.css({ height: 0, overflow: "hidden" }).show();			options.toHide				.filter( ":hidden" )					.each( options.complete )				.end()				.filter( ":visible" )				.animate( hideProps, {				step: function( now, settings ) {					// only calculate the percent when animating height					// IE gets very inconsistent results when animating elements					// with small values, which is common for padding					if ( settings.prop == "height" ) {						percentDone = ( settings.end - settings.start === 0 ) ? 0 :							( settings.now - settings.start ) / ( settings.end - settings.start );					}					options.toShow[ 0 ].style[ settings.prop ] =						( percentDone * showProps[ settings.prop ].value )						+ showProps[ settings.prop ].unit;				},				duration: options.duration,				easing: options.easing,				complete: function() {					if ( !options.autoHeight ) {						options.toShow.css( "height", "" );					}					options.toShow.css({						width: originalWidth,						overflow: overflow					});					options.complete();				}			});		},		bounceslide: function( options ) {			this.slide( options, {				easing: options.down ? "easeOutBounce" : "swing",				duration: options.down ? 1000 : 200			});		}	}});})( jQuery );
