/*
 Class:
 Accordion (inspired by accordion.js v2.0 from Kevin P Miller | http://www.stickmanlabs.com)
 
 Requirements:
 prototype 1.6.0.3
 scriptaculous >= 1.8.1
 Copyright (c) 2008 Ralph Senger

 Author: Ralph Senger

 Accordion is freely distributable under the terms of an MIT-style license.

*/


 // overwite existing script.aculo.us effect-class because of bad implementation, sorry
 Effect.Scale.addMethods({
 
 	setDimensions: function(height, width) {
	    var d = { };
	    if (this.options.scaleX) d.width = width.round() + 'px';
	    d.height = this.options.scaleY ? height.round() + 'px' : this.options.scaleMode.originalHeight != undefined ? this.options.scaleMode.originalHeight + 'px' : '';
	    if (this.options.scaleFromCenter) {
	      var topd  = (height - this.dims[0])/2;
	      var leftd = (width  - this.dims[1])/2;
	      if (this.elementPositioning == 'absolute') {
	        if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
	        if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
	      } else {
	        if (this.options.scaleY) d.top = -topd + 'px';
	        if (this.options.scaleX) d.left = -leftd + 'px';
	      }
	    }
	    this.element.setStyle(d);
    }
    
  });

// the class
if(!Accordion) {

	var Accordion = Class.create({
		
		initialize: function(_eContainer, options) {
			
			// the base of all
			this.container = $(_eContainer) || new Element('div');
			
			// remind the heighest height
			this.elementMaxSize = 0;
			
			// here you'll find the active accordion or null
			this.activePanel = null;
			
			// we want only one opening animation at once
			this.openingInProgress = false;
			this.closingInProgress = false;
			
			// default options
			this.options = Object.extend({
				'openOnStart': 'first',
				'alwaysKeepOneOpen': false,
				'onStart': Prototype.emptyFunction,
				'onOpen': Prototype.emptyFunction,
				'afterOpen': Prototype.emptyFunction,
				'onClose': Prototype.emptyFunction,
				'afterClose': Prototype.emptyFunction,
				'onEvent': 'click',
				'classToggle': 'acToggle',
				'classActive': 'acActive',
				'classContent': 'acContent',
				'dynamicSize': true,
				'direction': 'vertical',
				'duration': 0.5
				}, options || {});
			
			// the animating options
			if (this.options.direction == 'vertical')
				this.effectOptions = new Object({ 'scaleX': false, 'scaleY': true, 'duration': this.options.duration });
			else
				this.effectOptions = new Object({ 'scaleX': true, 'scaleY': false, 'duration': this.options.duration });

			this._initPanels();

			// start the accordion
			this.startAccordion();
			},
			
		_initPanels: function(){
			
			// get all elements of the accordion within container which has
			// classToggle from the options as style class definition
			this._eAccordionToggles = $$('#'.concat(this.container.identify(), ' .', this.options.classToggle));
			this._eAccordionContents = $$('#'.concat(this.container.identify(), ' .', this.options.classContent));
			
			// close all content elements and recieve their height for
			// getting the maximum height
			this._eAccordionContents.each(
				function(_eContent){
					this.elementMaxSize = Math.max(this.elementMaxSize, _eContent.getHeight());
					_eContent.hide();
					}.bind(this));
			
			// setting the maximum height to each panel
			if (!this.options.dynamicSize)
				this._eAccordionContents.each(
					function(_eContent){
						_eContent.setStyle({ 'height': ''.concat(this.elementMaxSize, 'px') });
						}.bind(this));
			
			// observe all toggle elements
			this._eAccordionToggles.each(
				function(_eToggle, index){
					
					// save the position in the array
					_eToggle.index = index;
					
					// connecting toggle + content
					_eToggle._eMyContent = this._eAccordionContents[index];
					_eToggle._eMyContent._eMyToggle = _eToggle;
					
					// observe it
					_eToggle.observe(this.options.onEvent, this._observeToggle.bindAsEventListener(this, _eToggle));
					
					// the activating function
					_eToggle.activatePanel = function(){
						
						if (!this.openingInProgress && !this.closingInProgress){
						
							// normal mode: you can close all panels of the accordion
							if (!this.options.alwaysKeepOneOpen) {
							
								// hide the current active accordion
								if (this.activePanel != null)
									this._closePanel(this.activePanel);
								
								// show the desired panel & keep this one in mind
								if (this.activePanel != _eToggle){
									this._openPanel(_eToggle);
									this.activePanel = _eToggle;
									}
								else
									this.activePanel = null;
								}
							// extended mode: there must be always on open panel
							else{
								var _eClosePanel = null;
								var _eOpenPanel = null;
								
								// get for hiding the current active accordion
								if (this.activePanel != null)
									_eClosePanel = this.activePanel;
								
								// get for showing the desired panel
								if (this.activePanel != _eToggle)
									_eOpenPanel = _eToggle;
								else{
									var prevIndex = _eToggle.index - 1;
									var nextIndex = (_eToggle.index + 1) % this._eAccordionToggles.length;
									
									// getting an alternate panel for opening
									if (nextIndex != _eToggle.index)
										_eOpenPanel = this._eAccordionToggles[nextIndex];
									else if (prevIndex != _eToggle.index)
										_eOpenPanel = this._eAccordionToggles[prevIndex];
									}
								
								// hide and open the correct ones
								if (_eClosePanel && _eClosePanel != _eOpenPanel && this._eAccordionToggles.length > 1)
									this._closePanel(_eClosePanel);
								
								if (_eOpenPanel && _eClosePanel != _eOpenPanel){
									this._openPanel(_eOpenPanel);
									this.activePanel = _eOpenPanel;
									}
								}
							}
						
						}.bind(this)
					}.bind(this));
			
			// option: should all accordions have the same height?
			if (!this.options.dynamicSize)
				this._eAccordionContents.each(
					function(_eContent){
						_eContent.setStyle({ 'height': ''.concat(this.elementMaxSize, 'px') });
						}.bind(this)
					);
					
			},
			
		startAccordion: function(){
			
			var _eAccordion = null;
			
			// which accordion should be displayed
			switch (this.options.openOnStart){
				case 'first':
					_eAccordion = this._eAccordionToggles.first();
					break;
				
				case 'last':
					_eAccordion = this._eAccordionToggles.last();
					break;
				
				default:
					if (Object.isArray(this.options.openOnStart)) {
						this.options.alwaysKeepOneOpen = 'loose';
						_eAccordion = this.options.openOnStart;
						}
					else
						if(this.options.openOnStart || (this.options.alwaysKeepOneOpen && this.options.alwaysKeepOneOpen != 'loose'))
							_eAccordion = this._eAccordionToggles[parseInt(this.options.openOnStart) ? parseInt(this.options.openOnStart) : 0];
				}
			
			// call the event "onStart"
			this.options.onStart(this._eAccordionToggles);
			
			if (_eAccordion)
				if (Object.isArray(_eAccordion)) {
					this.options.openOnStart.each(function(item){
						_eAccordion = this._eAccordionToggles[parseInt(item)];
						if (_eAccordion)
							this._openPanel(_eAccordion);
						}.bind(this));
					}
				else
					_eAccordion.activatePanel();
			},
			
			
			
		_observeToggle: function(event, _eToggle){
			if(this.options.alwaysKeepOneOpen != 'loose')
				_eToggle.activatePanel();
			else {
				if (_eToggle.opened)
					this._closePanel(_eToggle);
				else
					this._openPanel(_eToggle);
				
				this.activePanel = null;
				}
			},
			
			
			
		_openPanel: function(_ePanel){
			// preventing this accordion for showing double animating which causes layout problems
			this.openingInProgress = true;
			
			// call the event "onOpen"
			this.options.onOpen(_ePanel, _ePanel._eMyContent);
			
			// show this content & reset the flag for the animation
			var effectOptions = Object.extend({ 'afterFinish': function(_ePanel){ _ePanel.addClassName(this.options.classActive); _ePanel.opened = true; this.openingInProgress = false; this.options.afterOpen(_ePanel, _ePanel._eMyContent); }.bind(this, _ePanel) }, this.effectOptions);
			new Effect.BlindDown(_ePanel._eMyContent, effectOptions);
			},
			
			
			
		_closePanel: function(_ePanel){
			// preventing this accordion for showing double animating which causes layout problems
			this.closingInProgress = true;
			
			// call the event "onOpen"
			this.options.onClose(_ePanel, _ePanel._eMyContent);
			
			// hide this content & reset the flag for the animation
			var effectOptions = Object.extend({ 'afterFinish': function(_ePanel){ _ePanel.removeClassName(this.options.classActive); _ePanel.opened = false; this.closingInProgress = false; this.options.afterClose(_ePanel, _ePanel._eMyContent); }.bind(this, _ePanel) }, this.effectOptions);
			new Effect.BlindUp(_ePanel._eMyContent, effectOptions);
			},
			
			
			
		getElement: function(){
			return this.container;
			}
		});
	}