/* Syntax: motionTween("objectName", targetX, targetY, topSpeed, easeIn, easeOut)
Note: to change the "frame rate" of the motion tween,
change the variable "frameRate" at the top of the "motionTween" function

"objectName" - A string literal reference to the JavaScript object to be animated
targetX & Y - The coordinates (whole numbers, decimals will be rounded by the browser) you want it to move to
topSpeed - The maximum number of pixels you want it to move per "frame" in a straight line
easeIn - The lower this number, the longer it will take for the object to reach top speed
         If the "easeIn" value is 0, the object will begin at top speed
easeOut - The lower this number, the earlier the object will begin to slow down before reaching its destination
         If the "easeOut" value is 0, the object will "stop on a dime"
*/

function motionTween(objectName, targetX, targetY, topSpeed, easeIn, easeOut)
	{
		window[objectName + "IsDoneMoving"] = false;

	/* The "frame rate" of the motion tween, 41 is about 24 fps */
		var frameRate = 41;
	
	/* Find the current location of the element, and determine the angle between its current and target coordinates */
		var startX = window[objectName].offsetLeft;
		var startY = window[objectName].offsetTop;
		
		var rise = targetY - startY;
		var ySpeedPositive = true;
		if (rise < 0)
			{
				rise = -rise;
				ySpeedPositive = false;
			}
		
		var run = targetX - startX;
		var xSpeedPositive = true;
		if (run < 0)
			{
				run = -run;
				xSpeedPositive = false;
			}					
		
		var angle = new Number;
			(rise != 0 && run != 0) ? angle = Math.atan(rise/run) * 180 / Math.PI : null;
			(rise == 0) ? angle = 0 : null;
			(run == 0) ? angle = 90 : null;
	
	
		
	/* Set the x and y movement ratios for the specified element, based on the angle found above */
		var xRatio = (xSpeedPositive == true) ? Math.cos(angle * Math.PI / 180) :
				-(Math.cos(angle * Math.PI / 180));
			(run == 0) ? xRatio = 0 : null;
		
		var yRatio = (ySpeedPositive == true) ? Math.sin(angle * Math.PI / 180) :
				-(Math.sin(angle * Math.PI / 180));
			(rise == 0) ? yRatio = 0 : null;
			
	/* Set the x and y speeds of the target element to 0, and set the target speed */
		window[objectName + "xSpeed"] = 0;
		window[objectName + "ySpeed"] = 0;
		var xTargetSpeed = xRatio * topSpeed;
		var yTargetSpeed = yRatio * topSpeed;
		
	/* If easing in is set to 0, set speed to targetSpeed */
		if (easeIn == 0)
			{
				window[objectName + "xSpeed"] = xTargetSpeed;
				window[objectName + "ySpeed"] = yTargetSpeed;
			}
				
	/* If easing out is greater than 0 then find the x & y points where the target object should start easing out
	by starting at the end points and easing in backwards */
		var easeOutXStart = 0;
		var easeOutYStart = 0;
		window[objectName + "easeInDone"] = false;
		
		if (easeOut > 0)
			{		
				var testX = targetX;
				var testY = targetY;
				var xTestSpeed = 0;
				var yTestSpeed = 0;

				while (Math.abs(xTestSpeed) < Math.abs(xTargetSpeed) || Math.abs(yTestSpeed) < Math.abs(yTargetSpeed))
					{
						xTestSpeed -= xRatio * easeOut;
						yTestSpeed -= yRatio * easeOut;
						
						testX += xTestSpeed;
						testY += yTestSpeed;
					}
					
				easeOutXStart = testX;
				easeOutYStart = testY;
			}
		

	/* Declare global variables for tracking the sub-pixel position of the target object */
		window[objectName + "currentX"]	= window[objectName].offsetLeft;
		window[objectName + "currentY"]	= window[objectName].offsetTop;
	
		
	/* Set up the motion tween interval	*/
		var intervalCall = "motionTweener('"+objectName+"',"+targetX+","+targetY+","+xRatio+","+yRatio+","+xTargetSpeed+","+yTargetSpeed+","+
				easeIn+","+easeOut+","+easeOutXStart+","+easeOutYStart+")";
		window[objectName + "MotionTweenInterval"] = setInterval(intervalCall, frameRate);

	}
	
	
