// ---- original work ----------------
// @name      The Fade Anything Technique
// @namespace http://www.axentric.com/aside/fat/
// @version   1.0-RC1
// @author    Adam Michela
// ------------------------------------
// modified 10/09/2005
// by andrew hughes
// to support fading any css attribute
// defaults to "backgroundColor" for the attribute
// modified 3/22/2006
// to allow full object fading (opacity);

function fadeCSS(){}

fadeCSS.fade = function (id, attribName, from, to, fps, duration){
	if (typeof id == "object"){
		if (!id.id){
			var newID = "__randomID" + Math.round(Math.random()*99999);
			id.id = newID;
		}
		id = id.id;
	}
	
	if (!fps) fps = 40;
	if (!duration) duration = 3000;
	if (!from || from=="#") from = "#FFFF33";
	if (!attribName) attribName = "backgroundColor";
	if (!to) to = this.getColor(id,attribName);
	
	
	var frames = Math.round(fps * (duration / 1000));
	var interval = duration / frames;
	var delay = interval;
	var frame = 0;
	
	if (from.length < 7) from += from.substr(1,3);
	if (to.length < 7) to += to.substr(1,3);
	
	var rf = parseInt(from.substr(1,2),16);
	var gf = parseInt(from.substr(3,2),16);
	var bf = parseInt(from.substr(5,2),16);
	var rt = parseInt(to.substr(1,2),16);
	var gt = parseInt(to.substr(3,2),16);
	var bt = parseInt(to.substr(5,2),16);
	
	var r,g,b,h;
	while (frame < frames){
		r = Math.floor(rf * ((frames-frame)/frames) + rt * (frame/frames));
		g = Math.floor(gf * ((frames-frame)/frames) + gt * (frame/frames));
		b = Math.floor(bf * ((frames-frame)/frames) + bt * (frame/frames));
		h = this.getHex(r,g,b);
	
		setTimeout("fadeCSS.setColor('"+id+"','"+h+"','"+attribName+"')", delay);

		frame++;
		delay = interval * frame; 
	}
	setTimeout("fadeCSS.setColor('"+id+"','"+to+"','"+attribName+"')", delay);
};
	
fadeCSS.setColor = function (id, c, attribName){
		var o = document.getElementById(id);
		if (o){
			o.style[attribName] = c;
		}
	};
	
fadeCSS.getColor = function (id,attribName){
		var o = document.getElementById(id);
		while(o){
			var c;
			if (window.getComputedStyle) c = window.getComputedStyle(o,null)[attribName];
			if (o.currentStyle) c = o.currentStyle[attribName];
			if ((c != "" && c != "transparent") || o.tagName == "BODY") { break; }
			o = o.parentNode;
		}
		if (c == undefined || c == "" || c == "transparent") c = "#FFFFFF";
		var rgb = c.match(/rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/);
		if (rgb) c = this.getHex(parseInt(rgb[1]),parseInt(rgb[2]),parseInt(rgb[3]));
		return c;
	};
	
fadeCSS.getHex = function (r,g,b){
	r = r.toString(16); if (r.length == 1) r = '0' + r;
	g = g.toString(16); if (g.length == 1) g = '0' + g;
	b = b.toString(16); if (b.length == 1) b = '0' + b;
	return "#" + r + g + b;
};

//force the CSS opacity settings - send in values numbers between 0 -100
fadeCSS.setOpacity = function(objOrID, opacity) {
	var ob = (typeof objOrID == "object")?objOrID:document.getElementById(objOrID);
	if (ob){
	  opacity = (opacity == 100)?99.999:opacity;
	  // IE/Win
	  ob.style.filter = "alpha(opacity:"+opacity+")";	  
	  // Safari<1.2, Konqueror
	  ob.style.KHTMLOpacity = opacity/100;	  
	  // Older Mozilla and Firefox
	  ob.style.MozOpacity = opacity/100;	  
	  // Safari 1.2, newer Firefox and Mozilla, CSS3
	  ob.style.opacity = opacity/100;
	  //alert(opacity);
	}
};
	
