//------------------------------------------------------------------------
// Name: LW_Debug_Debugger
// Desc: Works with the PHP LW_Debug_Debugger class to display debugging
//       information.
//------------------------------------------------------------------------
LW_Debug_Debugger =
{
  
	debug_items:         Array(),  // The debug items.
	queries:             Array(),  // The queries array.
	database_resources:  Array(),  // The database resources array.
	resources:           Array(),  // The resources array.
	execution_time:      "",       // The execution time of the page.
	
	
	//----------------------------------------------------------------------
	// Name: addSystemSetting()
	// Desc: Adds a setting.
	//----------------------------------------------------------------------
	addSystemSetting: function( category, setting, value )
	{

		// Add the setting.
		LW_Debug_Debugger.system_settings[category].push( { setting: setting,
		                                                    value:   value } );

	},
	

	//----------------------------------------------------------------------
	// Name: addItem()
	// Desc: Adds a debug item.
	//----------------------------------------------------------------------
	addItem: function( message, error_code, file, line, php_class, php_function, type )
	{

		// Add the debug item.
		LW_Debug_Debugger.debug_items.push( { message:       message,
		                                      error_code:    error_code,
		                                      file:          file,
		                                      line:          line,
		                                      php_class:     php_class,
		                                      php_function:  php_function,
		                                      type:          type,
		                                      args:          Array() } );

	},


	//----------------------------------------------------------------------
	// Name: addFunctionArg()
	// Desc: Adds a function's argument.
	//----------------------------------------------------------------------
	addFunctionArg: function( id, arg )
	{

		// Get the debug item.
		var debug_item = LW_Debug_Debugger.debug_items[id];

		// Add the function argument.
		debug_item.args.push( arg );

	},


	//----------------------------------------------------------------------
	// Name: addQuery()
	// Desc: Adds a query.
	//----------------------------------------------------------------------
	addQuery: function( query, file, line )
	{

		// Add the debug item.
		LW_Debug_Debugger.queries.push( { query:  query,
																	    file:   file,
																	    line:   line } );

	},


	//----------------------------------------------------------------------
	// Name: addDBResource()
	// Desc: Adds a database resource.
	//----------------------------------------------------------------------
	addDBResource: function( host, name )
	{

		// Add the database resource.
		LW_Debug_Debugger.database_resources.push( { host:  host,
																	               name:  name } );

	},


	//----------------------------------------------------------------------
	// Name: addResource()
	// Desc: Adds a resource.
	//----------------------------------------------------------------------
	addResource: function( class_name, id )
	{

		// Add the resource.
		LW_Debug_Debugger.resources.push( { class_name: class_name, id: id } );

	},


	//----------------------------------------------------------------------
	// Name: showDebugInfo()
	// Desc: Pops up a window with the debug information.
	//----------------------------------------------------------------------
	showDebugInfo: function()
	{

		var window_html         = "";
		var debug_window        = null;
		var last_resource_class = "";

		// Start getting the debug HTML.
		window_html += "<head>";

		window_html += "<title>Debug Information</title>";

		window_html += "<style>";
		window_html += "html { color: #000;	text-align: justify; background-color: #FFF; }";
		window_html += "body { margin: 0; padding: 0; color: #000; font-family: Verdana, Helvetica, sans-serif;	font-size: 11px; }";
		window_html += "h1, h2, h3, h4, h5, h6 { font-family: Trebuchet MS, verdana, sans-serif; margin: 0px; }";
		window_html += "h1 { font-size: 17px; color: #3870A9; border-bottom: 1px solid #CCC; padding-left: 10px; margin-top: 15px; }";
		window_html += "h2 { font-size: 14px; color: #3870A9; border-bottom: 1px solid #CCC; text-align: right; margin-top: 15px; }";
		window_html += ".item { background-color: #EEE; margin: 0px 10px 10px 10px; padding: 5px; }";
		window_html += "table { border: 1px solid #CCC; border-top: 0px; width: 100%; font-size: 11px; margin-bottom: 20px; }";
		window_html += "th { padding: 3px 0px 3px 0px; border-bottom: 1px solid #CCC; background-color: #EEE; width: 50%; }";
		window_html += "td { padding: 3px 15px 3px 5px; border-right: 1px solid #CCC; border-bottom: 1px solid #EEE; }";
		window_html += "</style>";

		window_html += "</head>";

		////////////////////////////////////////
		// Execution Information
		window_html += "<h1>Execution Information</h1>";

		window_html += "<div class='item'>";
		window_html += "<strong>Page Execution Time: </strong> <br /> <em>" + LW_Debug_Debugger.execution_time + " Seconds</em> <br /><br />";
		window_html += "<strong>Number of Debug Items: </strong> <em>" + LW_Debug_Debugger.debug_items.length + "</em> <br />";
		window_html += "<strong>Number of Queries: </strong> <em>" + LW_Debug_Debugger.queries.length + "</em> <br />";
		window_html += "<strong>Number of Resources: </strong> <em>" + LW_Debug_Debugger.resources.length + "</em> <br />";
		window_html += "</div>";

		////////////////////////////////////////
		// Debug items.
		window_html += "<h1>Debug Information</h1>";

		// Loop through each debug item.
		formatted_debug_items = LW_Debug_Debugger.formatDebugItems();

		for ( var i = 0; i < formatted_debug_items.length; i++ )
		{

			// Get the debug item.
			var debug_item = formatted_debug_items[i];

			window_html += "<h2>Item #" + (i + 1) + "</h2>";
			window_html += "<div class='item'>";
			window_html += debug_item;
			window_html += "</div>";

		}  // Next debug item.

		////////////////////////////////////////
		// Database queries.
		window_html += "<h1>Database Queries (" + LW_Debug_Debugger.queries.length + ")</h1>";

		// Loop through each query.
		for ( var i = 0; i < LW_Debug_Debugger.queries.length; i++ )
		{

			// Get the query.
			var query = LW_Debug_Debugger.queries[i];

			// Show the query.
			window_html += "<h2>Query #" + (i + 1) + "</h2>";
			window_html += "<div class='item'>";
			window_html += '"' + query.query + '" <br />';
			window_html += "<strong>File:</strong> <em>" + query.file + "</em> <br />";
			window_html += "<strong>Line:</strong> <em>" + query.line + "</em> <br />";
			window_html += "</div>";

		}  // Next query.

		////////////////////////////////////////
		// Resource information.
		window_html += "<h1>Resource Information (" + LW_Debug_Debugger.resources.length + ")</h1>";

		// Loop through each DB resource.
		for ( var i = 0; i < LW_Debug_Debugger.database_resources.length; i++ )
		{

			// Get the DB resource.
			var resource = LW_Debug_Debugger.database_resources[i];

			// Show the DB resource.
			window_html += "<h2>DB #" + (i + 1) + "</h2>";
			window_html += "<div class='item'>";
			window_html += "<strong>DB Host:</strong> <em>" + resource.host + "</em> <br />";
			window_html += "<strong>DB Name:</strong> <em>" + resource.name + "</em> <br />";
			window_html += "</div>";

		}  // Next DB resource.

		// Loop through each resource.
		for ( var i = 0, n = 0; i < LW_Debug_Debugger.resources.length; i++, n++ )
		{

			// Get the resource.
			var resource = LW_Debug_Debugger.resources[i];

			// If we haven't encountered this resource yet.
			if ( last_resource_class != resource.class_name )
			{

				// Reset n.
				n = 0;

				// Store this new resource's class name.
				last_resource_class = resource.class_name;

			}

			// Show the resource.
			window_html += "<h2>" + resource.class_name + " #" + (n + 1) + "</h2>";
			window_html += "<div class='item'>";
			window_html += "<strong>ID:</strong> <em>" + resource.id + "</em> <br />";
			window_html += "</div>";

		}  // Next resource.

		// Open a window for the output.
		debug_window = window.open( "", "DebugWindow", "menubar=yes,scrollbars=yes,status=yes,width=500,height=500" );

		// Show the output.
		debug_window.document.open();
		debug_window.document.write( window_html );
		debug_window.document.close();

	},


	//----------------------------------------------------------------------
	// Name: showDebugInfo()
	// Desc: Loops through each debug item and formats it ready for printing.
	//----------------------------------------------------------------------
	formatDebugItems: function()
	{

		var formatted_items = Array();

		// Loop through each debug item.
		for ( var i = 0; i < LW_Debug_Debugger.debug_items.length; i++ )
		{

			var debug_item = LW_Debug_Debugger.debug_items[i];

			formatted_items[i] = "";

			// Error code.
			if ( debug_item.error_code != "" )
			  formatted_items[i] += "<strong>[ " + debug_item.error_code + " ]</strong> - ";

			// Message.
			if ( debug_item.message != "" )
			  formatted_items[i] += '"<em>' + debug_item.message + '</em>" <br />';

			// File.
			if ( debug_item.file != "" )
			  formatted_items[i] += "<strong>File:</strong> <em>" + debug_item.file + "</em> <br />";

			// Line.
			if ( debug_item.line != "" )
			  formatted_items[i] += "<strong>Line:</strong> <em>" + debug_item.line + "</em> <br />";

			// Class.
			if ( debug_item.php_class != "" )
			  formatted_items[i] += "<strong>Class:</strong> <em>" + debug_item.php_class + "</em> <br />";

			// Function.
			if ( debug_item.php_function != "" )
			  formatted_items[i] += "<strong>Function:</strong> <em>" + debug_item.php_function + "</em> <br />";

			// Type.
			if ( debug_item.php_function != "" )
			{

				// Type of function?
				if ( debug_item.type == "->" )
				{
					formatted_items[i] += "<strong>Type:</strong> <em>Class Function</em> <br />";
				}
				else if ( debug_item.type == "::" )
				{
					formatted_items[i] += "<strong>Type:</strong> <em>Static Function</em> <br />";
				}
				else
				{
					formatted_items[i] += "<strong>Type:</strong> <em>Normal Function</em> <br />";
				}

			}  // End type.

			// Prototype.
			if ( debug_item.php_function != "" )
			{

				formatted_items[i] += "<strong>Prototype:</strong> <em>";

				// Any class?
				if ( debug_item.php_class != "" )
				  formatted_items[i] += debug_item.php_class;

				// Any type?
				if ( debug_item.type != "" )
				  formatted_items[i] += debug_item.type;

				// Put the function name.
				formatted_items[i] += debug_item.php_function + "( ";

				// Loop through the args.
				for ( var n = 0; n < debug_item.args.length; n++ )
				{

					formatted_items[i] += debug_item.args[n];

					if ( n != debug_item.args.length - 1 )
					  formatted_items[i] += ", ";

				}  // Next arg.

			  // End the function.
				formatted_items[i] += " )";

				formatted_items[i] += "</em> <br />";

			}  // End prototype.

			formatted_items[i] += "<br />";

		}  // Next debug item.

		// Return the formatted items.
		return formatted_items;

	}

};

