// Ver 19990401
//////////////////////////////////////////////////////////////
//
//	Copyright 1997, 1999 Jeremie
//	Free for public non-commercial use and modification
//	as long as this header is kept intact and unmodified.
//	Please see http://www.jeremie.com for more information
//	or email jer@jeremie.com with questions/suggestions.
//
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
/////////////// Public Morphing Function //////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////   to do items/additions/notes
//
// I didnt have time to "fully" comment this throughout, so
// please feel free to ask me to explain anything.
//





////////////////////////////
//// this is the main public function
//// takes the element to morph, time between steps,
//// # of steps, style replacement, and JS code to execute when done
function morph(e,wait,steps,style,done){
	if(e.morphing){
		return;
	}
	e.morphing = true;
	e.step = 0;
	e.done = steps;
	e.wait = wait;
	e.morphDone = done;

	// initialize the given element for the process
	// save some temporary variables within it
	var attribs = _eat_attrib(style);
	if(attribs["top"] != null){
		e.deltaTop = Math.round(Number((_px(attribs["top"]) - _px(e.style.top)) / steps));
		e.finalTop = attribs["top"];
	}else{
		e.deltaTop = null;
		e.finalTop = e.style.top;
	}
	if(attribs["left"] != null){
		e.deltaLeft = Math.round(Number((_px(attribs["left"]) - _px(e.style.left)) / steps));
		e.finalLeft = attribs["left"];
	}else{
		e.deltaLeft = null;
		e.finalLeft = e.style.left;
	}
	if(attribs["height"] != null){
		e.deltaHeight = Math.round(Number((_px(attribs["height"]) - _px(e.style.height)) / steps));
		e.finalHeight = attribs["height"];
	}else{
		e.deltaHeight = null;
		e.finalHeight = e.style.height;
	}
	if(attribs["width"] != null){
		e.deltaWidth = Math.round(Number((_px(attribs["width"]) - _px(e.style.width)) / steps));
		e.finalWidth = attribs["width"];
	}else{
		e.deltaWidth = null;
		e.finalWidth = e.style.width;
	}

	// group all of the coloring elements together
	e.colors = new Array();
	for(attrib in attribs){
		// check each one individually to kludge
		// if we need to use a "safe" name for the css attribute
		if(attrib == "background"){
				e.colors[e.colors.length] = new Array();
				e.colors[e.colors.length - 1].name = attrib;
				e.colors[e.colors.length - 1].safename = attrib;
		}
		if(attrib == "color"){
				e.colors[e.colors.length] = new Array();
				e.colors[e.colors.length - 1].name = attrib;
				e.colors[e.colors.length - 1].safename = attrib;
		}
		if(attrib == "border-color"){
				e.colors[e.colors.length] = new Array();
				e.colors[e.colors.length - 1].name = attrib;
				e.colors[e.colors.length - 1].safename = "borderColor";
		}
	}
	for(var i=0;i<e.colors.length;i++){
		var rgb = _eat_rgb(attribs[e.colors[i].name]);
		var prergb = _eat_rgb(e.style[e.colors[i].safename]);
		e.colors[i].delta = _eat_rgb(attribs[e.colors[i].name]);
		e.colors[i].finish = _eat_rgb(attribs[e.colors[i].name]);
		e.colors[i].delta["red"] = Math.round(Number((rgb["red"] - prergb["red"]) / steps));
		e.colors[i].delta["green"] = Math.round(Number((rgb["green"] - prergb["green"]) / steps));
		e.colors[i].delta["blue"] = Math.round(Number((rgb["blue"] - prergb["blue"]) / steps));
	}

	// fire the first morphing step
	setTimeout("_morphing(document.getElementById('" + e.id + "'))", wait);
}
/////////////////////////////



