/* Simple Accordion Script 
 * Requires Prototype and Script.aculo.us Libraries
 * By: Brian Crescimanno <brian.crescimanno@gmail.com>
 * http://briancrescimanno.com
 * This work is licensed under the Creative Commons Attribution-Share Alike 3.0
 * http://creativecommons.org/licenses/by-sa/3.0/us/
 */

if ( typeof Effect == 'undefined' )
	throw("You must have the script.aculo.us library to use this accordion");

var Accordion = Class.create({
	initialize: function( id, defaultExpandedCount ) {
		if( !$(id) )  throw("Attempted to initalize accordion with id: "+ id + " which was not found.");
		
		this.accordion = $(id);
		this.options = {
			toggleActive: "active",
			
			toggleClass: "accordion-toggle",
			contentClass: "accordion-content"
		}
		
		this.contents = this.accordion.select( 'dd' );
		this.isAnimating = false;
		this.maxHeight = 0;
		this.current = defaultExpandedCount ? this.contents[defaultExpandedCount-1] : this.contents[0];
		this.toExpand = null;
		this.queuedExpand = null;
	
		this.checkMaxHeight();
		this.initialHide();
		this.attachInitialMaxHeight();
	
		this.accordion.observe( "mouseover", this.onMouseOver.bindAsEventListener(this) );
	},

	checkMaxHeight: function() {
		for ( var i = 0; i < this.contents.length; i++ )
			this.maxHeight = Math.max( this.maxHeight, this.contents[i].getHeight() );
	},
	
	initialHide: function(){
		for ( var i = 0; i < this.contents.length; i++ ) {
			if ( this.contents[i] != this.current )
				this.contents[i].hide().setStyle({ height: 0 });
		}
	},
	
	attachInitialMaxHeight: function() {
		this.current.previous( 'dt' ).addClassName( this.options.toggleActive );
		if ( this.current.getHeight() != this.maxHeight )
			this.current.setStyle({ height: this.maxHeight + "px" });
	},
	
	
	onMouseOver: function(e) {
		var el = e.element();
		if ( el.tagName.toLowerCase() == "dt" )
			if ( !this.isAnimating )
				this.expand(el);
			else
				this.queuedExpand = el;
	},
	
	expand: function(el) {
		this.toExpand = el.next( 'dd' );
		if ( this.current != this.toExpand ) {
			this.toExpand.show();
			this.animate();
		}
	},

	animate: function() {
		var effects = new Array();
		
		var options = {
			sync: true,
			scaleFrom: 0,
			scaleContent: false,
			transition: Effect.Transitions.sinoidal,
			scaleMode: { originalHeight: this.maxHeight, originalWidth: this.accordion.getWidth() },
			scaleX: false,
			scaleY: true
		};
		effects.push( new Effect.Scale( this.toExpand, 100, options ));
	
		options = {
			sync: true,
			scaleContent: false,
			transition: Effect.Transitions.sinoidal,
			scaleX: false,
			scaleY: true
		};
		effects.push( new Effect.Scale( this.current, 0, options ));
	
		new Effect.Parallel( effects, {
			delay: 0.1,
			duration: 0.4,
			fps: 25,
			queue: { position: 'end', scope: 'accordion' },
			
			beforeStart: function() {
				this.isAnimating = true;
				this.current.previous( 'dt' ).removeClassName( this.options.toggleActive );
				this.toExpand.previous( 'dt' ).addClassName( this.options.toggleActive );
			}.bind(this),
			
			afterFinish: function() {
				this.current.hide();
				this.toExpand.setStyle({ height: this.maxHeight + "px" });
				this.current = this.toExpand;
				this.isAnimating = false;
				
				if ( this.queuedExpand ) {
					this.expand(this.queuedExpand);
					this.queuedExpand = null;
				}
				
			}.bind(this)
		});
	}

});