//------------------------------------------------------------------------
// Package: Structures
// The various structures used by the system.
// 
// Topic: Dependencies
// - <DOM Library>
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Class: LW_Structure_Color
// Handles a single color.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Structure_Color()
// Class constructor.
//
// Parameters:
//     RGB - A six character string of Red, Green and Blue values, eg: "FF2345".
//     
//     OR
//
//     R - Red value, 0 - 255.
//     G - Green value, 0 - 255.
//     B - Blue value, 0 - 255.
//------------------------------------------------------------------------
function LW_Structure_Color()
{

	// What type of argument was passed in?
	if ( arguments.length == 1 && (typeof arguments[0] == "string" || arguments[0] instanceof String) )
	{

		this.R = parseInt( arguments[0].substring( 0, 2 ), 16 );
		this.G = parseInt( arguments[0].substring( 2, 4 ), 16 );
		this.B = parseInt( arguments[0].substring( 4, 6 ), 16 );

	}  // End if hex string.
	else if ( arguments.length == 3 )
	{

		this.R = arguments[0];
		this.G = arguments[1];
		this.B = arguments[2];

	}  // End if numbers passed in.
	else
	{

		this.R = null;
		this.G = null;
		this.B = null;

	}  // End if null passed in.

}


//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Function: toHexString()
// Returns the color as a string of hexidecimal values.
//------------------------------------------------------------------------
LW_Structure_Color.prototype.toHexString = function()
{

	var R = (this.R < 16) ? "0" + this.R.toString( 16 ) : this.R.toString( 16 );
	var G = (this.G < 16) ? "0" + this.G.toString( 16 ) : this.G.toString( 16 );
	var B = (this.B < 16) ? "0" + this.B.toString( 16 ) : this.B.toString( 16 );

	return R + G + B;

}


//------------------------------------------------------------------------
// Class: LW_Structure_Dimensions
// Handles a single set of dimensions.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Structure_Dimensions()
// Class constructor.
//
// Parameters:
//     width - The width to store.
//     height - The height to store.
//
//     OR
//
//     element - A DOM element, in which case it will store the dimensions
//               of that element at the time this structure was created.
//------------------------------------------------------------------------
function LW_Structure_Dimensions()
{
	
	// What type of arguments passed in?
	if ( arguments.length == 2 )
	{

		// Store the passed in parameters.
		this.width   = arguments[0];
		this.height  = arguments[1];
		
	}  // End if a width and height.
	else if ( arguments.length == 1 )
	{
		
		var element = arguments[0];

		// Get the element's dimensions.
		this.width = LW_DOM_Library.getWidth( element );
		this.height = LW_DOM_Library.getHeight( element );
		
	}  // End if element passed in.

}


//------------------------------------------------------------------------
// Class: LW_Structure_Position
// Handles a single position. For positioning objects relative to its
// containing element.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Structure_Position()
// Class constructor.
//
// Parameters:
//     top - The value from the top of the containing element.
//     right - The value from the right of the containing element.
//     bottom - The value from the bottom of the containing element.
//     left - The value from the left of the containing element.
//------------------------------------------------------------------------
function LW_Structure_Position( top, right, bottom, left )
{

	// Store the passed in parameters.
	this.top     = top;
	this.right   = right;
	this.bottom  = bottom;
	this.left    = left;

}


//------------------------------------------------------------------------
// Class: LW_Structure_Point
// Handles a single point.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Structure_Point()
// Class constructor.
//
// Parameters:
//     X - The X value of the point.
//     Y - The Y value of the point.
//------------------------------------------------------------------------
function LW_Structure_Point( X, Y )
{

	// Store the passed in parameters.
	this.X = X;
	this.Y = Y;

}


//------------------------------------------------------------------------
// Class: LW_Structure_Region
// Handles a single region.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Structure_Region()
// Class constructor.
//
// Parameters:
//     min_point - The <LW_Structure_Point> of the top left corner.
//     max_point - The <LW_Structure_Point> of the bottom right corner.
//
//     OR
//
//     element - A DOM element, in which case the region will be the
//               containing region of the element.
//------------------------------------------------------------------------
function LW_Structure_Region()
{

	// What was passed in?
	if ( arguments.length == 2 )
	{

		// Store the passed in parameters.
	  this.min_point  = arguments[0];
	  this.max_point  = arguments[1];

	}  // End if points passed in.
	else if ( arguments.length == 1 )
	{

		var element = arguments[0];

		// Get the element's position for the region's min point.
		this.min_point = LW_DOM_Library.getXY( element );

		// Get the max point for the region.
		this.max_point = new LW_Structure_Point( (this.min_point.X + element.offsetWidth), (this.min_point.Y + element.offsetHeight) );

	}  // End if HTML element passed in.

}


//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Function: intersectRegion()
// Used to test if two <LW_Structure_Region> objects are intersecting
// each other.
//
// Parameters:
//     region - The <LW_Structure_Region> that you'd like to test for
//              intersection against this object.
//     in_test - (Optional) If this is set to true, the region passed in
//               must be fully contained by this object.
//     epsilon - (Optional) This is the allowable mistake that can happen
//               between the tests, eg: if this is 1, then if the region
//               is 1 pixel away from intersecting, this function will
//               still return true.
//------------------------------------------------------------------------
LW_Structure_Region.prototype.intersectRegion = function( region, in_test, epsilon )
{

	// Get the epsilon.
	epsilon = (epsilon) ? epsilon : 0;

	// Only do this if we are testing if it's completely contained.
	if ( in_test )
	{

	  var contained = true;

		// Is the region completely contained in this region?
		if ( region.min_point.X < (this.min_point.X + epsilon) || region.min_point.X > (this.max_point.X + epsilon) ) contained = false;
		else if ( region.min_point.Y < (this.min_point.Y + epsilon) || region.min_point.Y > (this.max_point.Y + epsilon) ) contained = false;
		else if ( region.max_point.X < (this.min_point.X + epsilon) || region.max_point.X > (this.max_point.X + epsilon) ) contained = false;
		else if ( region.max_point.Y < (this.min_point.Y + epsilon) || region.max_point.Y > (this.max_point.Y + epsilon) ) contained = false;

		// Return.
		return contained;

	}  // End if completely contained test.
	else
	{

		// Perform the intersection test.
		return ((this.min_point.X + epsilon) <= region.max_point.X) &&
						((this.min_point.Y + epsilon) <= region.max_point.Y) &&
						((this.max_point.X + epsilon) >= region.min_point.X) &&
						((this.max_point.Y + epsilon) >= region.min_point.Y);

	}  // End normal touching test.

}


//------------------------------------------------------------------------
// Function: containsPoint()
// Used to test if there is an <LW_Structure_Point> object within the
// bounds of this region.
//
// Parameters:
//     point - The <LW_Structure_Point> object.
//------------------------------------------------------------------------
LW_Structure_Region.prototype.containsPoint = function( point )
{

	var contained = true;

	// Is the point completely contained in this region?
	if ( this.min_point.X > point.X || this.max_point.X < point.X ) contained = false;
	if ( this.min_point.Y > point.Y || this.max_point.Y < point.Y ) contained = false;

	// Return.
	return contained;

}


// First, before we do anything, load the Yahoo! UI DOM library.
document.writeln("<script type='text/javascript' src='" + LW_PATH_TO_API + "/yahoo-ui/yahoo-min.js'><" + "/script>");
document.writeln("<script type='text/javascript' src='" + LW_PATH_TO_API + "/yahoo-ui/dom-min.js'><" + "/script>");


