/**
 * Item Toggler allows to show/hide individual and all items.
 * @author NOSE
 *
 * @requires jquery.js 
 * @example $("#menu").itemToggler(); 
 * @before  
	<div id="menu">
		<a href="#" class="showhide">show all</a>
		<h3 class="toggler collapsed">link a</h3>
		<div class="hidden item">content a</div>
		<h3 class="toggler collapsed">link b</h3>
		<p>something inbetween</p>
		<div class="hidden item">content b</div>
		<h3 class="toggler collapsed">link c</h3>
		<div class="hidden item"> content c</div>
	</div>
 *
 * @option selectorShowHide 	Selector show hide link.
 * @option selectorToggler 		Selector toggler.
 * @option selectorItem 		Selector item.
 * @option selectorClose 		Selector close link (null if none).
 * @option classCollapsed 		Class name collapsed.
 * @option classExpanded 		Class name show all.
 * @option msgShowAll 			Message show all.
 * @option msgHideAll 			Message hide all.
 * @option slideDownSpeed 		Values slow or fast.
 * @option slideUpSpeed 		Values slow or fast.
 * @option slideItem			Either true/false to slide.
 * @option itemMessage			True to change the items message.
 * @option msgItemExpanded		Message expanded item.
 * @option msgItemCollapsed		Message collapsed item.
 * @option expanded				Initially expanded items (e.g. 0;2;5;).
 * @option accordion 			Set to true for accordion behaviour.
 * @option catchEvent 			Set to click or mouseover.
 * 
 * @version 1.2.0	added item message and additional close link
 * @version 1.1.2	fix for ie 5.5 (selector instead of class)
 * @version 1.1.1	fix for expanding table rows
 * @version 1.1.0	added accordion behaviour
 * @version 1.0.0	initial version			
 */
