/*
* Core Weatherhead javascript functions including a lightweight animation engine
* @author R. Dixon et. al
* @note some parts cobbled together from other sources - all of which are noted in comments
*/


/*
* $e returns a reference to the dom object
* @param id	string	id of div
*/
if (window["__coreLoaded"] !== true){
	function $e(id){
		if(document.getElementById && document.getElementById(id)) {
			return document.getElementById(id);
		} else if (document.all && document.all(id)) {
			return document.all(id);
		} else if (document.layers && document.layers[id]) {
			return document.layers[id];
		} else {
			return false;
		}
	}
	
	/*
	* shows a div
	* @param id	string	id of div
	*/
	$e.show=function(id){
		var s = $e(id).style;
		s.display="block";
	}
	
	/*
	* hides a div
	* @param id	string	id of div
	*/
	$e.hide=function(id){	
		var s = $e(id).style;
		s.display="none";
	}
	
	
	$e.setInnerText=function(el,msg){
		if(document.getElementsByTagName("body")[0].innerText != undefined){
	     	$e(el).innerText = msg;
		} else{
	    	$e(el).textContent = msg;
		}
	}
	
	/**
	* Originally from the Yahoo UI library
	* @param id	string	id of div
	* @param p	string	property name
	* @return mixed	the value of the property p
	*/
	$e.getStyle = function(id, p) {
		var el = $e(id);
		var value = null;
		var dv = document.defaultView;
		
		if (p == 'opacity' && el.filters) {// IE opacity
			value = 1;
			try {
				value = el.filters.item('DXImageTransform.Microsoft.Alpha').opacity / 100;
			} catch(e) {
				try {
					value = el.filters.item('alpha').opacity / 100;
				} catch(e) {}
			}
		} else if (el.style[p]) {
			value = el.style[p];
		}else if (el.currentStyle && el.currentStyle[p]) {
			value = el.currentStyle[p];
		}else if ( dv && dv.getComputedStyle ){  // convert camelCase to hyphen-case
			var converted = '';
			for(i = 0, len = p.length;i < len; ++i) {
				if (p.charAt(i) == p.charAt(i).toUpperCase()) {
					converted = converted + '-' + p.charAt(i).toLowerCase();
				} else {
					converted = converted + p.charAt(i);
				}
			}
			if (dv.getComputedStyle(el, '').getPropertyValue(converted)) {
				value = dv.getComputedStyle(el, '').getPropertyValue(converted);
			}
		}
		return value;
	};
	
	/*
	*setStyle
	* @param id	string  name od div to cahnge
	* @param p 	string	name of style property to change 
	* @param val	mixed	the value of the property to set
	*/
	$e.setStyle = function(id, p, v) {
		var el=$e(id);
		if(p=='opacity'){
			if (el.filters) {
				el.style.filter = 'alpha(opacity=' + v * 100 + ')';	
				if (!el.currentStyle.hasLayout) el.style.zoom = 1;
			} else {
				try{ 
					el.style.opacity = v;
				} catch(e){
					try{
						el.style['-moz-opacity'] = v;
					} catch(e){
						try{
							el.style['-khtml-opacity'] = v;
						} catch(e){}
					}
				}
			}
		} else {
			el.style[p] = v;
		}
	};

	/*
	* getElementsByClass
	* Written by Jonathan Snook, http://www.snook.ca/jonathan
	* Add-ons by Robert Nyman, http://www.robertnyman.com
	* @param id reference	this is a reference to a dom object - the top element to search from
	* @param t 	string  	name of tags to look at (i.e. "a", "div", "img", etc...)
	* @param c	string		name of the class to look for
	*/
	function getElementsByClass(id, c, t){
		var arrElements = (t == "*" && id.all)? id.all : id.getElementsByTagName(t);
		var val = new Array();
		c = c.replace(/-/g, "\-");
		var oRegExp = new RegExp("(^|\s)" + c + "(\s|$)");
		var oElement;
		for(var i=0; i<arrElements.length; i++){
			oElement = arrElements[i];
			if(oRegExp.test(oElement.className)){
				val.push(oElement);
			}
		}
		return (val)
	}

	/*
	* shorthand function for tween top and left vcalues of a div
	* @param id	string	id of div
	* @param at	string	animation type
	* @param tx	string	target left value
	* @param ty	string	target top value
	* @param tt	number	time in seconds
	* @param cb function callback function - need to work on this
	*/
	$e.move=function(id,at,tx,ty,tt,cb)
	{
		if(tx != null && ty != null){
			if(tx!=null) $e.animate(id,"left",tx,at,tt,cb);
			if(ty!=null) $e.animate(id,"top",ty,at,tt);
		} else {
			if(tx!=null) $e.animate(id,"left",tx,at,tt,cb);
			if(ty!=null) $e.animate(id,"top",ty,at,tt);
		}
	}
	
	/*
	* @param id	string	id of div
	* @param	p	string	property name
	* @param tp	number	target value of property - do NOT add px for pixels in left and right movement
	* @param	at	string	animation type
	* @param tt	number	time in seconds
	* @return returns a reference to the __anim<property> object applied to the div.
	*/
	
	$e.animate=function(id,p,tp,at,tt,cb)
	{
		if($e(id)["_anim"+p]) {
			var f = $e(id)["_anim"+p];
			f.stop();
			f.id=id;
			f.p=p;
			f.tP=tp;
			f.cb=cb;
			f.tt=tt;
			f.at=at;
			f.start();
		} else {
			$e(id)["_anim"+p]= new __anim(id,p,tp,at,tt,cb);
			$e(id)["_anim"+p].start();
		}
		return $e(id)["_anim"+p];
	}
	
	
	$e.stop=function(id,p){
		if($e(id)["_anim"+p]) {
			$e(id)["_anim"+p].stop();
			$e(id)["_anim"+p]=null;
		}
	}
	
	/*
	* __anim
	* this function should not be called directly, instead it is used by $e.animate
	* @param id	string	id of div
	* @param p	string	property name
	* @param tp	number	target value of property - do NOT add px for pixels in left and right movement
	* @param at	string	animation type
	* @param tt	number	time in seconds
	* @TODO need to be able to take the 'ps' or '%' for values
	*/
	 __anim = function(id, p,tP, at, tt,cb){
		this.n = $e(id);
		this.id= id;
		
		this.p=p;				//property
		this.sP=0;				//start value of property
		this.tP=parseInt(tP);	//target value of property
		this.cb=cb;
		this.tt=tt;
		this.at = at.toLowerCase();
		this.mod=null;
		this.finished=false;
		var self=this;
		this._interval=null;
		this.sTime=0;
		
		this.stop = function(){
			clearInterval(this._interval);
			this._interval=null;	
		}
		
		this.start=function(){
			this.finished=false;
			this.mod = (p == "left" || p =="top")? "px" : null;
			this.sP =  parseFloat( $e.getStyle(this.id,this.p) );
			if(this._interval != null) this.stop();
			this.sTime=new Date().getTime();
			this._interval = setInterval(tween, 10);
			
		}
		
		function tween(){
			var s = self.n.style;
			var now = (new Date().getTime()-self.sTime)/1000;
			if (s)
			{
				if(now < self.tt){
					var c = self[at](now,self.sP,self.tP-self.sP,self.tt)+self.mod;
					window["$e"].setStyle(self.id,self.p,c);
				} else {
					window["$e"].setStyle(self.id,self.tP+self.mod,c);
					self.stop();
					self.finished=true;	
					window.setTimeout(function(){
											if(self.cb != null){
												if(typeof(self.cb) == "function") { self.cb() 
												} else if(typeof(self.cb) == "string") window[self.cb](); }	
											}, 0);
				}
			}
		}
	 
	}//end anim class
	
	//from Yahoo utilities easing
	__anim.prototype.easeBoth = function(t,b,c,d) {if((t/=d/2)<1){return c/2*t*t+b;}return-c/2*((--t)*(t-2)-1)+b;};
	__anim.prototype.linear   = function(t,b,c,d) {return c*t/d+b;};
	__anim.prototype.easeOut  = function(t,b,c,d) {return-c*(t/=d)*(t-2)+b;};
	__anim.prototype.easeIn	  = function(t,b,c,d) {return b+c*((t/=d)*t*t);};
	
	/*
	* Math.bound
	* this confines a number to a upper and lower limit. 
	* ex: Math.bound(10,1,20) would return 10, since that is the upper boundry
	* ex: Math.bound(10,1,-5) would return 1 since that is the lower boundry
	* @param u	number	upper limit of the boundry
	* @param l	number	lower number of the boundry
	* @param n 	number	the current number
	*/
	Math.bound=function(u,l,n){
		if(n > u) n = u;
		if(n < l) n = l;
		return n;
	}
	
	/*
	* Queue
	* from http://www.safalra.com/programming/javascript/queues/
	* 
	*/
	function Queue(){
	  var queue=new Array();
	  var queueSpace=0;
	  this.enqueue=function(element){
	    queue.push(element);
	  }
	  this.dequeue=function(){
	    if (queue.length){
	      var element=queue[queueSpace];
	      if (++queueSpace*2 >= queue.length){
	        for (var i=queueSpace;i<queue.length;i++) queue[i-queueSpace]=queue[i];
	        queue.length-=queueSpace;
	        queueSpace=0;
	      }
	      return element;
	    }else{
	      return undefined;
	    }
	  }
	}
	
	/**
	* this is a placeholder incase we do not have debug loaded
	* the browser won;t throw a fit 
	*/
	var __debugWindow=null;
	
	function trace(msg){
				__debugWindow = window.open("","trace","width=600,height=200,resizable,scrollbars,screenX=0,screenY=0");
			try{
			__debugWindow.document.write(msg+"<br>");
			}catch(e){}
	}
	
	window["__coreLoaded"] == true;
}