function motionTweener(objectName, targetX, targetY, xRatio, yRatio, xTargetSpeed, yTargetSpeed,
                       easeIn, easeOut, easeOutXStart, easeOutYStart)
	{
	/* Move the sub-pixel "currentX" and "currentY" values by the current speed of the object */		
		window[objectName + "currentX"] += window[objectName + "xSpeed"];
		window[objectName + "currentY"] += window[objectName + "ySpeed"];

	/* If easing is on, and the object hasn't reached full speed (easeInDone == false), increase the speed */
		(Math.abs(window[objectName + "xSpeed"]) < Math.abs(xTargetSpeed) && window[objectName + "easeInDone"] == false) ? 
			window[objectName + "xSpeed"] += xRatio * easeIn : null;
		
		(Math.abs(window[objectName + "ySpeed"]) < Math.abs(yTargetSpeed) && window[objectName + "easeInDone"] == false) ? 
			window[objectName + "ySpeed"] += yRatio * easeIn : null;
		
	/* If the object has reached the target speed, set it to the target speed, and set the object's "easeInDone" variable to true */
		if (Math.abs(window[objectName + "xSpeed"]) >= Math.abs(xTargetSpeed) && 
		    Math.abs(window[objectName + "ySpeed"]) >= Math.abs(yTargetSpeed)) 
			{
				window[objectName + "xSpeed"] = xTargetSpeed;
				window[objectName + "ySpeed"] = yTargetSpeed;
				window[objectName + "easeInDone"] = true;
			}
	
	/* Two boolean values to determine whether or not to ease out */
		var xEaseOut = false;
		var yEaseOut = false;
	
	/* If easing out is on, and the object has finished easing in, and has passed the ease out coordinates, reduce speed by "easeOut" */	
		if (easeOut > 0 && window[objectName + "easeInDone"] == true)
			{
			/* Based on the direction of movement, determine if the object has passed the ease out coordinates */
				(xRatio >= 0 && window[objectName + "currentX"] >= easeOutXStart) ? xEaseOut = true : null;
				(xRatio < 0 && window[objectName + "currentX"] <= easeOutXStart) ? xEaseOut = true : null;
				(yRatio >= 0 && window[objectName + "currentY"] >= easeOutYStart) ? yEaseOut = true : null;
				(yRatio < 0 && window[objectName + "currentY"] <= easeOutYStart) ? yEaseOut = true : null;
			
			/* If both xEaseOut and yEaseOut are true, reduce speed, but don't let it start moving backwards */
				if (xEaseOut == true && yEaseOut == true)
					{
						window[objectName + "xSpeed"] = (Math.abs(window[objectName + "xSpeed"] - xRatio * easeOut) > Math.abs(xRatio)) ?
						                                 window[objectName + "xSpeed"] - xRatio * easeOut : xRatio;
						window[objectName + "ySpeed"] = (Math.abs(window[objectName + "ySpeed"] - yRatio * easeOut) > Math.abs(yRatio)) ?
						                                 window[objectName + "ySpeed"] - yRatio * easeOut : yRatio;
					}
			}
		
	/* A local variable to tell the function whether to clear the "motionTweenInterval" or not */
		var stopTheTween = false;
		
	/* If the object has reached or passed it's destination, set the x & y values to match target values */
		(xRatio >= 0 && window[objectName + "currentX"] >= targetX) ? window[objectName + "currentX"] = targetX : null; 
		(xRatio < 0 && window[objectName + "currentX"] <= targetX) ? window[objectName + "currentX"] = targetX : null; 
		(yRatio >= 0 && window[objectName + "currentY"] >= targetY) ? window[objectName + "currentY"] = targetY : null; 
		(yRatio < 0 && window[objectName + "currentY"] <= targetY) ? window[objectName + "currentY"] = targetY : null; 
	
	/* If the target object has reached its destination, set the "stopTheTween" variable to true */
		(window[objectName + "currentX"] == targetX && window[objectName + "currentY"] == targetY) ?
			stopTheTween = true : null;

	/* Set the position of the target object's "Left" and "Top" to match the "currentX" and "currentY" variables
	and clear the interval if the target has reached its destination */
		window[objectName].style.left = window[objectName + "currentX"] + "px";
		window[objectName].style.top = window[objectName + "currentY"] + "px";
		if (stopTheTween == true)
			{
				window[objectName + "IsDoneMoving"] = true;
				clearInterval(window[objectName + "MotionTweenInterval"]);
			}
	}