//------------------------------------------------------------------------
// Name: LW_DOM_Library
// Desc: Some helper functions to make working with the DOM easier.
//------------------------------------------------------------------------
LW_DOM_Library =
{

	//------------------------------------------------------------------------
	// Class Constants
	//------------------------------------------------------------------------
	CREATE_IFRAME:   0,
	CREATE_HTML:     1,
	CREATE_DOMNODE:  2,

	//----------------------------------------------------------------------
	// Name: noteToString()
	// Desc: Iterates through the node's children and retrieves
	//       all the node's text.
	//----------------------------------------------------------------------
	nodeToString: function( node )
	{

		var node_string = "";
		var suffix      = "";

		// Loop through each child node.
		for ( var i = 0; i < node.childNodes.length; i++ )
		{

			// Get the child node.
			child_node = node.childNodes[i];

			// Only store the text if it's not null.
			if ( child_node.data != undefined )
			  node_string += child_node.data;

			// If this node has a tag name, store the tags.
			if ( child_node.tagName != undefined )
			{
			   node_string += "<" + child_node.tagName + ">";
				 suffix += "</" + child_node.tagName + ">";
			}

			// If this node has child nodes, recurse.
			if ( child_node.childNodes.length != 0 )
			  node_string += LW_DOM_Library.nodeToString( child_node );

			// Add the suffix.
			node_string  = node_string + suffix;
			suffix       = "";

		}  // Next child node.

		// Return the collected string.
		return node_string;

	},


	//----------------------------------------------------------------------
	// Name: getViewportWidth()
	// Desc: Returns the viewport's width.
	//----------------------------------------------------------------------
	getViewportWidth: function()
	{
		
		return YAHOO.util.Dom.getViewportWidth();

	},


	//----------------------------------------------------------------------
  // Name: getViewportHeight()
  // Desc: Returns the viewport's height.
  //----------------------------------------------------------------------
	getViewportHeight: function()
	{

	  return YAHOO.util.Dom.getViewportHeight();

	},


	//----------------------------------------------------------------------
	// Name: getDocumentWidth()
	// Desc: Returns the document's width.
	//----------------------------------------------------------------------
	getDocumentWidth: function()
	{

		return YAHOO.util.Dom.getDocumentWidth();

	},


	//----------------------------------------------------------------------
	// Name: getDocumentHeight()
	// Desc: Returns the documents's height. 
	//----------------------------------------------------------------------
	getDocumentHeight: function()
	{

		return YAHOO.util.Dom.getDocumentHeight();

	},


	//----------------------------------------------------------------------
	// Name: getScrollXOffset()
	// Desc: Returns the scrollbar's X offset value.
	//----------------------------------------------------------------------
	getScrollXOffset: function()
	{

		return YAHOO.util.Dom.getDocumentScrollLeft();

	},


	//----------------------------------------------------------------------
	// Name: getScrollYOffset()
	// Desc: Returns the scrollbar's Y offset value.
	//----------------------------------------------------------------------
	getScrollYOffset: function()
	{

		return YAHOO.util.Dom.getDocumentScrollTop();

	},


	//----------------------------------------------------------------------
	// Name: getStyle()
	// Desc: Gets a property from the CSS style of the passed in element.
	//----------------------------------------------------------------------
	getStyle: function( element, property )
	{
		
		return YAHOO.util.Dom.getStyle( element, property );

	},


	//----------------------------------------------------------------------
	// Name: setStyle()
	// Desc: Sets a property from the CSS style of the passed in element, to
	//       the new value passed in.
	//----------------------------------------------------------------------
	setStyle: function( element, property, new_value )
	{

		YAHOO.util.Dom.setStyle( element, property, new_value );

	},


	//----------------------------------------------------------------------
	// Name: getWidth()
	// Desc: Returns the width of the passed in element.
	//----------------------------------------------------------------------
	getWidth: function( element )
	{

		return element.offsetWidth;

	},


	//----------------------------------------------------------------------
	// Name: getHeight()
	// Desc: Returns the height of the passed in element.
	//----------------------------------------------------------------------
	getHeight: function( element )
	{
		
	  	return element.offsetHeight;

	},


	//----------------------------------------------------------------------
	// Name: getDimensions()
	// Desc: Returns the dimensions of the passed in element.
	//----------------------------------------------------------------------
	getDimensions: function( element )
	{

		return LW_Structure_Dimensions( element.offsetWidth, element.offsetHeight );

	},


	//----------------------------------------------------------------------
	// Name: getX()
	// Desc: Returns the X value on the page of the passed in element.
	//----------------------------------------------------------------------
	getX: function( element )
	{

	  return LW_DOM_Library.getXY( element ).X;

	},


	//----------------------------------------------------------------------
	// Name: getY()
	// Desc: Returns the Y value on the page of the passed in element.
	//----------------------------------------------------------------------
	getY: function( element )
	{

	  return LW_DOM_Library.getXY( element ).Y;

	},


	//----------------------------------------------------------------------	
	// Name: getXY()
	// Desc: Returns the X and Y value on the page of the passed in
	//       element.
	//----------------------------------------------------------------------
	getXY: function( element )
	{

		// Get the positions.
    	pos = YAHOO.util.Dom.getXY( element );
    	
		// Return the position of the element.
		return new LW_Structure_Point( pos[0], pos[1] );

	},


	//----------------------------------------------------------------------
	// Name: setX()
	// Desc: Sets the X value on the page grid of the passed in element.
	//----------------------------------------------------------------------
	setX: function( element, X )
	{

		YAHOO.util.Dom.setX( element, X );

	},

	//----------------------------------------------------------------------
	// Name: setY()
	// Desc: Sets the Y value on the page grid of the passed in element.
	//----------------------------------------------------------------------
	setY: function( element, Y )
	{

		YAHOO.util.Dom.setY( element, Y );

	},


	//----------------------------------------------------------------------
	// Name: setXY()
	// Desc: Sets the X and Y value on the page grid of the passed in
	//       element.
	//----------------------------------------------------------------------
	setXY: function( element, point )
	{

		YAHOO.util.Dom.setXY( element, [ point.X, point.Y ] );

	},
	
	
	//----------------------------------------------------------------------
	// Name: getElementsByClassName()
	// Desc: Returns an array of elements with the class passed in.
	//----------------------------------------------------------------------
	getElementsByClassName: function( name, tag, root )
	{

		return YAHOO.util.Dom.getElementsByClassName( name, tag, root );

	},


	//----------------------------------------------------------------------
	// Name: createContainer()
	// Desc: Creates a container element in the document.
	//----------------------------------------------------------------------
	createContainer: function( create_type, creation_data, dimensions, position, align )
	{

		position = (position != null) ? position : new LW_Structure_Position( null, null, null, null );

		// Create a new div for the floating container.
		var container = document.createElement( "div" );

		// Specify its parameters.
		LW_DOM_Library.setStyle( container, "position", "absolute" );

		// Dimensions.
		if ( dimensions != null )
		{

			if ( dimensions.width  != null ) LW_DOM_Library.setStyle( container, "width", dimensions.width + "px" );
			if ( dimensions.height != null ) LW_DOM_Library.setStyle( container, "height", dimensions.height + "px" );

		}

		// Alignment.
		if ( align != null )
		{
			
			// Retrieve the window height and width.
			var client_height = LW_DOM_Library.getViewportHeight();
			var client_width  = LW_DOM_Library.getViewportWidth();
			
			// Get the element's dimensions.
			// We get it here in case the dimensions are set with CSS.
			var elem_dimensions = new LW_Structure_Dimensions( container );

			// Horizontal align.
			if ( align.halign == "left" )
				position.left = (position.left != null) ? position.left : 0;

			if ( align.halign == "center" )
				position.left = (position.left != null) ? (client_width * 0.5 - elem_dimensions.width * 0.5 + position.left) : (client_width * 0.5 - elem_dimensions.width * 0.5);
			
			if ( align.halign == "right" )
				position.left = (position.left != null) ? (client_width - elem_dimensions.width + position.left) : (client_width - elem_dimensions.width);

			// Vertical align.
			if ( align.valign == "top" )
				position.top = (position.top != null) ? position.top : 0;

			if ( align.valign == "center" )
				position.top = (position.top != null) ? (client_height * 0.5 - elem_dimensions.height * 0.5 + position.top) : (client_height * 0.5 - elem_dimensions.height * 0.5);

			if ( align.valign == "bottom" )
				position.top = (position.top != null) ? (client_height - elem_dimensions.height + position.top) : (client_height - elem_dimensions.height);

		}
		
		// Positions.
		if ( position.top    != null ) LW_DOM_Library.setStyle( container, "top", position.top + "px" );
		if ( position.right  != null ) LW_DOM_Library.setStyle( container, "right", position.right + "px" );
		if ( position.bottom != null ) LW_DOM_Library.setStyle( container, "bottom", position.bottom + "px" );
		if ( position.left   != null ) LW_DOM_Library.setStyle( container, "left", position.left + "px" );
		
		// Now add the content.
		if ( create_type == LW_DOM_Library.CREATE_IFRAME )
		{

			// Create the iframe.
			container.innerHTML = "<iframe width='" + dimensions.width + "' height='" + dimensions.height + "' frameborder='0' src='" + creation_data + "'></iframe>";

		}  // End if iframe passed.
		else if ( create_type == LW_DOM_Library.CREATE_HTML )
		{

			// Add the HTML to the container.
			container.innerHTML = creation_data;

		}  // End if HTML passed.
		else if ( create_type == LW_DOM_Library.CREATE_DOMNODE )
		{

			// Append the DOM node to the container.
		  container.appendChild( creation_data );

		}  // End if DOM node passed.

		// Append the div to the document.
		document.body.appendChild( container );

		// Return the new container element.
		return container;

	}

};


//------------------------------------------------------------------------
// Name: LW_Form
// Desc: A helper class to help with the PHP Form class.
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Some Global Form Variables
//------------------------------------------------------------------------
LW_Form.forms = Object();


//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Name: LW_Form
// Desc: Class constructor.
//------------------------------------------------------------------------
function LW_Form( form_id, dependants )
{

	// Add this object to a global form array.
	LW_Form.forms[form_id] = this;

	this.form_id     = form_id;    // The form ID.
	this.dependants  = dependants; // The dependants.

	// Loop through each dependant group.
	for ( var element_id in this.dependants )
	{

		// Get the element.
		var element = document.getElementById( element_id );

		// Add the events.
		if ( element.type == "radio" )
		{

			// What is the default value?
			if ( !element.checked )
			{

				// Call the toggleDependants function on these dependants.
				this.toggleDependants( element_id, false );

			}  // End if not checked.

			// Get all the elements with the same name as this.
			var elements = document.getElementsByName( element.name );

			// Loop through each element found.
			for ( var i = 0; i < elements.length; i++ )
			{

				// Add the event.
				if ( elements[i].id != element_id )
					LW_Events_Handler.addEvent( elements[i], "onchange", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "', false );" ) );
				else
					LW_Events_Handler.addEvent( elements[i], "onchange", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "', true );" ) );

			}  // Next element found.

		}  // End if radio button.
		else if ( element.type == "checkbox" )
		{

			// Call the toggleDependants function.
			this.toggleDependants( element_id );

			// Add the event.
			LW_Events_Handler.addEvent( element, "onclick", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "' );" ) );

		}  // End if checkbox.
		else if ( element.type == "select-one" )
		{

			// Call the toggleDependants function.
			this.toggleDependants( element_id );

			// Add the event.
			LW_Events_Handler.addEvent( element, "onchange", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "' );" ) );

		}  // End if select-one.
		else if ( element.type == "select-multiple" )
		{

			// Call the toggleDependants function.
			this.toggleDependants( element_id );

			// Add the event.
			LW_Events_Handler.addEvent( element, "onchange", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "' );" ) );

		}  // End if select-multiple.
		else if ( element.type == "text" || element.type == "password" || element.type == "textarea" || element.type == "file" )
		{

			// Call the toggleDependants function.
			this.toggleDependants( element_id );

			// Add the event.
			LW_Events_Handler.addEvent( element, "onkeyup", new Function( "LW_Form.forms['" + this.form_id + "'].toggleDependants( '" + element_id + "' );" ) );

		}  // End if text.

	}  // Next dependant group.

}