fadeCSS.fadeOpacity = function(objOrID, to, duration, opacity, removeOnCompletion) {
		var ob = (typeof objOrID == "object")?objOrID:document.getElementById(objOrID);
	  if (ob) {
			if (!to) to = 0;
			if (!duration) duration = 3000;
			if (!opacity) opacity = 100;
	    fadeCSS.setOpacity(ob.id, opacity);
	    opacity += -4;			
		  if (opacity != to && opacity > 0 && opacity <= 100) {
	      window.setTimeout("fadeCSS.fadeOpacity('"+ob.id+"'," + to + "," + duration + ","+opacity+")", 200);
	    }else{
	    	fadeCSS.setOpacity(ob.id,to);
	    	if (removeOnCompletion){dom.removeObject(ob);}
	    }
	  }
	};

// Method to ease from one value to another via algorithms
fadeCSS.ease = function (t,b,f,d,e,loopFunc,loopFuncArgArray,finishFunc,finishFuncArgArray){
	var res = 20;	//how often this function calls itself in milliseconds
	t = typeof t == "number"?t:0; 		//starting time value
	b = typeof b == "number"?b:0;			//begin value
	f = typeof f == "number"?f:100;		//finish value
	d = typeof d == "number"?d:10;		//duration in seconds
	e = e?e:"easeInExponential";			//default easing engine to use
	var c=f-b;												//delta value from beginning to finish
	if (t<d*(1000/res)){							// determine whether we've reached the end of the journey
		t+=1;														//increment t by 1																		
		window.setTimeout(							//call ourself again
		function(){fadeCSS.ease(t,b,f,d,e,loopFunc,loopFuncArgArray,finishFunc,finishFuncArgArray);},res);
	}else{														//we're done
		if (finishFunc){								//anything to do at the end?
			if (finishFuncArgArray){			//any arguments to pass?
				finishFunc.apply(this,finishFuncArgArray);
			}else{
				finishFunc.call(this);			//otherwise just call the function
			}
		}
	}
	var easeValue = fadeCSS.ease.engine[e](t,b,c,d*(1000/res));	//calc the actual ease value
	if (loopFunc){														//do we run something with each loop?
		if (loopFuncArgArray){									//are there arguments to pass?
			loopFuncArgArray.push(easeValue);			//push() the easeValue onto the arguments
			loopFunc.apply(this,loopFuncArgArray);//apply/call the function
			loopFuncArgArray.length--;						//remove the easeValue
		}else{																	//no arguments?
			loopFunc.call(this,easeValue);				//just pass the easeValue
		}
	}
};

fadeCSS.ease._inOut = function(objOrID,p,isFinished){
	if (!isFinished){
		fadeCSS.ease(null,0,110,.5,"easeOutExponential",fadeCSS.setOpacity,[objOrID],fadeCSS.ease._inOut,[objOrID,p,true]);
	}else{
		fadeCSS.ease(null,100,-10,1,"easeInExponential",fadeCSS.setOpacity,[objOrID],dom.removeObject,[objOrID]);
	}
};

fadeCSS.ease._in = function(objOrID,finishFunc,finishFuncArray){
	fadeCSS.ease(null,0,110,1,"easeInExponential",fadeCSS.setOpacity,[objOrID],finishFunc,finishFuncArray);
};

fadeCSS.ease._out = function(objOrID,finishFunc,finishFuncArray){
	fadeCSS.ease(null,100,-10,1,"easeInExponential",fadeCSS.setOpacity,[objOrID],finishFunc,finishFuncArray);
};


//	ease engine algorithms adapted from Robert Penner's ActionSript versions
//	http://www.robertpenner.com/
fadeCSS.ease.engine = function(){};
fadeCSS.ease.engine.easeInOutExponential = function(t,b,c,d){
	if (t==0) return b;
	if (t==d) return b+c;
	if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
	return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
};
	
fadeCSS.ease.engine.easeInExponential = function(t,b,c,d){
	return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
};

fadeCSS.ease.engine.easeOutExponential = function(t,b,c,d){
	return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
};