/***************************************************************************
 * mootools-expandables.js
 * ---------------
 *   author		-> Tyson Cox
 *   started	-> Tuesday, Jan 6th, 2009
 *   modified	-> Tuesday, Jan 6th, 2009
 *   copyright	-> 
 *   email     	-> tyson@imagin8.com
 *   version    -> 1.0
 *
 * file description
 * ------------------
 * Provides functionality to quickly turn a list into a set of
 * expandable/contractable lists
 *
 *
 * change log
 * ------------------
 * 1.0			Initial development
 *
 ***************************************************************************/


expandableList = new Class({
	
	                /*--------------------------------------------------------o
	----------------\                     Member Variables                    |
	    variables    \-------------------------------------------------------*/
	                
	saveState: Array(),
	
	cookieName: null,
	cookieDomain: null,
	recurseChildren: false,
	defaultState: 'collapsed',
	
	
	                /*--------------------------------------------------------o
	----------------\                    Internal Functions                   |
	     internal    \-------------------------------------------------------*/
		
	initialize: function(list, childSel, childListSel, options) {
		this.cookieName = (options.cookieName) ? options.cookieName : null;
		this.cookieDomain = (options.cookieDomain) ? options.cookieDomain : null;
		this.recurseChildren = (options.recurseChildren) ? true : false;
		this.defaultState = (options.defaultState) ? options.defaultState : 'collapsed';
		
		if ( this.cookieDomain && this.cookieName ) {
			this.saveState = new Hash.Cookie(this.cookieName, {		duration: 60,
																	domain: this.cookieDomain,
																	path: '/'
																});
			list.setProperty('cookieName', this.cookieName);
		}
		
		this.addExpandable(list, childSel, childListSel);
	},
	

	                /*--------------------------------------------------------o
	----------------\                    List Functionality                   |
	      lists      \-------------------------------------------------------*/
	                
	addExpandable: function(list, childSel, childListSel) {
		var eList = this;
		
		if ( list ) {
			var list_elems = list.getChildren((childSel) ? childSel : 'li');
			
			list_elems.each(function (list_elem, index) {
				var children = list_elem.getChildren((childListSel) ? childListSel : 'ul');
				
				if ( children.length > 0 ) {
					var handle = new Element('div', {	'class': 'expand_handle'
													});
													
													
					// Inject the handle into the list
					handle.inject(list_elem.getChildren()[0], 'before');
													
					
					// Mouse event handlers
					handle.addEvent('click', function(e) {
						eList.toggleChildren(this);
					});
					
					// Now attach FX Slide handlers to all children
					children.each(function(child, x) {
						list_elem.fx = new TMSlide(child,	{	'mode': 'vertical',
																'link': 'cancel'
														});
														
						// Recurse lower level lists if necessary
						if ( this.recurseChildren ) {
							this.addExpandable(child, params);
						}
					});
					
					if ( this.saveState.get(list_elem.id) != null ) {
						if ( this.saveState.get(list_elem.id) ) {
							this.setElementDisplay(handle, true, true);
						} else {
							this.setElementDisplay(handle, false, true);
						}
					} else {
						if ( this.defaultState == 'expanded' ) {
							this.setElementDisplay(handle, true, true);
						} else {
							this.setElementDisplay(handle, false, true);
						}
					}
				}
				
			}, this);
		}
		
	},
	
	
	setElementDisplay: function(handle, shown, no_anim) {
		var parent = handle.getParent();
		var list = parent.getParent();
		
		if ( shown ) {
			// Set the state on the object, and add a class to its parent
			handle.setProperty('expandState', 'expanded');
			parent.removeClass('collapsed');
			parent.addClass('expanded');	
			
			if ( no_anim ) {
				parent.fx.show();
			} else {
				parent.fx.slideIn();
			}
		} else {
			// Set the state on the object, and add a class to its parent
			handle.setProperty('expandState', 'collapsed');
			parent.removeClass('expanded');
			parent.addClass('collapsed');	
			
			if ( no_anim ) {
				parent.fx.hide();
			} else {
				parent.fx.slideOut();
			}
		}
		
		// Update cookie if necessary
		if ( list.getProperty('cookieName') && this.saveState ) {
			this.saveState.set(parent.id, shown);
			this.saveState.save();
		}
	},
	
	
	toggleChildren: function(elem) {
		var parent = elem.getParent();
		var list = parent.getParent();
		
		if ( elem.getProperty('expandState') == 'collapsed' ) {
			this.setElementDisplay(elem, true, false);
		} else {
			this.setElementDisplay(elem, false, false);
		}
	}
	
});






TMSlide = new Class({
	Extends:Fx.Slide,

	                /*--------------------------------------------------------o
	----------------\                    Extended Functions                   |
	     extended    \-------------------------------------------------------*/
	
	slideIn: function(A) {
		this.wrapper.setStyle('display', 'block');
		var returnVal = this.start("in",A);
		this.chain(function() {		this.wrapper.setStyle('height', 'auto'); });
		return returnVal;
	},

	
	slideOut: function(A) {
		var returnVal = this.start("out",A)
		this.chain(function() {		this.wrapper.setStyle('display', 'none'); });
		return returnVal;
	},
	
	
	hide: function(A) {
		this.wrapper.setStyle('display', 'none');
		this[A||this.options.mode]();
		this.open=false;
		var returnVal = this.set([-this.offset,0])
		return returnVal;
	},

	
	show: function(A) { 
		this.wrapper.setStyle('display', 'block');
		this[A||this.options.mode]();
		this.open=true;
		var returnVal = this.set([0,this.offset]);
		this.wrapper.setStyle('height', 'auto');
		return returnVal;
	}
});