//------------------------------------------------------------------------
// Name: toggleDependants
// Desc: Toggles the dependants on or off depending upon whether their
//       element is on or off.
//------------------------------------------------------------------------
LW_Form.prototype.toggleDependants = function( element_id, on )
{

	// Get the element.
	var element = document.getElementById( element_id );

	// What type of element.
	if ( element.type == "checkbox" )
	{

		if ( element.checked )
			on = true;
		else
			on = false;

	}  // End if checkbox.
	else if ( element.type == "select-one" )
	{

		if ( element.value == this.dependants[element_id].value[0] )
			on = true;
		else
			on = false;

	}  // End if select-one.
	else if ( element.type == "select-multiple" )
	{

		// Set on to be initially true. We will find if it should
		// really be true later on.
		var on = true;

		// Loop through each value.
		for ( var i = 0; i < this.dependants[element_id].value.length; i++ )
		{

			// Loop through each option.
			for ( var n = 0; n < element.options.length; n++ )
			{

				if ( !element.options[n].selected && element.options[n].value == this.dependants[element_id].value[i] )
					on = false;

			}  // Next option.

		}  // Next value.

	}  // End if select-one.
	else if ( element.type == "text" || element.type == "password" || element.type == "textarea" || element.type == "file" )
	{

		if ( element.value != '' )
			on = true;
		else
			on = false;

	}  // End if other.

	// Are we disabling or enabling?
	if ( on )
	{

		// Loop through each dependant.
		for ( var i = 0; i < this.dependants[element_id].dependants.length; i++ )
		{

			// Get the dependant.
			dependant = this.dependants[element_id].dependants[i];

			// Get the dependant's element.
			var dependant_element = document.getElementById( dependant );

			// Make sure nothing else is controlling this element.
			var free = this.isDependantFree( dependant );

			// Enable the element.
			if ( free ) dependant_element.disabled = false;

		}  // Next dependant.

	}  // End if enabling.
	else if ( !on )
	{

		// Loop through each dependant.
		for ( var i = 0; i < this.dependants[element_id].dependants.length; i++ )
		{

			// Get the dependant.
			dependant = this.dependants[element_id].dependants[i];

			// Get the dependant's element.
			var dependant_element = document.getElementById( dependant );

			// Disable the element.
			dependant_element.disabled = true;

		}  // Next dependant.

	}  // End if disabling.

}


//------------------------------------------------------------------------
// Name: isDependantFree
// Desc: Loops through every dependant being manage by the system and
//       makes sure this dependant is completely free.
//------------------------------------------------------------------------
LW_Form.prototype.isDependantFree = function( dependant )
{

	var ret = true;

	// Loop through each dependant group.
	for ( var element_id in this.dependants )
	{

		// Get the dependant group.
		var dependant_array = this.dependants[element_id].dependants;

		// Loop through each dependant.
		for ( var i = 0; i < dependant_array.length; i++ )
		{

			// If the dependant was found.
			if ( dependant == dependant_array[i] )
			{

				// Get the main dependant element.
				var element = document.getElementById( element_id );

				// If the element's main dependant is not checked, return false.
				if ( element.type == "checkbox" )
				{

					if ( !element.checked )
						ret = false;

				}  // End if checkbox.
				else if ( element.type == "radio" )
				{

					if ( !element.checked )
						ret = false;

				}  // End if radio.
				else if ( element.type == "select-one" )
				{

					if ( element.value != this.dependants[element_id].value )
						ret = false;

				}  // End if select-one.
				else if ( element.type == "text" || element.type == "password" || element.type == "textarea" || element.type == "file" )
				{

					if ( element.value == '' )
						ret = false;

				}  // End if other.

			}  // End if found.

		}  // Next dependant.

	}  // Next dependant group.

	return ret;

}


//------------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Name: submitForm
// Desc: You pass it a form DOM element and it submits the form, calling
//       the form's obsubmit event.
//------------------------------------------------------------------------
LW_Form.submitForm = function( form )
{

	// Call the onsubmit event of the form.
	form.onsubmit();

}


//------------------------------------------------------------------------
// Name: LW_Form_Validator
// Desc: Exploses methods to validate the input parameters passed in to a
//       form.
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// Some Global Form_Validator Variables
//------------------------------------------------------------------------
LW_Form_Validator.validators = Object();


//------------------------------------------------------------------------
// Name: Form_Validator
// Desc: Class constructor.
//------------------------------------------------------------------------
function LW_Form_Validator( form, options_object )
{

	// Add this object to a global validator array.
	LW_Form_Validator.validators[form.id] = this;

	this.form                  = form;
	this.input_elements        = new Array();
	this.groups                = new Array();

	// Store the parameters.
	this.submit_button         = options_object.submit_button;
	this.submit_form           = (options_object.submit_form == null) ? false : true;
	this.redirect_url          = options_object.redirect_url;
	this.modified_request_url  = "";
	this.errors                = new Array();

	this.processing            = false;

	// Add on onsubmit event for the form.
	LW_Events_Handler.addEvent( this.form, "onsubmit", new Function( "return LW_Form_Validator.validators['" + this.form.id + "'].validateForm();" ) );

}


//----------------------------------------------------------------------
// Name: validateForm()
// Desc: Start the validation.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.validateForm = function()
{

	var errors = false;

	// Are we processing?
	if ( this.processing == true )
		return false;
	else
		this.processing = true;

	// Disable the submit button.
	if ( this.submit_button != null ) this.submit_button.disabled = true;

	// First make sure the form is clean.
	this.cleanupForm();

	// Call the form's onprevalidate function.
	if ( this.form['onprevalidate'] != null )
		this.form['onprevalidate']();
	/*
	// Were there any errors?
	if ( errors == true )
	{

		this.postError( null, "There were errors while processing the form. Please fix them and try submitting the form again." );

		// Set processing to false.
		this.processing = false;

		// Enable the submit button.
		if ( this.submit_button != null ) this.submit_button.disabled = false;

		// Return. We don't want to process any more.
		return false;

	}

	// If there is a request URL, send the request.
	if ( this.request_url != null )
	{

	  var query_string = this.getQueryString();

		// Send the request.
		LW_RequestManager.makeRequest( this.modified_request_url, new Function( "response", "LW_Form_Validator.validators['" + this.form.id + "'].processResponse( response );" ), query_string );

		// Return. We will continue processing in the processResponse() function.
		return false;

	}
	*/
	// Finish the validation.
	return this.finishValidation();

}


//----------------------------------------------------------------------
// Name: processResponse()
// Desc: Processes the response from the XHR request.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.processResponse = function( response )
{

	var response = response.responseXML;

	// Hide the message container, if there is one.
	if ( this.message_container != null )
		LW_DOM_Library.setStyle( this.message_container, "visibility", "hidden" );

	// Get the errors.
	var errors = response.getElementsByTagName( "error" );

	// Is there any errors?
	if ( errors.length != 0 )
	{

		// Loop through each error.
		for ( var i = 0; i < errors.length; i++ )
		{

			// Get the error details.
			var id = errors[i].getElementsByTagName( "id" );

			if ( id.length == 0 )
				id = null;
			else
				id = id[0].firstChild.data;

			var message = errors[i].getElementsByTagName( "message" )[0].firstChild.data;

			// Post the error.
			this.postError( id, message );

		}  // Next error.

		// Should we alert the errors?
		if ( this.alert_errors )
		{

		  // Show the first error as an alert.
		  alert( this.errors[0] );

		  // Empty out the errors array.
		  this.errors.length = 0;

		}  // End if alerting errors.

	}  // End if errors.
	else
	{

		// Finish validation.
		LW_Form_Validator.validators[this.form.id].finishValidation();

		// Return.
		return;

	}  // End if no errors.

	// If there was errors, show the generic error message.
	if ( errors.length > 0 && !this.alert_errors ) this.postError( null, "There were errors while processing the form. Please fix them and try submitting the form again." );

	// Set processing to false.
	this.processing = false;

	// Enable the submit button.
	if ( this.submit_button != null ) this.submit_button.disabled = false;

}


//----------------------------------------------------------------------
// Name: finishValidation()
// Desc: Finishes the validation.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.finishValidation = function()
{
	
	// Set processing to false.
	this.processing = false;

	// Enable the submit button.
	if ( this.submit_button != null ) this.submit_button.disabled = false;

	// Check for a redirect URL and if there is one redirect them.
//	if ( this.redirect_url != null )
	//	window.location = this.redirect_url;
	
	// If the submit form flag is set, submit the form.
	if ( this.submit_form )
		return true;
	else
		return false;

}


//----------------------------------------------------------------------
// Name: postError()
// Desc: Posts an error to the form with information about what went
//       wrong and why it went wrong.
// Note: If null is passed in for element_id, the error will be placed
//       at the end of the form.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.postError = function( element_id, error )
{

	// Create the error node.
	var error_node = document.createElement( "p" );
	error_node.className = "error";

	// Stick the text into the error node.
	error_node.innerHTML = error;

	// What type of placement?
	if ( element_id == null )
	{

		// Do we have a submit button?
		if ( this.submit_button != null )
		{

			this.submit_button.parentNode.parentNode.insertBefore( error_node, this.submit_button.parentNode.parentNode.firstChild );

		}  // End if submit button.
		else
		{

			document.getElementById( this.form.id ).appendChild( error_node );

		}  // End if no submit button.

	}  // End if general error message.
	else
	{

		var html_element = document.getElementById( element_id );

		// Group or normal?
		if ( html_element.parentNode.parentNode.className == "group" )
		{

			// Insert the error node before the input element.
			html_element.parentNode.parentNode.insertBefore( error_node, html_element.parentNode.parentNode.firstChild );

		}  // End if group.
		else
		{

			// Insert the error node before the input element.
			html_element.parentNode.insertBefore( error_node, html_element.parentNode.firstChild );

		}  // End if normal.

	}  // End if normal/group error message.

}


//----------------------------------------------------------------------
// Name: cleanupForm()
// Desc: Cleans up the form to make it ready for form validation.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.cleanupForm = function()
{

	// Get all the forms error's.
	var errors = this.form.getElementsByTagName( "p" );

	// Loop through each error.
	// We get the length before hand, because we take elements away from the
	// array in the loop.
	for ( var i = 0, length = errors.length, index = 0; i < length; i++ )
	{

		// Get the element. We retrieve the 0th element because we remove
		// the child below, and the next one will fall in this place.
		var error_element = errors[index];

		// Is this an error element?
		if ( error_element.getAttribute( "class" ) == "error" )
			error_element.parentNode.removeChild( error_element );  // Remove the element.
		else
			index++; // Increment the index if we have skipped an element.


	}  // Next error node.

}