jQuery.fn.itemToggler = function(op) {	
	// defaults
	var defaults =  {
			selectorShowHide: "a.showhide",
			selectorToggler: "h3.toggler",
			selectorItem: "div.item",	
			selectorClose:null,		
			classCollapsed: "collapsed",
			classExpanded: "expanded",
			msgShowAll: "show all",
			msgHideAll: "hide all",
			slideDownSpeed: 450,
			slideUpSpeed: 300,
			slideUpEasing:"easeOutQuad",
			slideDownEasing:"easeOutQuad",
			itemMessage:false,
			msgItemExpanded:"hide details",
			msgItemCollapsed:"show details",
			slideAll: false,
			slideItem: true,
			expanded:null,
			accordion:false,
			catchEvent: "click"
	};
	jQuery.extend(defaults, op);
	
	// params
	var sAll = true;
	var showHideAll = new Array();
	jQuery(this).find(defaults.selectorShowHide).each(function(i){
		jQuery(this).bind(defaults.catchEvent, toggleAll);	
		showHideAll.push(this);
	});	
	
	// items
	var togglers = new Array();
	var items = new Array();
	var expanded = new Array();
	var closers = new Array();
	jQuery(this).find(defaults.selectorItem).each(function(i){
		// store
		items.push(this);
		// hide
		//jQuery(this).css("visibility","visible"); // for table rows
		jQuery(this).hide();
	});
	jQuery(this).find(defaults.selectorToggler).each(function(i){
		// store
		jQuery(this).attr("rel",i.toString());
		togglers.push(this);
		expanded.push(false);
		
		// event
		jQuery(togglers[i]).bind(defaults.catchEvent,function() {
			// link
			toggleItem((jQuery(this).attr("rel")));
		});
	});	
	// close
	if (defaults.selectorClose) {
		jQuery(this).find(defaults.selectorClose).each(function(i){
			// store
			jQuery(this).attr("rel",i.toString());
			closers.push(this);
		
			// event
			jQuery(closers[i]).bind(defaults.catchEvent,function() {
				// link
				toggleItem((jQuery(this).attr("rel")));
			});
		});	
	}
	
	// initialize
	if (defaults.expanded) {
		var values = defaults.expanded.split(";");
		for (var i = 0; i < values.length; i++) {
			var v = values[i];
			if (v) {
				showItem(v,false);
			}
		}
	}	
	for (var i = 0; i < togglers.length; i++) {
		var t = togglers[i];
		if (jQuery(t).hasClass(defaults.classExpanded)) {
			showItem(i,false);
		}
	}


	/*
	 * Toggles all items.
	 */
	function toggleAll() {
		if (sAll) {
			showAll();
		}
		else {
			hideAll();
		}
	}
	
	/*
	 * Shows all items.
	 */
	function showAll() {
			// items
			for (var i = 0; i < items.length; i++) {
				if (! expanded[i]) {
				  showItem(i,defaults.slideAll);
				}
			}
		    setShowAll(false);
	}
	/*
	 * Hides all items.
	 */
	function hideAll() {
		// items
		for (var i = 0; i < items.length; i++) {
			if (expanded[i]) {
			  hideItem(i,defaults.slideAll);
			}
		}
		setShowAll(true);
	}
	
	/*
	 * Toggles an item.
	 */
	function toggleItem(i) {
		// item
		if (expanded[i]) {
			hideItem(i,defaults.slideItem);
		}
		else {
			showItem(i,defaults.slideItem);
			
		}
		
		// accordion
		if (defaults.accordion) {
			for (var j = 0; j < items.length; j++) {
				if (j != i && expanded[j]) {
					hideItem(j,defaults.slideItem);
				}
			}
		 }
		
		// check
		if(isAllExpanded()) {
			setShowAll(false);
		}
		if(isAllCollapsed()) {
			setShowAll(true);
		}

	}
	
	/*
	 * Sets the show/hide title.
	 */
	function setShowAll(v) {
		// set html
		if (v) {
			for (var i = 0; i < showHideAll.length; i++) {
				jQuery(showHideAll[i]).html(defaults.msgShowAll);
			}
		}
		else {
			for (var i = 0; i < showHideAll.length; i++) {
				jQuery(showHideAll[i]).html(defaults.msgHideAll);
			}
		}	
		// flag
		sAll = v;
	}
	
	/*
	 * Indicates if all expanded.
	 */
	function isAllExpanded() {
		var allExpanded = true;
		for (var i = 0; i < expanded.length; i++) {
			if (! expanded[i]) {
				allExpanded = false;
				break;
			}			
		}
		return allExpanded;
	}
	
	/*
	 * Indicates if all collapsed.
	 */
	function isAllCollapsed() {
		var allCollapsed = true;
		for (var i = 0; i < expanded.length; i++) {
			if (expanded[i]) {
				allCollapsed = false;
				break;
			}			
		}
		return allCollapsed;
	}
	
	/*
	 * Shows an item.
	 */
	function showItem(i,slide) {
		var t = togglers[i];
		var e = items[i];
		
		// class
		jQuery(t).removeClass(defaults.classCollapsed);
		jQuery(t).addClass(defaults.classExpanded);
		// item
		if (defaults.itemMessage) {
			jQuery(t).html(defaults.msgItemExpanded);
		}
		// content
		if (slide) {
			jQuery(e).show();
			var h = jQuery(e).height();
			jQuery(e).css("height","0px");
			jQuery(e).animate({"height":h+"px"},defaults.slideDownSpeed,defaults.slideDownEasing);
		}
		else {
			jQuery(e).show();
		}
		// item
		expanded[i] = true;
	}
	
	/*
	 * Hides an item.
	 */
	function hideItem(i,slide) {
		var t = togglers[i];
		var e = items[i];
		
		// class
		jQuery(t).addClass(defaults.classCollapsed);
		jQuery(t).removeClass(defaults.classExpanded);
		// item
		if (defaults.itemMessage) {
			jQuery(t).html(defaults.msgItemCollapsed);
		}
		// content
		if (slide) {
			jQuery(e).slideUp(defaults.slideUpSpeed,defaults.slideUpEasing);
		}
		else {
		    jQuery(e).hide();
		}

		// item
		expanded[i] = false;
	}
  
    // return
    return this;
};
