﻿/**
 * the Accordion class
 *
 * @author Klaas Dieleman
 * @since feb 2011
 * @copyright eFocus
 *
 * @require jQuery 1.4.2, <http://www.jquery.com>
 *
 * @param Array - elements that function as togglers
 * @param Array - elements that will open/close
 * @param Object - options
 */
function Accordion(togglers, elements, options) {
	
	this.togglers = jQuery(togglers);
	this.elements = jQuery(elements);
	
	if((this.togglers.length == this.elements.length) && this.togglers.length != 0) {
		this.initialize(options);
	} else {
		return false;
	}
	
};


Accordion.prototype = {

	/**
	 * default options
	 */
	options: {

		display			: -1,		// index of item to open initially, with animation, -1 for none, overrules 'show' option
		show			: 0,		// index of item to show initially, -1 for none
		alwaysHide		: false,	// allow closing of all items
		onActive		: null,		// function fired on opened item, current Toggler and Element are passed as arguments
		onBackground	: null		// function fired on closed item, current Toggler and Element are passed as arguments

	},


	/**
	 * sets up Accordion
	 */
	initialize: function(options) {

		jQuery.extend(true, this.options, options);
		
		this.blnInProgress = false;

		this.elements.slideUp(0);

		if(this.options.display != -1) {
			this.showElement(this.options.display);
		} else if (this.options.show != -1) {
			this.showElement(this.options.show, true);
		}

		this.setupEvents();
							
	},


	/**
	 * attach click eventlistener to togglers
	 */
	setupEvents: function() {

		this.togglers.click(jQuery.proxy(function(event) {
			
			// don't fire in case of bubbled event
			if(event.target == event.currentTarget) {
				
				// cancel further action if animation is in progress
				if(this.blnInProgress == true) return false;
			
				event.preventDefault();
				event.stopPropagation();

				var elToggler = jQuery(event.currentTarget);
				var intIndex = this.togglers.index(elToggler);
			
				this.showElement(intIndex);
			}

		}, this));
	
	},


	/**
	 * shows or toggles element, hiding other elements
	 */
	showElement: function(intIndex, blnInstant) {
	
		var intDuration = 400;
		if(blnInstant) intDuration = 0;

		this.elements.clearQueue();

		this.blnInProgress = true;

		// fire onBackground on all items but the clicked one
		if(this.options.onBackground && typeof(this.options.onBackground == 'function')) {
			this.elements.not(jQuery(this.elements[intIndex])).each(jQuery.proxy(function(index, el) {
				this.options.onBackground(jQuery(this.togglers[index]), jQuery(this.elements[index]));
			}, this));
		}

		// close all items but the clicked one
		this.elements.not(jQuery(this.elements[intIndex])).slideUp(intDuration);

		if(this.options.alwaysHide) {
				
			// check whether clicked item was open or closed
			if(jQuery(this.elements[intIndex]).css('display') != 'none') {
				
				// if open, fire onBackground on clicked item
				if(this.options.onBackground && typeof(this.options.onBackground == 'function')) {
					this.options.onBackground(jQuery(this.togglers[intIndex]), jQuery(this.elements[intIndex]));
				}

			} else {
				
				// if closed, fire onActive on clicked item
				if(this.options.onActive && typeof(this.options.onActive == 'function')) {
					this.options.onActive(jQuery(this.togglers[intIndex]), jQuery(this.elements[intIndex]));
				}

			}
			
			// open or close clicked item
			jQuery(this.elements[intIndex]).slideToggle(intDuration, jQuery.proxy(function() {
				this.blnInProgress = false;
			}, this));

		} else {

			// fire onActive on clicked item
			if(this.options.onActive && typeof(this.options.onActive == 'function')) {
				this.options.onActive(jQuery(this.togglers[intIndex]), jQuery(this.elements[intIndex]));
			}

			// open clicked item
			jQuery(this.elements[intIndex]).slideDown(intDuration, jQuery.proxy(function() {
				this.blnInProgress = false;
			}, this));

		}
	
	}
		
}