//----------------------------------------------------------------------
// Name: getQueryString()
// Desc: Concatenates all the managed input elements in to a query
//       string suitable for appending to a URL.
//----------------------------------------------------------------------
LW_Form_Validator.prototype.getQueryString = function()
{

	var values = Array();

	// Loop through each input element in the form.
	for ( var i = 0; i < this.form.elements.length; i++ )
	{

		var element = this.form.elements[i];

		// What type of element?
		switch ( element.type )
		{

		// Simple elements.
	  case 'text':
		case 'password':
		case 'file':
		case 'textarea':
		case 'hidden':
		case 'select-one':

		  values.push( (element.name + "=" + encodeURIComponent( element.value )) );
			break;

		// Checkboxes and radio buttons.
		case 'checkbox':
		case 'radio':

		  // Only add if checked.
			if ( element.checked )
			  values.push( (element.name + "=" + encodeURIComponent( element.value )) );

			break;

		// Select multiples.
		case 'select-multiple':

		  // Loop through each option.
			for ( var n = 0; n < element.options.length; n++ )
			{

				// Only add if option is selected.
				if ( element.options[n].selected )
				  values.push( (element.name + "=" + encodeURIComponent( element.options[n].value )) );

			}  // Next option.

			break;

		}  // End what type of elements.

	}  // Next input element.

	// Put the values together into a string.
	var query_string = values.join( "&" );

	// Get the pieces of the request URL.
	var pieces = this.request_url.match( /(\S*)\?(\S*)/ );

	// If the request_url does not have a ? in it, get rid of the query values from
	// the request URL, and add it to the query string.
	if ( pieces != null )
	{

	  this.modified_request_url = pieces[1];
		query_string              = pieces[2] + "&" + query_string;

	}
	else
	{

		this.modified_request_url = this.request_url;

	}

	// Return the query string.
	return query_string;

}


//------------------------------------------------------------------------
// Package: Animation
// For animating elements in the DOM in various ways.
//
// Topic: Dependencies
// - <Events Handler>
// - <Structures>
// - <DOM Library>
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Class: LW_Animation_Controller
// Stores the animations parameters.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Animation_Controller()
// Class constructor. You don't need to instantiate this as it is used by
// the system.
//------------------------------------------------------------------------
function LW_Animation_Controller()
{

	// Store the default values.
	this.move              = { to:    new LW_Structure_Point(),
	                           by:    new LW_Structure_Point(),
							   ease:  LW_Animation.EASE_NONE };

	this.width             = { to:    null,
	                           by:    null,
							   ease:  LW_Animation.EASE_NONE };

	this.height            = { to:    null,
	                           by:    null,
							   ease:  LW_Animation.EASE_NONE };

	this.opacity           = { to:    null,
	                           by:    null,
							   ease:  LW_Animation.EASE_NONE };

	this.background_color  = { to:    new LW_Structure_Color(),
	                           by:    new LW_Structure_Color() };

	this.border_color      = { to:    new LW_Structure_Color(),
	                           by:    new LW_Structure_Color() };

	this.text_color        = { to:    new LW_Structure_Color(),
	                           by:    new LW_Structure_Color() };

	this.delay             = 0;

}


//------------------------------------------------------------------------
// Class: LW_Animation
// Holds a single animation for an element and the necessary methods to
// handle it.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Class Constants
//------------------------------------------------------------------------
LW_Animation.EASE_NONE          = 0;
LW_Animation.EASE_IN            = 1;
LW_Animation.EASE_OUT           = 2;
LW_Animation.EASE_BOTH          = 3;
LW_Animation.STRONG_EASE_IN     = 4;
LW_Animation.STRONG_EASE_OUT    = 5;
LW_Animation.STRONG_EASE_BOTH   = 6;
LW_Animation.BACK_EASE_IN       = 7;
LW_Animation.BACK_EASE_OUT      = 8;
LW_Animation.BACK_EASE_BOTH     = 9;
LW_Animation.BOUNCE_EASE_IN     = 10;
LW_Animation.BOUNCE_EASE_OUT    = 11;
LW_Animation.BOUNCE_EASE_BOTH   = 12;
LW_Animation.ELASTIC_EASE_IN    = 13;
LW_Animation.ELASTIC_EASE_OUT   = 14;
LW_Animation.ELASTIC_EASE_BOTH  = 15;


//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Animation()
// Class constructor.
//
// Parameters:
//     element - The DOM element that you'd like to animate.
//     run_time - The length that you'd like the animation to run.
//------------------------------------------------------------------------
function LW_Animation( element, run_time )
{

	// Store the values.
	this.element               = element;
	this.element_properties    = Object();
	this.run_time              = run_time;
	this.controller            = new LW_Animation_Controller();

	this.onStart               = null;
	this.onInterval            = null;
	this.onAdvance             = null;
	this.onEventFrame          = null;
	this.onStop                = null;
	this.onFinish              = null;

	// These values are used by the LW_Animation system internally.
	this.status                = false;
	this.event_frames          = new Array();

	this.start_time            = null;
	this.current_time          = null;

	this.begin_width           = null;
	this.begin_height          = null;
	this.begin_pos             = null;
	this.begin_back_color      = null;
	this.begin_border_color    = null;
	this.begin_text_color      = null;
	this.begin_opacity         = null;

	this.offset_width          = null;
	this.offset_height         = null;
	this.offset_pos            = new LW_Structure_Point();
	this.offset_back_color     = new LW_Structure_Color();
	this.offset_border_color   = new LW_Structure_Color();
	this.offset_text_color     = new LW_Structure_Color();
	this.offset_opacity        = null;

	this.desired_width         = null;
	this.desired_height        = null;
	this.desired_pos           = new LW_Structure_Point();
	this.desired_back_color    = null;
	this.desired_border_color  = null;
	this.desired_text_color    = null;
	this.desired_opacity       = null;

}


//------------------------------------------------------------------------
// Function: addEventFrame()
// Adds an event frame to the animation.
//
// Parameters:
//      time_offset - The offset from the beginning of the animation that
//                    you'd like this event to be fired.
//      event_func - The function that you'd like to execute.
//------------------------------------------------------------------------
LW_Animation.prototype.addEventFrame = function( time_offset, event_func )
{

  // Add the new event frame to the animation.
	this.event_frames.push( { time_offset: time_offset, event_func: event_func, triggered: false } );

}


