/**
 * zudolab jqAccordion
 *
 * @version    1
 * @copyright    (c)2008 Takeshi Takatsudo (http://zudolab.net/)
 * @license    MIT (http://www.opensource.org/licenses/mit-license.php)
 */

(function($){

	jqAccordion = function(setting)
	{
		this.bodyHeight = setting.bodyHeight ? setting.bodyHeight : "auto";
		this.trigger = setting.trigger ? setting.trigger : "click";
		this.animation = setting.animation ? setting.animation : "quick";
		this.speed = setting.speed ? setting.speed : 200;
		this.selector_container = setting.container ? setting.container : null;
		this.selector_item = setting.item ? setting.item : null;
		this.selector_header = setting.header ? setting.header : null;
		this.selector_body = setting.body ? setting.body : null;
		this.elemSets = [];
		this.currentSet = null;
		
		/* exec setup when onload */
		var self = this;
		$(function(){ self.setup(); });
	}

	jqAccordion.prototype.setup = function()
	{
		this.prepareSets();
		this.setBodyHeight();
		this.preploadImgs();
		if(!this.elemSets) return;
		this.setEvents();
	}
	jqAccordion.prototype.prepareSets = function()
	{
		var self = this;
		var selector_container = this.selector_container;
		var selector_item = this.selector_item;
		var selector_header = this.selector_header;
		var selector_body = this.selector_body;
		var containers = $(selector_container);
		for(var i=0,container; container=containers[i]; i++){
			prepareOneElemSet(container);
		}
		function prepareOneElemSet(container){
			var currentItemSet = null;
			var itemSets = [];
			var items = $(container).find(selector_item);
			for(var j=0,item; item=items[j]; j++){
				var $item = $(item);
				var $header = $item.find(selector_header);
				var header = $header.get(0);
				var $img = $header.find("img");
				
				/* if jqAccordion header contains img element, prepare img data */
				
				if($img.length!=0){
					var img = $img.get(0);
					var srcOff = img.src;
					var srcOn = srcOff.replace(/\/off\//,"/on/");
				}else{
					var img = null;
				}
				
				var body = $item.find(selector_body).get(0);
				var set= {
					item: item,
					header: header,
					body: body,
					img: img,
					srcOff: srcOff ? srcOff : null,
					srcOn: srcOn ? srcOn : null
				};
				itemSets.push(set);
				
				/* 
					if its class has "showThis", set the set as the active item.
					if accordion header has img in it and it was active img,
					set the item as the active item.
				*/
				if($item.hasClass("showThis")){
					$item.removeClass("showThis").addClass("opened");
					if(img) img.src = srcOn;
					currentItemSet = set;
				}
			}
			self.elemSets.push({
				currentItemSet: currentItemSet,
				itemSets: itemSets
			});
			if(currentItemSet) $(currentItemSet.body).show();
		}
	}
	jqAccordion.prototype.setBodyHeight = function()
	{
		if(this.bodyHeight=="auto") return;
		for(var i=0,elemSet; elemSet=this.elemSets[i]; i++){
			for(var j=0,itemSet; itemSet=elemSet.itemSets[j]; j++){
				$(itemSet.body).height(this.bodyHeight);
			}
		}
	}
	jqAccordion.prototype.preploadImgs = function()
	{
		for(var i=0,elemSet; elemSet=this.elemSets[i]; i++){
			for(var j=0,itemSet; itemSet=elemSet.itemSets[j]; j++){
				if(!itemSet.img) return;
				(new Image).src = itemSet.srcOn;
				(new Image).src = itemSet.srcOff;
			}
		}
	}
	jqAccordion.prototype.setEvents = function()
	{
		var self = this;
		for(var i=0,elemSet; elemSet=this.elemSets[i]; i++){
			for(var j=0,itemSet; itemSet=elemSet.itemSets[j]; j++){
				switch (this.trigger){
					case "click":
						$(itemSet.header).click(changeItem);
						break;
					case "mouseover":
						$(itemSet.header).mouseover(changeItem);
						$(itemSet.header).focus(changeItem);
						break;
				}
			}
		}
		function changeItem(){
			var setInfo = self.getSetInfoFromHeader(this);
			var nextItemSet = setInfo.itemSet;
			var currentElemSet = setInfo.elemSet;
			var currentItemSet = currentElemSet.currentItemSet;
			if(currentItemSet==nextItemSet) return false;
			
			switch(self.animation){
				case "slide":
					slideChange(currentItemSet,nextItemSet);
					break
				default:
					quickChange(currentItemSet,nextItemSet);
					break;
			}
			currentElemSet.currentItemSet = nextItemSet;
			return false;
			
			function quickChange(oldSet, newSet){
				if(oldSet) $(oldSet.body).hide();
				$(newSet.body).show();
				moveOnClass(oldSet, newSet);
				swapImg(oldSet, newSet);
			}
			function slideChange(oldSet, newSet){
				moveOnClass(oldSet, newSet);
				swapImg(oldSet, newSet);
				if(oldSet) $(oldSet.body).stop().slideUp(self.speed);
				var $body = $(newSet.body);
				$body
					.css("height","0")
					.css("display","block")
					.animate({height:getChildrenTotalHeight(newSet.body)},self.speed-10,function(){
						$body.height(self.bodyHeight);
					});
				function getChildrenTotalHeight(elem){
					if(self.bodyHeight!="auto") return self.bodyHeight;
					var children = $(elem).children();
					var totalHeight=0;
					for(var i=0,child; child=children[i]; i++){
						totalHeight+=$(child).outerHeight();
					}
					return totalHeight;
				}
			}
			function moveOnClass(oldSet, newSet){
				if(oldSet) $(oldSet.item).removeClass("opened");
				$(newSet.item).addClass("opened");
			}
			function swapImg(oldSet, newSet){
				if(oldSet && oldSet.img) oldSet.img.src = oldSet.srcOff;
				if(newSet.img) newSet.img.src = newSet.srcOn;
			}
			
		}
	}
	jqAccordion.prototype.getSetInfoFromHeader = function(header)
	{
		for(var i=0,elemSet; elemSet=this.elemSets[i]; i++){
			for(var j=0,itemSet; itemSet=elemSet.itemSets[j]; j++){
				if(itemSet.header==header){
					return {
						elemSet: elemSet,
						itemSet: itemSet
					};
				}
			}
		}
	}
})(jQuery);