/////////////////////////////
//// private function that does the work of morphing the element
function _morphing(e){
	e.step++;

//alert("step " + e.step + " delta " + e.deltaTop + " top " + e.style.top);

	if(e.deltaTop!=null){
		e.style.top = document.getElementById('content_box').style.top = _px(e.style.top) + e.deltaTop + "px";
	}

	if(e.deltaLeft!=null){
		e.style.left = document.getElementById('content_box').style.left = _px(e.style.left) + e.deltaLeft + "px";
	}

	if(e.deltaHeight!=null){
		e.style.height = document.getElementById('content_box').style.height = Math.abs(_px(e.style.height) + e.deltaHeight) + "px";
	}

	if(e.deltaWidth!=null){
		e.style.width = document.getElementById('content_box').style.width = Math.abs(_px(e.style.width) + e.deltaWidth) + "px";
	}


	for(var i=0;i<e.colors.length;i++){

             if (e.colors[i].safename=='color') {
                 var rgb = _eat_rgb(e.style[e.colors[i].safename]);
                 document.getElementById("content_box").style[e.colors[i].safename] 	= "rgb("
						+ (e.colors[i].delta["red"] + rgb["red"])
						+ ","
						+ (e.colors[i].delta["green"] + rgb["green"])
						+ ","
						+ (e.colors[i].delta["blue"] + rgb["blue"])
						+ ")";
             }
             else {
                 var rgb = _eat_rgb(e.style[e.colors[i].safename]);
                 e.style[e.colors[i].safename] 	= "rgb("
						+ (e.colors[i].delta["red"] + rgb["red"])
						+ ","
						+ (e.colors[i].delta["green"] + rgb["green"])
						+ ","
						+ (e.colors[i].delta["blue"] + rgb["blue"])
						+ ")";
             }
	}

	// do special things when we are done
	if(e.step == e.done){
		if(e.deltaTop != null)
			e.style.top = document.getElementById('content_box').style.top = e.finalTop;
		if(e.deltaLeft != null)
			e.style.left = document.getElementById('content_box').style.left = e.finalLeft;
		if(e.deltaWidth != null)
			e.style.width = document.getElementById('content_box').style.width = e.finalWidth;
		if(e.deltaHeight != null)
			e.style.height = document.getElementById('content_box').style.height = e.finalHeight;
		for(var i=0;i<e.colors.length;i++){
                     if (e.colors[i].safename=='color') {
                         document.getElementById("content_box").style[e.colors[i].safename] 	= "rgb("
							+ (e.colors[i].finish["red"] + rgb["red"])
							+ ","
							+ (e.colors[i].finish["green"] + rgb["green"])
							+ ","
							+ (e.colors[i].finish["blue"] + rgb["blue"])
							+ ")";
                     }
                     else {
                         e.style[e.colors[i].safename] 	= "rgb("
						+ (e.colors[i].delta["red"] + rgb["red"])
						+ ","
						+ (e.colors[i].delta["green"] + rgb["green"])
						+ ","
						+ (e.colors[i].delta["blue"] + rgb["blue"])
						+ ")";
                     }
		}
		e.morphing = false;
		eval(e.morphDone);
	}else{
		setTimeout("_morphing(document.getElementById('" + e.id + "'))", e.wait);
	}
	return;
}


//////////////////
//// util for element attribute parsing
//// returns an array of all of the keys = values
function _eat_attrib(str){
	var chunks = new Array();
	var all = new Array();

	chunks=str.split(";");

	for(var i=0;i<chunks.length;i++){
		var tmpA = new Array();
		tmpA=chunks[i].split(":");
		all[tmpA[0]]=tmpA[1];
	}
	return all;
}
////////////////////


//////////////////
//// util for style rgb(#,#,#) parsing
//// returns an array of red/green/blue = number
function _eat_rgb(str){
	var all = new Array();

	var a = str.indexOf("(");
	var b = str.indexOf(")");

	str = str.substring(a + 1, b);

	var tmpA = str.split(",");

	all["red"]=Number(tmpA[0]);
	all["green"]=Number(tmpA[1]);
	all["blue"]=Number(tmpA[2]);

	return all;
}
////////////////////


//////////////////
//// util for handling the "123px" style attribs
//// returns the numerical value, there has gotta be a better way?
function _px(pixels)
{
	loc = pixels.indexOf("px");
	if(loc != -1)
		num = pixels.substring(0, loc);
	else
		num = pixels;
	return Number(num);
}