//------------------------------------------------------------------------
// Function: start()
// Sets the animation to start playing.
//------------------------------------------------------------------------
LW_Animation.prototype.start = function()
{

	// Don't start if in the middle of playing.
	if ( this.status ) return;

	// Set the necessary values.
	this.status      = true;
	this.start_time  = new Date();

	// Width.
	if ( this.controller.width.to != null || this.controller.width.by != null )
	{

		// Get the element's width.
		this.begin_width = LW_DOM_Library.getWidth( this.element );

		// Get the desired width and offset width.
		this.desired_width  = (this.controller.width.to != null) ? (this.controller.width.to) : (this.begin_width + this.controller.width.by);
		this.offset_width   = this.desired_width - this.begin_width;

	}

	// Height.
	if ( this.controller.height.to != null || this.controller.height.by != null )
	{

		// Get the element's height.
		this.begin_height = LW_DOM_Library.getHeight( this.element );

		// Get the desired height and offset height.
		this.desired_height  = (this.controller.height.to != null) ? (this.controller.height.to) : (this.begin_height + this.controller.height.by);
		this.offset_height   = this.desired_height - this.begin_height;

	}

	// Position.
	if ( this.controller.move.to.X != null || this.controller.move.to.Y != null || this.controller.move.by.X != null || this.controller.move.by.Y != null )
	{

		// Get the element's position.
		this.begin_pos = LW_DOM_Library.getXY( this.element );

		// Get the desired X position and X offset position.
		if ( this.controller.move.to.X != null || this.controller.move.by.X != null )
		{

			this.desired_pos.X  = (this.controller.move.to.X != null) ? (this.controller.move.to.X) : (this.begin_pos.X + this.controller.move.by.X);
			this.offset_pos.X   = this.desired_pos.X - this.begin_pos.X;

		}

		// Get the desired Y position and Y offset position.
		if ( this.controller.move.to.Y != null || this.controller.move.by.Y != null )
		{

			this.desired_pos.Y  = (this.controller.move.to.Y != null) ? (this.controller.move.to.Y) : (this.begin_pos.Y + this.controller.move.by.Y);
			this.offset_pos.Y   = this.desired_pos.Y - this.begin_pos.Y;

		}

	}

	// Opacity.
	if ( this.controller.opacity.to != null || this.controller.opacity.by != null )
	{
		
		// Get the element's opacity.
		this.begin_opacity = LW_DOM_Library.getStyle( this.element, "opacity" );
		
		// Get the desired opacity and offset opacity.
		this.desired_opacity  = (this.controller.opacity.to != null) ? (this.controller.opacity.to) : (this.begin_opacity + this.controller.opacity.by);
		this.offset_opacity   = this.desired_opacity - this.begin_opacity;
		
	}

	// Background Color.
	if ( this.controller.background_color.to.R != null || 
	     this.controller.background_color.to.G != null || 
		 this.controller.background_color.to.B != null || 
	     this.controller.background_color.by.R != null ||
		 this.controller.background_color.by.G != null ||
		 this.controller.background_color.by.B != null )
	{
		
		// Get the element's background color.
		this.begin_back_color   = new LW_Structure_Color( LW_DOM_Library.getStyle( this.element, "backgroundColor" ).substring( 1 ) );
		this.desired_back_color = new LW_Structure_Color( this.begin_back_color.toHexString() );

		// Get the desired red value and offset value.
		if ( this.controller.background_color.to.R != null || this.controller.background_color.by.R != null )
		{

			this.desired_back_color.R  = (this.controller.background_color.to.R != null) ? (this.controller.background_color.to.R) : (this.begin_back_color.R + this.controller.background_color.by.R);
			this.offset_back_color.R   = this.desired_back_color.R - this.begin_back_color.R;

		}

		// Get the desired green value and offset value.
		if ( this.controller.background_color.to.G != null || this.controller.background_color.by.G != null )
		{

			this.desired_back_color.G  = (this.controller.background_color.to.G != null) ? (this.controller.background_color.to.G) : (this.begin_back_color.G + this.controller.background_color.by.G);
			this.offset_back_color.G   = this.desired_back_color.G - this.begin_back_color.G;

		}

		// Get the desired blue value and offset value.
		if ( this.controller.background_color.to.B != null || this.controller.background_color.by.B != null )
		{

			this.desired_back_color.B  = (this.controller.background_color.to.B != null) ? (this.controller.background_color.to.B) : (this.begin_back_color.B + this.controller.background_color.by.B);
			this.offset_back_color.B   = this.desired_back_color.B - this.begin_back_color.B;

		}

	}

	// Border Color.
	if ( this.controller.border_color.to.R != null || 
	     this.controller.border_color.to.G != null || 
		 this.controller.border_color.to.B != null || 
	     this.controller.border_color.by.R != null ||
		 this.controller.border_color.by.G != null ||
		 this.controller.border_color.by.B != null )
	{
		
		// Get the element's border color.
		this.begin_border_color   = new LW_Structure_Color( LW_DOM_Library.getStyle( this.element, "borderColor" ).substring( 1 ) );
		this.desired_border_color = new LW_Structure_Color( this.begin_border_color.toHexString() );

		// Get the desired red value and offset value.
		if ( this.controller.border_color.to.R != null || this.controller.border_color.by.R != null )
		{

			this.desired_border_color.R  = (this.controller.border_color.to.R != null) ? (this.controller.border_color.to.R) : (this.begin_border_color.R + this.controller.border_color.by.R);
			this.offset_border_color.R   = this.desired_border_color.R - this.begin_border_color.R;

		}

		// Get the desired green value and offset value.
		if ( this.controller.border_color.to.G != null || this.controller.border_color.by.G != null )
		{

			this.desired_border_color.G  = (this.controller.border_color.to.G != null) ? (this.controller.border_color.to.G) : (this.begin_border_color.G + this.controller.border_color.by.G);
			this.offset_border_color.G   = this.desired_border_color.G - this.begin_border_color.G;

		}

		// Get the desired blue value and offset value.
		if ( this.controller.border_color.to.B != null || this.controller.border_color.by.B != null )
		{

			this.desired_border_color.B  = (this.controller.border_color.to.B != null) ? (this.controller.border_color.to.B) : (this.begin_border_color.B + this.controller.border_color.by.B);
			this.offset_border_color.B   = this.desired_border_color.B - this.begin_border_color.B;

		}

	}

	// Text Color.
	if ( this.controller.text_color.to.R != null || 
	     this.controller.text_color.to.G != null || 
		 this.controller.text_color.to.B != null || 
	     this.controller.text_color.by.R != null ||
		 this.controller.text_color.by.G != null ||
		 this.controller.text_color.by.B != null )
	{

		// Get the element's text color.
		this.begin_text_color   = new LW_Structure_Color( LW_DOM_Library.getStyle( this.element, "color" ).substring( 1 ) );
		this.desired_text_color = new LW_Structure_Color( this.begin_text_color.toHexString() );

		// Get the desired red value and offset value.
		if ( this.controller.text_color.to.R != null || this.controller.text_color.by.R != null )
		{

			this.desired_text_color.R  = (this.controller.text_color.to.R != null) ? (this.controller.text_color.to.R) : (this.begin_text_color.R + this.controller.text_color.by.R);
			this.offset_text_color.R   = this.desired_text_color.R - this.begin_text_color.R;

		}

		// Get the desired green value and offset value.
		if ( this.controller.text_color.to.G != null || this.controller.text_color.by.G != null )
		{

			this.desired_text_color.G  = (this.controller.text_color.to.G != null) ? (this.controller.text_color.to.G) : (this.begin_text_color.G + this.controller.text_color.by.G);
			this.offset_text_color.G   = this.desired_text_color.G - this.begin_text_color.G;

		}

		// Get the desired blue value and offset value.
		if ( this.controller.text_color.to.B != null || this.controller.text_color.by.B != null )
		{

			this.desired_text_color.B  = (this.controller.text_color.to.B != null) ? (this.controller.text_color.to.B) : (this.begin_text_color.B + this.controller.text_color.by.B);
			this.offset_text_color.B   = this.desired_text_color.B - this.begin_text_color.B;

		}

	}

	// Call the onStart function if there is any.
	if ( this.onStart != null )
	  this.onStart( this );

	// Call the incrementAnimation function. It will start the animation.
	LW_Animation_Manager.addAnimation( this );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceWidth()
// Advances the width.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceWidth = function()
{

	// Get the new width.
	var new_width = LW_Animation.tweenValue( this.controller.width.ease, (this.current_time - this.controller.delay), this.run_time, this.begin_width, this.offset_width );

	// Bounds.
	new_width = Math.max( new_width, 0 );

	// Set the new width on the element.
	LW_DOM_Library.setStyle( this.element, "width", new_width + "px" );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceHeight()
// Advances the height.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceHeight = function()
{

	// Get the new height.
	var new_height = LW_Animation.tweenValue( this.controller.height.ease, (this.current_time - this.controller.delay), this.run_time, this.begin_height, this.offset_height );
	
	// Bounds.
	new_height = Math.max( new_height, 0 );
	
	// Set the new height on the element.
	LW_DOM_Library.setStyle( this.element, "height", new_height + "px" );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advancePosition()
// Advances the position.
//------------------------------------------------------------------------
LW_Animation.prototype.advancePosition = function()
{

	// Updating X position?
	if ( this.offset_pos.X != null )
	{

		// Get the new X position.
		var new_X_pos = LW_Animation.tweenValue( this.controller.move.ease, (this.current_time - this.controller.delay), this.run_time, this.begin_pos.X, this.offset_pos.X );
		
		// Bounds.
		new_X_pos = Math.max( new_X_pos, 0 );

		// Set the new X position on the element.
		LW_DOM_Library.setX( this.element, new_X_pos );

	}  // End if updating X position.

	// Updating Y position?
	if ( this.offset_pos.Y != null )
	{

		// Get the new Y position.
		var new_Y_pos = LW_Animation.tweenValue( this.controller.move.ease, (this.current_time - this.controller.delay), this.run_time, this.begin_pos.Y, this.offset_pos.Y );
		
		// Bounds.
		new_Y_pos = Math.max( new_Y_pos, 0 );

		// Set the new Y position on the element.
		LW_DOM_Library.setY( this.element, new_Y_pos );

	}  // End if updating Y position.

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceOpacity()
// Advances the opacity.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceOpacity = function()
{

	// Get the new opacity.
	var new_opacity = (LW_Animation.tweenValue( this.controller.opacity.ease, (this.current_time - this.controller.delay), this.run_time, (this.begin_opacity * 100), (this.offset_opacity * 100) ) / 100);
	
	// Bounds.
	new_opacity = Math.min( Math.max( new_opacity, 0 ), 1 );
	
	// Set the new opacity on the element.
	LW_DOM_Library.setStyle( this.element, "opacity", new_opacity );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceBackgroundColor()
// Advances the background color.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceBackgroundColor = function()
{

	// Set the new back color as the beginning color.
	var new_back_color = new LW_Structure_Color( this.begin_back_color.toHexString() );

	// Updating red value?
	if ( this.offset_back_color.R != null )
	{

		// Get the new background color.
		new_back_color.R = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_back_color.R, this.offset_back_color.R ) );
	
	}  // End if updating red value.

	// Updating green value?
	if ( this.offset_back_color.G != null )
	{

		// Get the new background color.
		new_back_color.G = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_back_color.G, this.offset_back_color.G ) );

	}  // End if updating red value.

	// Updating blue value?
	if ( this.offset_back_color.B != null )
	{

		// Get the new background color.
		new_back_color.B = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_back_color.B, this.offset_back_color.B ) );

	}  // End if updating red value.
	
	// Bounds.
	new_back_color.R = Math.min( Math.max( new_back_color.R, 0 ), 255 );
	new_back_color.G = Math.min( Math.max( new_back_color.G, 0 ), 255 );
	new_back_color.B = Math.min( Math.max( new_back_color.B, 0 ), 255 );

	// Set the new background color on the element.
	LW_DOM_Library.setStyle( this.element, "backgroundColor", "#" + new_back_color.toHexString() );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceBorderColor()
// Advances the border color.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceBorderColor = function()
{

	// Set the new border color as the beginning color.
	var new_border_color = new LW_Structure_Color( this.begin_border_color.toHexString() );

	// Updating red value?
	if ( this.offset_border_color.R != null )
	{

		// Get the new border color.
		new_border_color.R = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_border_color.R, this.offset_border_color.R ) );

	}  // End if updating red value.

	// Updating green value?
	if ( this.offset_back_color.G != null )
	{

		// Get the new border color.
		new_border_color.G = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_border_color.G, this.offset_border_color.G ) );

	}  // End if updating red value.

	// Updating blue value?
	if ( this.offset_border_color.B != null )
	{

		// Get the new border color.
		new_border_color.B = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_border_color.B, this.offset_border_color.B ) );

	}  // End if updating red value.
	
	// Bounds.
	new_border_color.R = Math.min( Math.max( new_border_color.R, 0 ), 255 );
	new_border_color.G = Math.min( Math.max( new_border_color.G, 0 ), 255 );
	new_border_color.B = Math.min( Math.max( new_border_color.B, 0 ), 255 );

	// Set the new border color on the element.
	LW_DOM_Library.setStyle( this.element, "borderColor", "#" + new_border_color.toHexString() );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceTextColor()
// Advances the text color.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceTextColor = function()
{

	// Set the new text color as the beginning color.
	var new_text_color = new LW_Structure_Color( this.begin_text_color.toHexString() );

	// Updating red value?
	if ( this.offset_text_color.R != null )
	{

		// Get the new text color.
		new_text_color.R = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_text_color.R, this.offset_text_color.R ) );

	}  // End if updating red value.

	// Updating green value?
	if ( this.offset_text_color.G != null )
	{

		// Get the new text color.
		new_text_color.G = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_text_color.G, this.offset_text_color.G ) );

	}  // End if updating red value.

	// Updating blue value?
	if ( this.offset_text_color.B != null )
	{

		// Get the new text color.
		new_text_color.B = Math.ceil( LW_Animation.tweenValue( LW_Animation.EASE_NONE, (this.current_time - this.controller.delay), this.run_time, this.begin_text_color.B, this.offset_text_color.B ) );

	}  // End if updating red value.
	
	// Bounds.
	new_text_color.R = Math.min( Math.max( new_text_color.R, 0 ), 255 );
	new_text_color.G = Math.min( Math.max( new_text_color.G, 0 ), 255 );
	new_text_color.B = Math.min( Math.max( new_text_color.B, 0 ), 255 );

	// Set the new text color on the element.
	LW_DOM_Library.setStyle( this.element, "color", "#" + new_text_color.toHexString() );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: advanceFrame()
