/* 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("script.aculo.us required");
}
var Accordion = Class.create({

    initialize: function(id, options) {
        if(!$(id)){
        	throw(container+" not found");
        	return false;
        }
        this.accordion = $(id);
        
        this.options = Object.extend({
            toggleClass: "acc_toggle",
            toggleFirstClass: "acc_toggle_first",
            toggleLastClass: "acc_toggle_last",
            toggleActiveClass: "acc_toggle_active",
            contentClass: "acc_content",
            contentLastClass: "acc_content_last",  
	    toggleFollowClass: "acc_toggle_after",
            toggleAdditionalHTML: '<span class="acc_content_bottom"></span><span class="acc_icon"></span><span class="acc_content_top"></span>',
            contentAdditionalHTML: '<p class="clear"></p>', // needed for IE6 getHeight 
            contentEndHTML:'<span class="acc_content_end"></span>',
            slideDuration: 0.4,
            slideFps: 35,
            openAt: 0
        }, options || {});
        
        this.contents = this.accordion.select('.'+this.options.contentClass);
        this.headers = this.accordion.select('.'+this.options.toggleClass);
        this.isAnimating = false;
        this.maxHeight = 0;
        this.current = this.contents[this.options.openAt];
        this.toExpand = null;
        
        this.noCurrent = false;
        this.closeAll = false;

	this.styleToggles();
        this.checkMaxHeight();
        this.initialHide();
        this.attachInitialMaxHeight();

        var clickHandler =  this.clickHandler.bindAsEventListener(this);
        this.accordion.observe('click', clickHandler);
    },

    expand: function(el) {
        this.toExpand = el.next('.'+this.options.contentClass);
        if(!this.noCurrent && this.current == this.toExpand){
            this.closeAll = true;
        }else{
            this.toExpand.show();
        }
        this.animate();
    },

    checkMaxHeight: function() {
        for(var i=0; i<this.contents.length; i++) {
            this.contents[i].innerHTML+=this.options.contentAdditionalHTML; 
            if(this.contents[i].getHeight() > this.maxHeight) {
                this.maxHeight = this.contents[i].getHeight();
            }
        }
    },

    attachInitialMaxHeight: function() {
	this.current.previous('.'+this.options.toggleClass).addClassName(this.options.toggleActiveClass);
        if(this.current.getHeight() != this.maxHeight) this.current.setStyle({height: this.maxHeight+"px"});
    },

    clickHandler: function(e) {
        var el = e.element();
        if((el.hasClassName(this.options.toggleClass) || el.up('.'+this.options.toggleClass)) && !this.isAnimating) {
            el.hasClassName(this.options.toggleClass)? this.expand(el):this.expand(el.up('.'+this.options.toggleClass));
        }
    },

    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});
            }
        }
    },

    styleToggles: function(){
        for(var i=0; i<this.headers.length; i++){
        	if(i==0){this.headers[i].addClassName(this.options.toggleFirstClass)}
        	else if(i==this.headers.length-1){this.headers[i].addClassName(this.options.toggleLastClass)}
		this.headers[i].innerHTML+=this.options.toggleAdditionalHTML;
        }
        this.contents.last().innerHTML+=this.options.contentEndHTML;
        if(this.current.next('.'+this.options.toggleClass)){this.current.next('.'+this.options.toggleClass).addClassName(this.options.toggleFollowClass);}
    },

    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
        };

        if(!this.closeAll){effects.push(new Effect.Scale(this.toExpand, 100, options));}

        options = {
            sync: true,
            scaleContent: false,
            transition: Effect.Transitions.sinoidal,
            scaleX: false,
            scaleY: true
        };

        if(!this.noCurrent){effects.push(new Effect.Scale(this.current, 0, options));}

        new Effect.Parallel(effects, {
            duration: this.options.slideDuration,
            fps: this.options.slideFps,
            queue: {
                position: 'end',
                scope: 'accordion'
            },
            beforeStart: function() {
                this.isAnimating = true;
                this.current.previous('.'+this.options.toggleClass).removeClassName(this.options.toggleActiveClass);
                if(!this.closeAll){this.toExpand.previous('.'+this.options.toggleClass).addClassName(this.options.toggleActiveClass);}
                if(this.current.next('.'+this.options.toggleClass)){this.current.next('.'+this.options.toggleClass).removeClassName(this.options.toggleFollowClass);}
                if(!this.closeAll && this.toExpand.next('.'+this.options.toggleClass)){this.toExpand.next('.'+this.options.toggleClass).addClassName(this.options.toggleFollowClass);}
            }.bind(this),
            afterFinish: function() {
                if(!this.noCurrent){this.current.hide();}
                if(!this.closeAll){this.toExpand.setStyle({ height: this.maxHeight+"px" });}
                this.current = this.toExpand;
                this.isAnimating = false;
                this.closeAll?this.noCurrent=true:this.noCurrent=false;
                this.closeAll = false;
            }.bind(this)
        });
    }

});
