/*
:: Script Information ::
Title       : expandable and collasible menu with state stored by cookie
Author      : livibetter
Created date: 04/28/2006
Updated date: 22:34 10/26/2006
Version     : 0.2.1.2
Credit      : cookies.js by RoBorg
			  lb_common.js 0.1
			  lb_html.js 0.1
License     : GNU Lesser General Public License
Copyright   : 2006 livibetter

:: Contact Information ::
eMail		: web@livibetter.com
MSN			: livibetter@gmail.com
Website		: http://www.livibetter.com
*/

c.setExpires(new Date(new Date().getTime() + 604800000));

/*
	Class: clb_menu_method
		Describe how the menu would be collapsed or expanded
	Parameters:
		duration:
			number
				in millisecond.
				0 means instantly collapsed or expanded
			Default 1000ms
		stepsSizing:
			number
				how many sizing steps in duration.
				0 means instant sizing.
			Default=10
		stepsFading :
			number
				how many fading steps in duration.
				0 means instant fading.
			Default=10
*/
function clb_menu_method(duration, stepsSizing, stepsFading){
	// Set duration of sizing and fading
	this.duration = (typeof duration=="number")?duration:1000;
	// Set steps of sizing if there is a value and duration != 0, or no sizing
	this.stepsSizing = (this.duration==0)?0:((typeof stepsSizing=="number")?stepsSizing:10);
	// Set interval for sizing
	this.intervalSizing = (this.stepsSizing>0)?(this.duration / this.stepsSizing):0;
	// Set steps of fading, same as how sizing
	this.stepsFading = (this.duration==0)?0:((typeof stepsFading=="number")?stepsFading:10);
	// Set interval for fading
	this.intervalFading = (this.stepsFading>0)?(this.duration / this.stepsFading):0;
	}