// Carries out the next frame of the animation.
//------------------------------------------------------------------------
LW_Animation.prototype.advanceFrame = function()
{

	// If the animation is stopped, return false.
	if ( !this.status )
	  return false;

	// Update the current time.
	this.current_time = new Date() - this.start_time;

	// Only start incrementing if we have passed the delay time.
	if ( this.current_time > this.controller.delay )
	{
		
		// Animating width?
		if ( this.desired_width )
			this.advanceWidth();

		// Animating height?
		if ( this.desired_height )
			this.advanceHeight();

		// Animating position?
		if ( this.desired_pos.X || this.desired_pos.Y )
			this.advancePosition();

		// Animating opacity?
		if ( this.desired_opacity )
			this.advanceOpacity();

		// Animating background color?
		if ( this.desired_back_color )
			this.advanceBackgroundColor();

		// Animating border color?
		if ( this.desired_border_color )
			this.advanceBorderColor();

		// Animating text color?
		if ( this.desired_text_color )
			this.advanceTextColor();
			
		// Loop through each event frame.
		var event_triggered = false;
		for ( var i = 0; i < this.event_frames.length; i++ )
		{

			// If it is time (or passed time) to trigger the event, do so.
			if ( !this.event_frames[i].triggered && this.current_time >= this.controller.delay + this.event_frames[i].time_offset )
			{

			  this.event_frames[i].event_func( this );
				this.event_frames[i].triggered = true;
				event_triggered = true;

			}

		}  // Next event frame.

		// If an event was triggered and there's an onEventFrame function, call it.
		if ( event_triggered && this.onEventFrame )
		  this.onEventFrame( this );

		// Call the onAdvance function if there is any.
		if ( this.onAdvance )
			this.onAdvance( this );

	}  // End if delay is over.

	// Call the onAdvance function if there is any.
	if ( this.onInterval )
		this.onInterval( this );

	// Should we continue processing?
	if ( this.current_time < this.run_time + this.controller.delay )
		return true;
	else
		return false;

}


//------------------------------------------------------------------------
// Function: stop()
// Stops the animation where it currently is. Does not finish it.
//------------------------------------------------------------------------
LW_Animation.prototype.stop = function()
{

	// Set the animation's status to not playing.
	this.status = false;

	// Call the onStop function if there is any.
	if ( this.onStop )
	  this.onStop( this );

}


//------------------------------------------------------------------------
// (Exclude)
// Function: finish()
// Does the required clean up of the animation.
//------------------------------------------------------------------------
LW_Animation.prototype.finish = function()
{

	// Set the animation's status to not playing.
	this.status = false;
	
	// Get rid of any animation errors. Set the desired values on the elements.
	if ( this.desired_width        ) LW_DOM_Library.setStyle( this.element, "width", this.desired_width + "px" );
	if ( this.desired_height       ) LW_DOM_Library.setStyle( this.element, "height", this.desired_height + "px" );

	if ( this.desired_pos.X        ) LW_DOM_Library.setX( this.element, this.desired_pos.X );
	if ( this.desired_pos.Y        ) LW_DOM_Library.setY( this.element, this.desired_pos.Y );

	if ( this.desired_opacity      ) LW_DOM_Library.setStyle( this.element, "opacity", this.desired_opacity );

	if ( this.desired_back_color   ) LW_DOM_Library.setStyle( this.element, "backgroundColor", "#" + this.desired_back_color.toHexString() );

	if ( this.desired_border_color ) LW_DOM_Library.setStyle( this.element, "borderColor", "#" + this.desired_border_color.toHexString() );

	if ( this.desired_text_color   ) LW_DOM_Library.setStyle( this.element, "color", "#" + this.desired_text_color.toHexString() );

	// Call the onFinish function if there is any.
	if ( this.onFinish )
	  this.onFinish( this );

}


//------------------------------------------------------------------------
// Public Static Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// (Exclude)
// Function: tweenValue()
// Tweens the value.
//------------------------------------------------------------------------
LW_Animation.tweenValue = function( ease_type, current_time, duration, begin_val, change_val )
{
	
	// What easing equation?
	switch( ease_type )
	{
		
	// EASE NONE
	case LW_Animation.EASE_NONE:	
		return change_val * (current_time / duration) + begin_val;
		
	// EASE IN
	case LW_Animation.EASE_IN:
		return change_val * (current_time /= duration) * current_time + begin_val;
		
	// EASE OUT
	case LW_Animation.EASE_OUT:
		return -change_val * (current_time /= duration) * (current_time - 2) + begin_val;
		
	// EASE BOTH
	case LW_Animation.EASE_BOTH:
		
		if ( (current_time /= duration / 2) < 1 ) 
			return change_val / 2 * current_time * current_time + begin_val;

		return -change_val / 2 * ((--current_time) * (current_time - 2) - 1) + begin_val;
		
	// STRONG EASE IN
	case LW_Animation.STRONG_EASE_IN:
		return change_val * (current_time /= duration) * current_time * current_time * current_time + begin_val;
	
	// STRONG EASE OUT	
	case LW_Animation.STRONG_EASE_OUT:
		return -change_val * ((current_time = current_time / duration - 1) * current_time * current_time * current_time - 1) + begin_val;
		
	// STRONG EASE BOTH
	case LW_Animation.STRONG_EASE_BOTH:
	
		if ( (current_time /= duration / 2) < 1 ) 
			return change_val / 2 * current_time * current_time * current_time * current_time + begin_val;

		return -change_val / 2 * ((current_time -= 2) * current_time * current_time * current_time - 2) + begin_val;
		
	// BACK EASE IN
	case LW_Animation.BACK_EASE_IN:
		return change_val * (current_time /= duration) * current_time * (2.70158 * current_time - 1.70158) + begin_val;
		
	// BACK EASE OUT
	case LW_Animation.BACK_EASE_OUT:
		return change_val * ((current_time = current_time / duration - 1) * current_time * (2.70158 * current_time + 1.70158) + 1) + begin_val;
		
	// BACK EASE BOTH
	case LW_Animation.BACK_EASE_BOTH:
		
		if ( (current_time /= duration / 2) < 1 ) 
			return change_val / 2 * (current_time * current_time * (3.5949095 * current_time - 2.5949095)) + begin_val;

		return change_val / 2 * ((current_time -= 2) * current_time * (3.5949095 * current_time + 2.5949095) + 2) + begin_val;
		
	// BOUNCE EASE IN
	case LW_Animation.BOUNCE_EASE_IN:
		
		current_time = duration - current_time;

		if ( (current_time /= duration) < (1 / 2.75) )
			return change_val - (change_val * (7.5625 * current_time * current_time)) + begin_val;
		else if ( current_time < (2 / 2.75 ) )
			return change_val - (change_val * (7.5625 * (current_time -= (1.5 / 2.75)) * current_time + 0.75)) + begin_val;
		else if ( current_time < (2.5 / 2.75) )
			return change_val - (change_val * (7.5625 * (current_time -= (2.25 / 2.75)) * current_time + 0.9375)) + begin_val;
		else
			return change_val - (change_val * (7.5625 * (current_time -= (2.625 / 2.75)) * current_time + 0.984375)) + begin_val;
		
	// BOUNCE EASE OUT	
	case LW_Animation.BOUNCE_EASE_OUT:
	
		if ( (current_time /= duration) < (1 / 2.75) )
		  return change_val * (7.5625 * current_time * current_time) + begin_val;
		else if ( current_time < (2 / 2.75 ) )
		  return change_val * (7.5625 * (current_time -= (1.5 / 2.75)) * current_time + 0.75) + begin_val;
		else if ( current_time < (2.5 / 2.75) )
		  return change_val * (7.5625 * (current_time -= (2.25 / 2.75)) * current_time + 0.9375) + begin_val;
		else
		  return change_val * (7.5625 * (current_time -= (2.625 / 2.75)) * current_time + 0.984375) + begin_val;
		  
	// BOUNCE EASE BOTH
	case LW_Animation.BOUNCE_EASE_BOTH:
	
		if ( current_time < duration / 2 )
		{

			current_time = duration - (current_time * 2);

			if ( (current_time /= duration) < (1 / 2.75) )
				return (change_val - (change_val * (7.5625 * current_time * current_time))) * 0.5 + begin_val;
			else if ( current_time < (2 / 2.75 ) )
				return (change_val - (change_val * (7.5625 * (current_time -= (1.5 / 2.75)) * current_time + 0.75))) * 0.5 + begin_val;
			else if ( current_time < (2.5 / 2.75) )
				return (change_val - (change_val * (7.5625 * (current_time -= (2.25 / 2.75)) * current_time + 0.9375))) * 0.5 + begin_val;
			else
				return (change_val - (change_val * (7.5625 * (current_time -= (2.625 / 2.75)) * current_time + 0.984375))) * 0.5 + begin_val;

		}

		current_time = current_time * 2 - duration;

		if ( (current_time /= duration) < (1 / 2.75) )
		  return change_val * (7.5625 * current_time * current_time) * 0.5 + change_val * 0.5 + begin_val;
		else if ( current_time < (2 / 2.75 ) )
		  return change_val * (7.5625 * (current_time -= (1.5 / 2.75)) * current_time + 0.75) * 0.5 + change_val * 0.5 + begin_val;
		else if ( current_time < (2.5 / 2.75) )
		  return change_val * (7.5625 * (current_time -= (2.25 / 2.75)) * current_time + 0.9375) * 0.5 + change_val * 0.5 + begin_val;
		else
		  return change_val * (7.5625 * (current_time -= (2.625 / 2.75)) * current_time + 0.984375) * 0.5 + change_val * 0.5 + begin_val;
		  
	// ELASTIC EASE IN
	case LW_Animation.ELASTIC_EASE_IN:
	
		if ( current_time == 0 ) 
			return begin_val;
			
		if ( (current_time /= duration) == 1 ) 
			return begin_val + change_val;

		var p = duration * 0.3;
		var a = change_val;
		var s = p / 4;

		return -(a * Math.pow( 2, 10 * (current_time -= 1) ) * Math.sin( (current_time * duration - s) * (2 * Math.PI) / p )) + begin_val;
		
	// ELASTIC EASE OUT
	case LW_Animation.ELASTIC_EASE_OUT:
		
		if ( current_time == 0 ) 
			return begin_val;
			
		if ( (current_time /= duration) == 1 ) 
			return begin_val + change_val;

		var p = duration * 0.3;
		var a = change_val;
		var s = p / 4;

		return a * Math.pow( 2, -10 * current_time ) * Math.sin( (current_time * duration - s) * (2 * Math.PI) / p ) + change_val + begin_val;
		
	// ELASTIC EASE BOTH
	case LW_Animation.ELASTIC_EASE_BOTH:
	
		if ( current_time == 0 ) 
			return begin_val;
			
		if ( (current_time /= duration / 2) == 2 ) 
			return begin_val + change_val;

		var p = duration * (0.3 * 1.5);
		var a = change_val;
		var s = p / 4;

		if ( current_time < 1 ) return -0.5 * (a * Math.pow( 2, 10 * (current_time -= 1) ) * Math.sin( (current_time * duration - s) * (2 * Math.PI) / p )) + begin_val;

		return a * Math.pow( 2, -10 * (current_time -= 1) ) * Math.sin( (current_time * duration - s) * (2 * Math.PI) / p ) * 0.5 + change_val + begin_val;
		
	}

}


