/* 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 = {
				toggleClass: "AccordionPanelTab",
				toggleActive: "AccordionPanelTabActive",
				contentClass: "AccordionPanelContent"
		}
		this.contents = this.accordion.select('div.'+this.options.contentClass);
		this.isAnimating = false;
		this.maxHeight = [];
		if (typeof(defaultExpandedCount) != 'undifined') this.current = this.contents[defaultExpandedCount];
		this.toExpand = null;

		this.checkMaxHeight();
		this.initialHide();
		this.attachInitialMaxHeight();

		var clickHandler =  this.clickHandler.bindAsEventListener(this);
		this.accordion.observe('click', clickHandler);
	},

	expand: function(el) {
		this.toExpand = el.next('div.'+this.options.contentClass);
		if (this.current != this.toExpand){
			this.toExpand.show();
			this.animate();
		}
		else {
			this.disanimate();
		}
	},

	checkMaxHeight: function() {
		for(var i=0; i<this.contents.length; i++) {
			if (!this.contents[i].getAttribute('id')) this.contents[i].setAttribute('id', 'accordion'+i);
			this.maxHeight[this.contents[i].getAttribute('id')] = this.contents[i].getHeight();
		}
	},

	attachInitialMaxHeight: function() {
		if (this.current) this.current.previous('.'+this.options.toggleClass).addClassName(this.options.toggleActive);
	},

	clickHandler: function(e) {
		var el = e.element();
		if(el.hasClassName(this.options.toggleClass) && !this.isAnimating) {
			this.expand(el);
		}
	},

	initialHide: function(){
		for(var i=0; i<this.contents.length; i++){
				if(this.contents[i] != this.current) {
					this.contents[i].hide();
					this.contents[i].setStyle({height: 0});
				}
		}
	},

	animate: function() {
		var effects = new Array();
		var options = {
				sync: true,
				scaleFrom: 0,
				scaleContent: false,
				transition: Effect.Transitions.sinoidal,
				scaleMode: {
					originalHeight: this.maxHeight[this.toExpand.getAttribute('id')],
					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
		};
		if (this.current) effects.push(new Effect.Scale(this.current, 0, options));
		var myDuration = 0.75;

		new Effect.Parallel(effects, {
				duration: myDuration,
				fps: 35,
				queue: {
					position: 'end',
					scope: 'accordion'
				},
				beforeStart: function() {
					this.isAnimating = true;
					if (this.current) this.current.previous('.'+this.options.toggleClass).removeClassName(this.options.toggleActive);
					this.toExpand.previous('.'+this.options.toggleClass).addClassName(this.options.toggleActive);
				}.bind(this),
				afterFinish: function() {
					if (this.current) this.current.hide();
					this.toExpand.setStyle({ height: this.maxHeight[this.toExpand.getAttribute('id')]+"px" });
					this.current = this.toExpand;
					this.isAnimating = false;
				}.bind(this)
		});
	},

	disanimate: function() {
		var myDuration = 0.75;
		var effects = new Array();
		var options = {
				scaleFrom: 100,
				scaleContent: false,
				transition: Effect.Transitions.sinoidal,
				scaleMode: {
					originalHeight: this.maxHeight[this.toExpand.getAttribute('id')],
					originalWidth: this.accordion.getWidth()
				},
				duration: myDuration,
				beforeStart: function() {
					this.isAnimating = true;
					this.toExpand.previous('.'+this.options.toggleClass).removeClassName(this.options.toggleActive);
				}.bind(this),
				afterFinish: function() {
					this.toExpand.setStyle({ height: "0px" });
					this.current = null;
					this.toExpand.hide();
					this.isAnimating = false;
				}.bind(this),
				scaleX: false,
				scaleY: true
		};
		new Effect.Scale(this.toExpand, 0, options);
	}
});