/*
	Class: clb_menu
*/
function clb_menu(Object, bCollapse, methodCollapsing, sizeCollapsed, sizeExpanded, rangeOpacity, methodCookie, fOnDone){
	if(typeof Object!="object") return;
	this.scan = scan;
	this.toggle = toggle;
	this.sizing = sizing;
	this.fading = fading;
	this.checkDone = checkDone;
	/*
		Initial
		Parameters:
			undefined, null:
				Default lb_menu object.
			Object:
				object
					A Div needs lb_menu functionality.
			bCollapse:
				boolean
					Is this menu collapse at first time(can't find data in cookie)?
				Default false
			methodCollapsing:
				clb_menu_method
					Default Collapsing Method
			sizeCollapsed:
				clb_size
					Collapsed Size of menu
				Default 0, 0
			sizeExpanded:
				clb_size
					Expanded Size of menu
				Default offsetWidth, offset Height of Object
			rangeOpacity:
				clb_range
					Define how to change opacity.
				Default 0 to 100;
			methodCookie:
				undefined, null
					only default method
				clb_menu_method
					Collapsing Method for cookie say collapse. If this is not set, the default method will be used.
			fOnDone:
				undefined, null
					no callback function is needed
				function
					After menu collapsed or expanded, it invokes fOnDone(this), which this is current menu object.
	*/
	if(arguments.length>0){
		// *****************
		// Initial variables
		this.target = Object;
		// Assign this menu to target Object
		Object.menu = this;
		// Set style for Object 
		this.target.style.overflow = "hidden"
		// Set default method
		this.methodDefault = methodCollapsing;
		// Set collapsed size
		if(sizeCollapsed == null)
			this.sizeCollapsed = new clb_size(0,0);
		else
			this.sizeCollapsed = sizeCollapsed;
		// Set expanded size
		if(sizeExpanded == null)
			this.sizeExpanded = new clb_size(this.target.offsetWidth, this.target.offsetHeight);
		else
			this.sizeExpanded = sizeExpanded;
		// Set opacity range
		if(rangeOpacity == null)
			this.rangeOpacity = new clb_range(0, 100);
		else
			this.rangeOpacity = rangeOpacity;
		// Set callback functions
		if(typeof fOnDone == "function")
			this.onDone = fOnDone;
		// Set initial state
		this.state = "Expanded";
		// ***********************
		// Check cookies for state
		statePrev = c.getValue("lb_menu_" + this.target.id);
		switch(statePrev){
			case "Collapsed":
				bCollapse = true;	// contunue at next case
			case undefined:
				// It is the first time
				if(bCollapse == true)
					// Collapse at first time, same as collapsing by cookie
					if(methodCookie!=null)
						this.toggle("collapse", methodCookie);
					else
						this.toggle("collapse"); // Use default method
						
				break;
			default:
				// Expanded, do nothing
				// NOTE: assuming sizeExpanded equals offsetWidth, offsetHeight always.
			}
		}
	/*
		Method: scan
		Paraments:
	*/
	function scan(){
		// TODO: Not implemented yet.
		}
	/*
		Method: toogle
		Paraments:
			method:
				undefined, null:
					Using default method and toggle
				sToggle:
					"expand"
						Do expand
					"collapse"
						Do expand
					"toggle", null, undefined
						Do toggle
				clb_menu_method:
					overrides method for toogling
	*/
	function toggle(sToggle, method){
		// Check state
		if(this.state=='Expanding' || this.state=='Collapsing') return;
		if(this.state=='Expanded' && sToggle=='expand') return;
		if(this.state=='Collapsed' && sToggle=='collapse') return;
		// Use default or override
		this.methodCurrent = (method==null)?this.methodDefault:method;
		// Set count for callback function.
		this.countdown = 2;
		
		// ****************
		// Starting
		this.methodCurrent.countSizing = 0;
		this.methodCurrent.countFading = 0;

		this.state = (this.state=='Expanded')?'Collapsing':'Expanding';
		setTimeout("document.getElementById('"+this.target.id+"').menu.sizing()", Math.round(this.methodCurrent.intervalSizing));
		setTimeout("document.getElementById('"+this.target.id+"').menu.fading()", Math.round(this.methodCurrent.intervalFading));
		}
	/*
		Method: sizing
				for collapsing or expanding
		Parameters:

	*/
	function sizing(sID){
		var bExpanding = this.state=="Expanding";
		this.methodCurrent.countSizing++;
		if(this.methodCurrent.countSizing>=this.methodCurrent.stepsSizing){
			// End of sizing
			if(bExpanding){
				this.target.style.width  = this.sizeExpanded.width + 'px';
				this.target.style.height = this.sizeExpanded.height + 'px';
				}
			else{
				this.target.style.width  = this.sizeCollapsed.width + 'px';
				this.target.style.height = this.sizeCollapsed.height + 'px';
				}
			this.checkDone();
			}
		else{
			// In progress
			var intervalWidth  = (this.sizeExpanded.width  - this.sizeCollapsed.width )/this.methodCurrent.stepsSizing*this.methodCurrent.countSizing*(bExpanding*2 - 1);
			var intervalHeight = (this.sizeExpanded.height - this.sizeCollapsed.height)/this.methodCurrent.stepsSizing*this.methodCurrent.countSizing*(bExpanding*2 - 1);
			this.target.style.width  = (((bExpanding)?this.sizeCollapsed.width :this.sizeExpanded.width ) + intervalWidth ) + "px";
			this.target.style.height = (((bExpanding)?this.sizeCollapsed.height:this.sizeExpanded.height) + intervalHeight) + "px";
			// Keep sizing
			setTimeout("document.getElementById('"+this.target.id+"').menu.sizing()", Math.round(this.methodCurrent.intervalSizing));
			}
		}
	/*
		Method: fading
				for fading in or out
		Parameters:
	*/
	function fading(){
		var bExpanding = this.state=="Expanding";
		this.methodCurrent.countFading++;
		if(this.methodCurrent.countFading>=this.methodCurrent.stepsFading){
			// End of fading
			lb_html_setOpacity(this.target, (bExpanding)?this.rangeOpacity.to:this.rangeOpacity.from);
			this.checkDone();
			}
		else{
			// In progress
			var interval = (this.rangeOpacity.to - this.rangeOpacity.from)/this.methodCurrent.stepsFading*this.methodCurrent.countFading*(bExpanding*2 - 1);
			lb_html_setOpacity(this.target, ((bExpanding)?this.rangeOpacity.from:this.rangeOpacity.to) + interval);
			// Keep fading
			setTimeout("document.getElementById('"+this.target.id+"').menu.fading()", Math.round(this.methodCurrent.intervalFading));
			}
		}
	/*
		Method: checkDone
				Changing state and check both sizing and fading are done. If both are done, then call invoke onDone.
		Parameters:
	*/
	function checkDone(){
		this.countdown--;
		if(this.countdown==0){
			this.state = (this.state=="Expanding")?"Expanded":"Collapsed";
			c.setValue("lb_menu_" + this.target.id, this.state);
			if(typeof this.onDone == "function")
				this.onDone(this);	// Invoke event
			}
		}
	}