//------------------------------------------------------------------------
// Class: LW_Animation_Sequence
// Stores a sequence of <LW_Animation> objects.
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Static Variables
//------------------------------------------------------------------------
LW_Animation_Sequence.sequences = new Array();


//------------------------------------------------------------------------
// Public Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// Constructor: LW_Animation_Sequence()
// Class constructor.
//
// Parameters:
//     options - An optional object of options for the Animation Sequence.
//------------------------------------------------------------------------
function LW_Animation_Sequence( options )
{

	// Store the default values.
	this.animations               = new Array();
	this.current_animation_index  = 0;
	this.sequence_index           = LW_Animation_Sequence.sequences.length;
	this.status                   = false;
	this.options                  = options;
	
	// Callbacks.
	this.onStart               = null;
	this.onAdvance             = null;
	this.onLoop                = null;
	this.onFinish              = null;

	// Store this animation sequence in the global sequences array.
	LW_Animation_Sequence.sequences[this.sequence_index] = this;

}


//------------------------------------------------------------------------
// Function: addAnimation()
// Adds an <LW_Animation> object to the animation sequence.
//
// Parameters:
//     animation - An <LW_Animation> object that you would like to set up
//                 to play in the animation. Will add it at the end of the
//                 sequence.
//------------------------------------------------------------------------
LW_Animation_Sequence.prototype.addAnimation = function( animation )
{

	// Store the animation in the sequence.
	this.animations.push( animation );

	// Add the onFinish and onStop functions.
	LW_Events_Handler.addEvent( animation, "onFinish", LW_Animation_Sequence.nextAnimation );
	LW_Events_Handler.addEvent( animation, "onStop", LW_Animation_Sequence.nextAnimation );

	// Store the sequence index in the animation.
	animation.sequence_index = this.sequence_index;

}


//------------------------------------------------------------------------
// Function: start()
// Sets the Animation Sequence to start playing.
//------------------------------------------------------------------------
LW_Animation_Sequence.prototype.start = function()
{

	// Only start if there is at least one animation in the sequence
	// and we are not already playing.
	if ( this.animations.length == 0 || this.status ) return;

	// Set as playing.
	this.status = true;
	
	// On start callback.
	if ( this.onStart != null && this.onStart( this ) == false )
		return;

	// Start the first animation in the sequence.
	this.animations[0].start();

}


//------------------------------------------------------------------------
// (Exclude)
// Function: reset()
// Cleans up the animation sequence.
//------------------------------------------------------------------------
LW_Animation_Sequence.prototype.reset = function()
{

	// Reset the values.
	this.status                   = false;
	this.current_animation_index  = 0;

}


//------------------------------------------------------------------------
// Public Static Member Functions
//------------------------------------------------------------------------

//------------------------------------------------------------------------
// (Exclude)
// Function: nextAnimation()
// Plays the next animation in the sequence. This is set as the previous
// animation's onFinish function so that a chain forms.
//------------------------------------------------------------------------
LW_Animation_Sequence.nextAnimation = function( animation )
{

	// Get the animation sequence.
	var animation_sequence = LW_Animation_Sequence.sequences[animation.sequence_index];

	// If the animation sequence is stopped, return false.
	if ( !animation_sequence.status )
	  return false;

	// Increment the current animation index.
	animation_sequence.current_animation_index++;

	// Play the next animation if there is one.
	if ( animation_sequence.animations[animation_sequence.current_animation_index] != null )
	{
		
		// On advance callback.
		if ( animation_sequence.onAdvance != null && animation_sequence.onAdvance( animation_sequence ) == false )
			return;

		// Start the next animation.
		animation_sequence.animations[animation_sequence.current_animation_index].start();

	}  // End if next animation.
	else
	{
		
		// Should we loop?
		if ( animation_sequence.options && animation_sequence.options.loop == true )
		{
			
			// On loop callback.
			if ( animation_sequence.onLoop != null && animation_sequence.onLoop( animation_sequence ) == false )
				return;
				
			// Loop.
			animation_sequence.reset();
			animation_sequence.start();
			
		}  // End if looping.
		else
		{

			// Finish the animation sequence.
			animation_sequence.reset();
			
			// On finish callback.
			if ( animation_sequence.onFinish != null )
				animation_sequence.onFinish( animation_sequence );
			
		}

	}  // End if no more animations.

}


//------------------------------------------------------------------------
// (Exclude)
// Class: LW_Animation_Manager
// Manages each animation. All the animations are incremented through the
// manager.
//------------------------------------------------------------------------
LW_Animation_Manager =
{

	//----------------------------------------------------------------------
	// Public Variables
	//----------------------------------------------------------------------
	increment_speed:     20,           // The speed at which the animation manager will increment each animation.
	playing_animations:  new Array(),  // An array of all the currently playing animations.
	interval_handle:     null,         // The handle that the setInterval() function returns.


	//----------------------------------------------------------------------
	// Public Member Functions
	//----------------------------------------------------------------------
	//----------------------------------------------------------------------
	// (Exclude)
	// Function: addAnimation()
	// This function is used to add an animation to the animation manager
	// for playing.
	//----------------------------------------------------------------------
	addAnimation: function( animation )
	{

		// Loop through each animation being played.
		for ( var i = 0; i < this.playing_animations.length; i++ )
		{

			// Get the animation.
			var playing_animation = this.playing_animations[i];

			// Is the animation we're adding animate the
			// same element than this animation's element?
			if ( animation.element == playing_animation.element )
			{

				// Remove the animation from the playing animations array.
				this.playing_animations.splice( i, 1 );

				// Stop the currently playing animation so that we can play this one.
				playing_animation.stop();

			}  // End if managing the same element.

		}  // Next playing animation.

		// Add the animation to the playing animations array.
		this.playing_animations.push( animation );

		// If we don't have any animations playing,
		// we have to set up the timeout.
		if ( this.interval_handle == null )
		{

			// Set to advanced all animations.
			this.interval_handle = setInterval( LW_Animation_Manager.advanceAnimations, this.increment_speed, null );

		}  // End if no animations currently playing.

	},


	//------------------------------------------------------------------------
	// (Exclude)
	// Function: advanceAnimations()
	// Advances each animation being played.
	//------------------------------------------------------------------------
	advanceAnimations: function()
	{

		// Loop through each animation being played.
		for ( var i = 0; i < LW_Animation_Manager.playing_animations.length; i++ )
		{

			// Get the animation from the array.
			var animation = LW_Animation_Manager.playing_animations[i];

			// Advance the animation.
			var continue_playing = animation.advanceFrame();

			// Is the animation done playing?
			if ( !continue_playing )
			{
				
				// Remove the animation from the playing animations array.
				LW_Animation_Manager.playing_animations.splice( i, 1 );
				
				// Finish up the animation.
				animation.finish();
				
				// If we don't have any more animations to play, stop
				// JavaScript from calling this function again.
				if ( LW_Animation_Manager.playing_animations.length == 0 )
				{
					clearInterval( LW_Animation_Manager.interval_handle );
					LW_Animation_Manager.interval_handle = null;
				}

			}  // End if stop playing this animation.

		}  // Next playing animation.

	}

}



//--------------------------------------------------------------------
// Name: addImageRollovers()
// Desc: An array of IDs of images is passed in and it adds rollovers
//       to each one.
//--------------------------------------------------------------------
function addImageRollovers( id_array )
{	
	
	addImageRollovers.active_element = "";
	
	if ( document.getElementById( "menu" ) )
		addImageRollovers.active_element = LW_DOM_Library.getElementsByClassName( "active", "div", document.getElementById( "menu" ) )[0].id;
	
	// We use this function so that we can correctly form a closure
	// around the element.
	function addRollover( id )
	{
		    
	    var element = document.getElementById( id );
	    
	    // The function used for mousing onto the menu item..
	    function rollOver()
	    {
	    	
	    	if ( id == addImageRollovers.active_element )
				element.className = "hover_active";
			else
				element.className = "hover";
			
		}
		
		// The function used for mousing off of the menu item.
		function rollOut()
		{
			
			if ( id == addImageRollovers.active_element )
				element.className = "active";
			else
				element.className = "";
				
		}
	    
	    // Set the events.
	    LW_Events_Handler.addEvent( element, "onmouseover", rollOver );
	    LW_Events_Handler.addEvent( element, "onmouseout", rollOut );
	
	}

    // Get the image's elements.
    for ( var i = 0; i < id_array.length; i++ )
    {
        
        addRollover( id_array[i] );
        
    }  // Next image.
    
}


//--------------------------------------------------------------------
// Name: preloadImages()
// Desc: Used to preload images before they are shown.
//--------------------------------------------------------------------
function preloadImages( image_array )
{
	
	// Create the preloaders array.
	var preloaders = new Array( image_array.length );
	
	// Loop through every image that we want to preload.
	for ( var i in image_array )
	{
		
		// Preload the image.
		preloaders[i] = new Image();
		preloaders[i].src = image_array[i];
		
	}
	
}


//--------------------------------------------------------------------
// Name: toggleListing()
// Desc: Used to preload images before they are shown.
//--------------------------------------------------------------------
function toggleListing( id )
{
	
	// Loop through all the listings and hide them.
	var listings = LW_DOM_Library.getElementsByClassName( "listing" );
	for ( var i = 0; i < listings.length; i++ )
		LW_DOM_Library.setStyle( listings, "display", "none" );
		
	if ( id != 0 && id != toggleListing.active_id )
	{
		
		var listing = document.getElementById( "listing" + id );
		
		// Show the listing.
		LW_DOM_Library.setStyle( listing, "display", "block" );
		
		// Scroll to the top of the listing.
		window.scroll( 0, LW_DOM_Library.getY( listing ) - 100 );
		
		// Set as active listing.
		toggleListing.active_id = id;
		
	}
	else
		toggleListing.active_id = "";
	
}

toggleListing.active_id = "";