	var Document_Click_Function = null;
	var Document_Escape_Key_Function = null;
	var Document_Down_Key_Function = null;
	var Document_Up_Key_Function = null;
	var Context_Element_ID = null;
	var Context_Menu_Element_ID = null;
	var Context_Highlight_Element_ID = null;
	var Simple_Menu_Element_ID = null;
	var Windows = new Array();	

/* Event Handlers */

	// Handle document level key presses, such as escape key, up and down...
	function Handle_Document_Key_Press(Key_Event)
	{
		// Handle the up arrow key.
		if (Key_Event.keyCode == 38)
		{	
			if (Document_Up_Key_Function)
				Up_Key_Function.call();
		}
		
		// Handle the down arrow key.
		if (Key_Event.keyCode == 40)
		{	
			if (Document_Down_Key_Function)
				Document_Down_Key_Function.call();
		}
		
		// Handle the escape key.
		if (Key_Event.keyCode == 27)
		{	
			if (Document_Escape_Key_Function)
				Document_Escape_Key_Function.call();
		}
		
		return true;
	}

	// Hide open menus.
	function Handle_Document_Click(Click_Event)
	{	
		// Hide any displayed simple menu.
		if (Simple_Menu_Element_ID)
			Hide_Simple_Menu();
			
		// Hide any displayed context menu.
		if (Context_Menu_Element_ID)	
			Hide_Context_Menu();
			
		// Hide any displayed context highlight.
		if (Context_Highlight_Element_ID)
			Hide_Context_Highlight();
			
		// Call the registered specialized hide functions.
		if (Document_Click_Function)
		{
			Document_Click_Function.call();
		}
			
		return true;		
	}
	
function Handle_Text_Area_Input_Key_Down(Key_Event, Text_Area_Element, Namespace)
{		
	// Handle open bracket key.
	if (Key_Event.charCode == 91)
	{				
		// Attach menu near cursor position
//		Create_Menu({ID: Namespace + '_Properties_Menu', From_Element: Namespace + '_Properties_Menu_Items', Position: 'Cursor', Attach: Text_Area_Element.id});
	}
	
	if (Key_Event.charCode == 93)
	{
	//document.getElementById("Body").removeChild(document.getElementById("Cursor_Size_Element"));
		Close_Menus();
	}
}

// Highlight an object if the control key is held, hide the current highlight otherwise.
var Handle_Hover_Bubble = false;
function Handle_Hover(event)
{
	// Handle only front-most event
	if (!Handle_Hover_Bubble)
	{
		Handle_Hover_Bubble = true;
		setTimeout("Handle_Hover_Bubble = false;", 5);
		
		// Show context highlight if control-key is held.
		if (event.ctrlKey)
			Show_Context_Highlight({"Target_Element": this});
			
		// Hide context highlight if control-key is not held and no context menu is displayed.
		else if (!Context_Menu_Element_ID)
			Hide_Context_Highlight();
	}
	
	return true;
}

// Open the object's context menu on right or control click.
var Handle_Context_Click_Bubble = false;
function Handle_Context_Click(event)
{
	// Don't trigger for any other than top level
	if (!Handle_Context_Click_Bubble)
	{		
		Handle_Context_Click_Bubble = true;
		setTimeout("Handle_Context_Click_Bubble = false", 200);

		// TODO: This is the developer key combination hack to bring up the normal context menu for firebug's inspect element.
		// Maybe the design should allow for this more naturally.			
		if (event.ctrlKey && event.shiftKey)
			return true;
		
		if (event.ctrlKey || event.button == 2)
		{			
			Show_Context_Menu({"Target_Element":this, "Mouse_Event":event});
			return false;
		}
	}
	return true;
}


/* Show and Hide Functions */

// Generate and display contextual information about a target element on the page.
function Show_Context_Highlight(Parameters)
{
	Force_Display = Parameters["Force_Display"];		
	Target_Element = Parameters["Target_Element"];
	if (!Target_Element)
		Target_Element = document.getElementById(Parameters["Target_Element_ID"]);
	if (!Target_Element)
		return;
	
	// If force display hasn't been specified then...
	// 		If the context highlight for the target element is already displayed, don't display highlight.
	// 		If a context menu is displayed, don't display highlight.
	// 		If a window has been opened, don't display highlight.		
	if (
		!Force_Display &&
		(
			(Target_Element.id == Context_Element_ID && Context_Highlight_Element_ID) ||
			(Context_Menu_Element_ID) ||
			(Windows.length > 0)
		)
	)
		return;
	
	// Hide currently displayed context highlight.
	Hide_Context_Highlight();
	
	// Position and display the four borders and flag of the item highlight interface.	
	Highlight_Border_Width = 3;
	var Element_Position = Find_Position(Target_Element);
	var Element_Size = Find_Size(Target_Element, 1);
	Element_Position[0] -= 5;
	Element_Position[1] -= 5;
	Element_Size[0] += 10;
	Element_Size[1] += 10;
	
	// Create highlight elements.
	var Highlight_Parts = [
		{
			"ID": "Container"
		},
		{ 
			"ID": "Top",
			"Parent_ID": "Container",
			"Top": Element_Position[1]  - Highlight_Border_Width + "px", 
			"Left": Element_Position[0]  +  "px",
			"Width": (Element_Size[0] ) + "px",
			"Height": Highlight_Border_Width + "px",
			"Class": "Highlight_Border Highlight_Top"
			
		},
		{
			"ID":"Right",
			"Parent_ID": "Container",
			"Top": Element_Position[1] + "px",
			"Left": Element_Position[0] + Element_Size[0] +"px",
			"Width": Highlight_Border_Width + "px",
			"Height": Element_Size[1] + "px",
			"Class": "Highlight_Border Highlight_Right",
		},
		{
			"ID":"Bottom",
			"Parent_ID": "Container",
			"Top": Element_Position[1]  + Element_Size[1] + "px",
			"Left": Element_Position[0] +"px",
			"Width": (Element_Size[0] ) + "px",
			"Height": Highlight_Border_Width + "px",
			"Class": "Highlight_Border Highlight_Bottom",
		},
		{
			"ID":"Left",
			"Parent_ID": "Container",
			"Top": Element_Position[1] + "px",
			"Left": Element_Position[0] - Highlight_Border_Width  +"px",
			"Width": Highlight_Border_Width + "px",
			"Height": Element_Size[1] + "px",
			"Class": "Highlight_Border Highlight_Left",
		},
		{
			"ID":"Top_Left",
			"Parent_ID": "Container",
			"Top": Element_Position[1] - 5 +  "px",
			"Left": Element_Position[0] - 5  +"px",
			"Class": "Highlight_Border Highlight_Top_Left",
		},
		{
			"ID":"Top_Right",
			"Parent_ID": "Container",
			"Top": Element_Position[1] - 5 +  "px",
			"Left": Element_Position[0] + Element_Size[0] +"px",
			"Class": "Highlight_Border Highlight_Top_Right",
		},
		{
			"ID":"Bottom_Left",
			"Parent_ID": "Container",
			"Top": Element_Position[1]  + Element_Size[1] + "px",
			"Left": Element_Position[0] - 5  +"px",
			"Class": "Highlight_Border Highlight_Bottom_Left",
		},
		{
			"ID":"Bottom_Right",
			"Parent_ID": "Container",
			"Top": Element_Position[1] + Element_Size[1]  + "px",
			"Left": Element_Position[0] + Element_Size[0] +"px",
			"Class": "Highlight_Border Highlight_Bottom_Right",
		},
		{
			"ID":"Flag",
			"Parent_ID": "Container",
			"Top": Math.max(5, (Element_Position[1]  - 30)) + "px",
			"Left": Math.max(5, (Element_Position[0] - 20))+ "px",
			"Class": "Highlight_Flag",
		},
		{
			"ID":"Title", 
			"Parent_ID" : "Flag",
			"Class": "Highlight_Title"
		},
		{
			"ID": "Pointer", 
			"Parent_ID" : "Flag",
			"Class": "Highlight_Pointer",
		}
	];
	
	for (var Highlight_Part_Index in Highlight_Parts)
	{
		var Highlight_Part = Highlight_Parts[Highlight_Part_Index];
		
		var Highlight_Part_Element = document.createElement("div");
		
		Highlight_Part_Element.id = Target_Element.id + "_Highlight_" + Highlight_Part["ID"];
		Highlight_Part_Element.style.top = Highlight_Part["Top"];
		Highlight_Part_Element.style.left = Highlight_Part["Left"];
		Highlight_Part_Element.style.width = Highlight_Part["Width"];
		Highlight_Part_Element.style.height = Highlight_Part["Height"];				
		if (Highlight_Part["Class"])
			Highlight_Part_Element.className = Highlight_Part["Class"];
		
		if (Highlight_Part["Parent_ID"])
			Highlight_Parent_Element = document.getElementById(Target_Element.id + "_Highlight_" + Highlight_Part["Parent_ID"]);
		else
			Highlight_Parent_Element = document.getElementById("Body");
		
		Highlight_Parent_Element.appendChild(Highlight_Part_Element);
	}
	
	// Set the text for the title flag.
	var Dependency = Dependencies_By_Namespace[Target_Element.id];
	if (Dependency.Name != "" && Dependency.Name != undefined)
		var Item_Label = Dependency.Name;
	else
		var Item_Label = Dependency.ID;
	if (Dependency.Type != undefined)
		var Item_Title = "<b>" + Item_Label + "</b>"  + " " + Dependency.Type;
	else
		var Item_Title = "<b>" + Item_Label + "</b>";
	document.getElementById(Target_Element.id + "_Highlight_Title").innerHTML = Item_Title;
	
	// Generate a shadow for the title flag.
	Generate_Shadow({"ID": Target_Element.id + "_Highlight_Flag"});
	
	// Register highlight element and target element ids.
	Context_Highlight_Element_ID = Target_Element.id + "_Highlight_Container";
	Context_Element_ID = Target_Element.id;
}

// Hide the currently displayed context highlight.
function Hide_Context_Highlight()
{
	Hide({'Remove_Element':true, 'ID': Context_Highlight_Element_ID});
	
	// Unregister context highlight element id and context element id.
	Context_Highlight_Element_ID = null;
	Context_Element_ID = null;
}

// Show the context menu for the target element.
function Show_Context_Menu(Parameters)
{				
	Target_Element = Parameters["Target_Element"];
	if (!Target_Element)
		Target_Element = document.getElementById(Parameters["Target_Element_ID"]);
	Mouse_Event = Parameters["Mouse_Event"];
	
	// If a window is displayed, do nothing.
	if (Windows.length > 0)
		return;	
	
	// Show the relevant context highlight.
	Show_Context_Highlight(Parameters);
	
	// Hide current context menu.
	Hide_Context_Menu();
	
	// Generate new context menu at mouse position.
	Context_Menu = document.createElement("div");
	Context_Menu.id  = Target_Element.id + "_Context_Menu";
	
	var Pointer_X = Mouse_Event.pageX || (Mouse_Event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
	var Pointer_Y = Mouse_Event.pageY || (Mouse_Event.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
	
	Context_Menu.style.left = (Pointer_X - 7) + "px";
	Context_Menu.style.top = (Pointer_Y - 7) + "px";
	Context_Menu.className = "Context_Menu";
	
	// Populate new context menu.
	var Context_Menu_List = document.createElement("ul");
	Context_Menu_List.className = "Context_Menu_List";
	Dependency = Dependencies_By_Namespace[Target_Element.id];
	
	// Add title
	/*
	Context_Menu_Title = document.createElement("li");
	Context_Menu_Title.className = "Context_Menu_Title";
	Context_Menu_Title.innerHTML = Dependency.Type + " " + "<b>" + Dependency.Name + "</b>";
	Context_Menu_List.appendChild(Context_Menu_Title);
	*/		
	
	// Add edit links for target element and each of its containers.
	Next_Dependency = Dependency;
	while (Next_Dependency)
	{
//		Log("Next Dependency!:" + Next_Dependency.Namespace + ", " + Next_Dependency.Parent_Namespace);
		if (Next_Dependency.Name)
		{		
			var Item_Row = document.createElement("li");
			Item_Row.className = "Context_Menu_Item";
			Item_Row.innerHTML = "<a href=\"#\" class=\"Context_Menu_Item_Link\" onmouseover=\"Show_Context_Highlight({'Target_Element_ID' : '" + Next_Dependency.Namespace + "', 'Force_Display' : true});\" onclick=\"Hide_Context_Menu(); Hide_Context_Highlight(); Show({'Type':'Window','Namespace':'"+ Next_Dependency.Namespace + "_Edit_" + Next_Dependency.Type + "_" + Next_Dependency.ID + "','URL':'" + Directory +  "/Action/Edit/Raw:Namespace=" + Next_Dependency.Namespace + "_Edit_" + Next_Dependency.Type + "_" + Next_Dependency.ID + ",Edit_Item_Type=" + Next_Dependency.Type + ",Edit_Item_ID=" + Next_Dependency.ID + "'}); return false;\">" + "Edit " + Next_Dependency.Type + " " + "<b>" + Next_Dependency.Name + "</b>" + "...</a>"
			
			Context_Menu_List.appendChild(Item_Row);
		}
		Next_Dependency = Dependencies_By_Namespace[Next_Dependency.Parent_Namespace];
	}
	
	// Add edit link for current template if it exists.
	if (Dependency.Template_ID)
	{
		var Item_Type = "Template";
		var Item_Row = document.createElement("li");
		Item_Row.className = "Context_Menu_Item  Context_Menu_Divider";
		Item_Row.innerHTML = "<a href=\"#\" class=\"Context_Menu_Item_Link\" onmouseover=\"Show_Context_Highlight({'Target_Element_ID' : '" + Dependency.Namespace + "', 'Force_Display' : true});\" onclick=\"Hide_Context_Menu(); Hide_Context_Highlight(); Show({'Type':'Window','Namespace':'"+ Dependency.Namespace + "_Edit_" + Item_Type + "_" + Dependency.Template_ID + "','URL':'" + Directory +  "/Action/Edit/Raw:Namespace=" + Dependency.Namespace + "_Edit_" + Item_Type + "_" + Dependency.Template_ID + ",Edit_Item_Type=" + Item_Type + ",Edit_Item_ID=" + Dependency.Template_ID + "'}); return false;\">" + "Edit" + " <b>" + Dependency.Template + "</b> " + "Template for " + Dependency.Template_Type + "...</a>";
		Context_Menu_List.appendChild(Item_Row);
	}
	
	// Otherwise add link to create a new template.
	else
	{
		var Item_Row = document.createElement("li");
		Item_Row.className = "Context_Menu_Item Context_Menu_Divider";
		Item_Row.innerHTML = "<a href=\"#\" class=\"Context_Menu_Item_Link\" onmouseover=\"Show_Context_Highlight({'Target_Element_ID' : '" + Dependency.Namespace + "', 'Force_Display' : true});\" onclick=\"Hide_Context_Menu();Hide_Context_Highlight();Execute_Action_With_Parameters({'Action': 'Add', 'Namespace': '" + Dependency.Namespace + "_Add_Type_Template', 'Parameters': {'Add_Type': 'Type_Template', 'Type':'" + Dependency.Type + "'}});\">Create <b>New</b> Template for " + Dependency.Type +  "...</a>";
		Context_Menu_List.appendChild(Item_Row);
	}
	
	// Add link to create new type.
	var Item_Row = document.createElement("li");
	Item_Row.className = "Context_Menu_Item Context_Menu_Divider";
	Item_Row.innerHTML = "<a href=\"#\" class=\"Context_Menu_Item_Link\"  onclick=\"Hide_Context_Menu();Hide_Context_Highlight();Execute_Action_With_Parameters({'Action': 'Add', 'Parameters': {'Add_Type': 'Type'}}); return false;\">Create <b>New</b> Type...</a>";
	Context_Menu_List.appendChild(Item_Row);
	
	// Add context menu to document.
	Context_Menu_Container = document.createElement("div");
	Context_Menu_Container.id  = Target_Element.id + "_Context_Menu_Container";
	Context_Menu.appendChild(Context_Menu_List);
	Context_Menu_Container.appendChild(Context_Menu);
	document.getElementById("Body").appendChild(Context_Menu_Container);		
			
	// Generate a shadow for the context menu.		
	Generate_Shadow({"Element":Context_Menu});
	
	// Register menu element and target element ids.
	Context_Element_ID = Target_Element.id;
	Context_Menu_Element_ID = Context_Menu_Container.id;
}

// Hide current context menu.
function Hide_Context_Menu()
{
	Hide({'Remove_Element':true, 'ID':Context_Menu_Element_ID});
	
	// Unregister context menu element id.
	Context_Menu_Element_ID = null;
}

// Show an simple menu element that will hide on the next document click.
function Show_Simple_Menu(Parameters)
{	
	Show_Element = Parameters["Element"];
	if (!Show_Element)
		Show_Element = document.getElementById(Parameters["ID"]);
		
	// Make sure the menu displays in the foreground.
	Show_Element.style.zIndex = "1000";
	
	Show({'Element':Show_Element});

	// Register simple menu element id.
	Simple_Menu_Element_ID = Show_Element.id;
}

// Hide the element that was last opened as a simple menu.
function Hide_Simple_Menu()
{	
	Hide({'ID':Simple_Menu_Element_ID});

	//Unregister simple menu element id.
	Simple_Menu_Element_ID = null;
}

// Show the uploading control inside a new window.
function Show_Uploader(Parameters)
{
	Namespace = Parameters["Namespace"];
	File_Name = Parameters["File_Name"];

	// Generate the uploader control and populate its namespace and file name.
	Uploader_Element = Parse_HTML_Text(Controls["Uploader"].replace(/NAMESPACE/g, Namespace).replace(/FILENAME/g, File_Name))[0];
	
	// Display the uploader control in a new window.
	Show_Window({"Namespace":Namespace, "Element": Uploader_Element});
}

function Show_HTML_Uploader(Parameters)
{
	var HTML_Uploader = Controls["HTML_Uploader"];
	
	HTML_Uploader = HTML_Uploader.replace(/ACTIONNAMESPACE/g, Parameters["Action_Namespace"]);
	HTML_Uploader = HTML_Uploader.replace(/INPUTALIAS/g, Parameters["Input_Alias"]);
	HTML_Uploader = HTML_Uploader.replace(/NAMESPACE/g, Parameters["Namespace"]);
	HTML_Uploader = HTML_Uploader.replace(/FILETYPE/g, Parameters["File_Type"]);
	
	document.getElementById(Parameters["Namespace"] + "_Uploader_No_Flash").innerHTML = HTML_Uploader;
	document.getElementById(Parameters["Namespace"] + "_Uploader_No_Flash").style.display = "block";
}

// Load an element or URL into a floating window.
function Show_Window(Parameters)
{
	var Namespace = Parameters["Namespace"];
	if (Parameters["URL"])
		var URL = Parameters["URL"];
	else
		var Inner_Element = Parameters["Element"];
	
	var Window_Item = document.getElementById(Namespace);
	if (!Window_Item)
	{
		Window_Item = Parse_HTML_Text(Controls["Window"].replace(/NAMESPACE/g, Namespace))[0];
		Windows.push(Window_Item);			
		
		Body_Item = document.getElementById("Body");
		Body_Item.appendChild(Window_Item);
	}
	Window_Item.style.zIndex = 500 + Windows.length * 2 + 1;
	
	Show_Lightbox();		
	
	if (URL)
	{
		Fill({"ID": Namespace, "URL": URL});
		Add_Dependency({"ID": "", "Namespace": Namespace, "URL": URL});
	}
	else
	{
		document.getElementById(Namespace).appendChild(Inner_Element);
	}
}
// TODO : Change defaults.xmk
function Add_Window(Namespace, URL){Show_Window({"Namespace":Namespace, "URL": URL});}

// Hide the window that was last opened.
function Hide_Window()
{
	// Remove top window if it exists
	if (Windows.length)
	{
		var Window_Item = Windows.pop();
		Window_Item.parentNode.removeChild(Window_Item);
		
		if (Windows.length)
			Show_Lightbox();
		else
			Hide_Lightbox();
	}
}
// TODO : Fix in php and xml instead.
function Close_Top_Window(){Hide_Window();}

// Display a translucent lightbox in the highest layer of the site.
function Show_Lightbox()
{
	var Lightbox_Item = document.getElementById("Lightbox");
	
	// Generate lightbox if it doesn't exist.
	if (!Lightbox_Item)
	{
		Lightbox_Item = Generate_Control("Lightbox");
		Body_Item = document.getElementById("Body");
		Body_Item.appendChild(Lightbox_Item);
	}

	// Display lightbox right beneath highest window.
	Lightbox_Item.style.zIndex = 500 + Windows.length * 2;	
	Lightbox_Item.style.display = "block";
}

// Hide lightbox.
function Hide_Lightbox()
{
	document.getElementById("Lightbox").style.display = "none";
}

// TODO: Show an item inside an container element will revert to its original content when hidden.
function Show_Inline(Parameters)
{
}

// TODO: Revert a container element to its original content.
function Hide_Inline(Parameters)
{	
}

// Show an element or URL in a window or in place.
function Show(Parameters)
{		
	Type = Parameters["Type"];		
	switch (Type)
	{
		case "Window":
			Show_Window(Parameters);
			break;
			
		case "Inline":
			Show_Inline(Parameters);
			break;
			
		case "Menu":
			Show_Simple_Menu(Parameters);
			break;
		
		case "Lightbox":
			Show_Lightbox();
			
		default:
			Show_Element = Parameters["Element"];
			if (!Show_Element)
				Show_Element = document.getElementById(Parameters["ID"]);
			Show_Element.style.display = "block";
			break;
	}
}

// Hide an element, remove the element from the document tree if specified.
function Hide(Parameters)
{
	Hide_Element = Parameters["Element"];
	if (!Hide_Element)
		Hide_Element = document.getElementById(Parameters["ID"]);
		
	if (Hide_Element)
	{
		if (Parameters['Remove_Element'])
			Hide_Element.parentNode.removeChild(Hide_Element);
		else
			Hide_Element.style.display = "none";
	}
}

// Generate a faint shadow for an element with a specified width.
function Generate_Shadow(Parameters)
{		
	Shadow_Target_Element = Parameters["Element"];
	if (!Shadow_Target_Element)
		Shadow_Target_Element = document.getElementById(Parameters["ID"]);
	
	var Element_Position = Find_Position(Shadow_Target_Element);
	var Element_Size = Find_Size(Shadow_Target_Element, 1);						
	var Shadow_Width = 4;
	
	// Create shadow elements.		
	var Shadow_Parts = [
		{
			"ID": "Container"			
		},
		{
			"ID":"Right",
			"Parent_ID": "Container",
			"Top": Element_Position[1] + Shadow_Width + "px",
			"Left": Element_Position[0] + Element_Size[0] +"px",
			"Height": Element_Size[1]  - Shadow_Width + "px",
			"Class": "Shadow_Element Shadow_Right",
		},
		{
			"ID":"Bottom",
			"Parent_ID": "Container",
			"Top": Element_Position[1]  + Element_Size[1] + "px",
			"Left": Element_Position[0] + Shadow_Width + "px",
			"Width": (Element_Size[0] )  - Shadow_Width + "px",
			"Class": "Shadow_Element Shadow_Bottom",
		},
		{
			"ID":"Bottom_Right",
			"Parent_ID": "Container",
			"Top": Element_Position[1]  + Element_Size[1] + "px",
			"Left": Element_Position[0] + Element_Size[0] + "px",
			"Class": "Shadow_Element Shadow_Bottom_Right",
		},
	];
		
	for (var Shadow_Part_Index in Shadow_Parts)
	{
		var Shadow_Part = Shadow_Parts[Shadow_Part_Index];
		
		var Shadow_Part_Element = document.createElement("div");
		
		Shadow_Part_Element.id = Shadow_Target_Element.id + "_Shadow_" + Shadow_Part["ID"];
		if (Shadow_Part["Class"])
			Shadow_Part_Element.className = Shadow_Part["Class"];
		Shadow_Part_Element.style.top = Shadow_Part["Top"];
		Shadow_Part_Element.style.left = Shadow_Part["Left"];
		Shadow_Part_Element.style.width = Shadow_Part["Width"];
		Shadow_Part_Element.style.height = Shadow_Part["Height"];
		
		if (Shadow_Part["Parent_ID"])
			Shadow_Parent_Element = document.getElementById(Shadow_Target_Element.id + "_Shadow_" + Shadow_Part["Parent_ID"]);
		else
			Shadow_Parent_Element = Shadow_Target_Element.parentNode;
		Shadow_Parent_Element.appendChild(Shadow_Part_Element);
	}
}

/* Design Editor Functions */

// Toggle between and Design and HTML modes in the design editor.
function Select_Design_Editor_Mode(Mode, Namespace)
{
	Synchronize_Design_Editor(Namespace);
	if (Mode == "Design")
	{
		document.getElementById(Namespace + "_Design_Tab").className = "Active_Tab Last_Tab";
		document.getElementById(Namespace + "_HTML_Tab").className = "Inactive_Tab";
		document.getElementById(Namespace + "_Design_Editor").style.display = "block";
		document.getElementById(Namespace + "_HTML_Editor").style.display = "none";
	}
	else
	{
		document.getElementById(Namespace + "_HTML_Tab").className = "Active_Tab";
		document.getElementById(Namespace + "_Design_Tab").className = "Inactive_Tab Last_Tab";
		document.getElementById(Namespace + "_HTML_Editor").style.display = "block";
		document.getElementById(Namespace + "_Design_Editor").style.display = "none";
	}		
}

// Synchronize data between Design and HTML modes in the design editor.
function Synchronize_Design_Editor(Namespace)
{	
	// Copy from Design mode to HTML mode.
	if (document.getElementById(Namespace + "_HTML_Tab").className == "Active_Tab")
		document.getElementById(Namespace + "_Design").innerHTML = document.getElementById(Namespace).value;
		
	// Copy from HTML mode to Design mode.
	else
	{
		document.getElementById(Namespace).value = Clean_HTML(document.getElementById(Namespace + "_Design").innerHTML, document.getElementById(Namespace).value);
	}
		
}

// Sets the size of the currently selected text in the design editor, hides the size menu.
function Set_Design_Editor_Size(Namespace, Size)
{
	var Size_Value;
	switch(Size)
	{
		case "huge":
			Size_Value = 7;
			break;
		case "large":
			Size_Value = 5;
			break;
		case "normal":
			Size_Value = 2;
			break;
		case "small":
			Size_Value = 1;
			break;
		default:
			break;
	}
	Set_Design_Editor_Style(Namespace, "fontsize", Size_Value);
	Hide_Simple_Menu();
}

// Sets the font of the currently selected text in the design editor, hides the font menu.
function Set_Design_Editor_Font(Namespace, Font)
{
	Set_Design_Editor_Style(Namespace, "fontname", Font);
	Hide_Simple_Menu();
}

function Set_Design_Editor_Style(Namespace, Style, Value)
{	
	document.execCommand(Style, null, Value);
	Synchronize_Design_Editor(Namespace);
}

/* Video Functions */

function Load_Video(Namespace, URL)
{
document.getElementById(Namespace + "_Video_Player").Load_Video(URL);
}

function Play_Video(Namespace)
{
document.getElementById(Namespace + "_Video_Player").Play_Video();

/*
var Video_Stop_Control = document.getElementById(Namespace + "_Video_Stop");
if (Video_Stop_Control)
	Video_Stop_Control.style.display = "block";

var Video_Play_Control = document.getElementById(Namespace + "_Video_Play");
if (Video_Play_Control)
	Video_Play_Control.style.display = "none";
*/
}

function Stop_Video(Namespace)
{
document.getElementById(Namespace + "_Video_Player").Stop_Video();

/*
var Video_Stop_Control = document.getElementById(Namespace + "_Video_Stop");
if (Video_Stop_Control)
	Video_Stop_Control.style.display = "none";

var Video_Play_Control = document.getElementById(Namespace + "_Video_Play");
if (Video_Play_Control)
	Video_Play_Control.style.display = "block";
*/
}

function Video_Update(Namespace, Update_Type, Update_Description, Bytes_Loaded, Bytes_Total)
{
Log("Video Update: " + Update_Type + ", " + Update_Description + ", " + Bytes_Loaded + ", " + Bytes_Total);
switch (Update_Type)
{
	case "Duration":
		break;
	case "Stop":
		break;
	case "Complete":
		break;
	case "Progress":
		break;
	case "Error":
		document.title = "Player error: " + Update_Description;
		break;
}
}


/* Miscellaneous Functions */

function Scope_Visible_Properties(Namespace)
{
	var Simple_Types = new Array("Boolean", "Data", "Date", "DateTime", "Number", "Password", "String", "Time");
	if (Simple_Types.indexOf(document.getElementById(Namespace + "_Value_Type").value) < 0)
	{
		// Complex types	
		document.getElementById(Namespace + "_Multiple_Row").style.opacity = "1";
		document.getElementById(Namespace + "_Inline_Row").style.opacity = "1";
		Ramp_Value({"Command": "document.getElementById(Namespace + \"_Multiple_Row\").style.opacity = VALUE / 10", "Start_Value": 3, "End_Value": 10});
		Ramp_Value({"Command": "document.getElementById(Namespace + \"_Inline_Row\").style.opacity = VALUE / 10", "Start_Value": 3, "End_Value": 10});
		
		document.getElementById(Namespace + "_Multiple").enabled = true;
		document.getElementById(Namespace + "_Inline").enabled = true;
		
		if (document.getElementById(Namespace + "_Multiple").checked)
		{
			//Multiple	
			document.getElementById(Namespace + "_Bidirectional_Row").style.opacity = "1";
			document.getElementById(Namespace + "_Commutative_Row").style.opacity = "1";
			
			document.getElementById(Namespace + "_Bidirectional").enabled = true;
			document.getElementById(Namespace + "_Commutative").enabled = true;
		}
		else
		{
			//Single
			document.getElementById(Namespace + "_Bidirectional_Row").style.opacity = ".3";
			document.getElementById(Namespace + "_Commutative_Row").style.opacity = ".3";

			document.getElementById(Namespace + "_Bidirectional").checked = false;
			document.getElementById(Namespace + "_Commutative").checked = false;
			
			document.getElementById(Namespace + "_Bidirectional").enabled = false;
			document.getElementById(Namespace + "_Commutative").enabled = false;
		}
	}
	else
	{
		//Simple types
		document.getElementById(Namespace + "_Multiple_Row").style.opacity = ".3";
		document.getElementById(Namespace + "_Inline_Row").style.opacity = ".3";
		document.getElementById(Namespace + "_Bidirectional_Row").style.opacity = ".3";
		document.getElementById(Namespace + "_Commutative_Row").style.opacity = ".3";
		
		document.getElementById(Namespace + "_Commutative_Row").style.height = "0px";

		document.getElementById(Namespace + "_Multiple").checked = false;
		document.getElementById(Namespace + "_Inline").checked = true;
		document.getElementById(Namespace + "_Bidirectional").enabled = false;
		document.getElementById(Namespace + "_Commutative").enabled = false;
		
		document.getElementById(Namespace + "_Multiple").enabled = false;
		document.getElementById(Namespace + "_Inline").enabled = false;
		document.getElementById(Namespace + "_Bidirectional").enabled = false;
		document.getElementById(Namespace + "_Commutative").enabled = false;
	}

}

/* Select Input Functions */

	var Select_Lists = new Object();	
	
	// Handle clicks for a select input.
	function Select_Item_Click(Namespace, List_Index)
	{	
		Select_Item_Select(Namespace, List_Index);
	}

	// Hide list, populate trigger item.
	function Select_Hide_List(Namespace,List_Index)
	{	
		Trigger_Item_Element = document.getElementById(Namespace + '_List_Item_0');			

		// If an item is specified, make sure the trigger item is updated to display the selected item.
		 if (List_Index)
		{
			// If the "none" item is specified, show add property title.
			if (List_Index == 2)
			{
				Trigger_Item_Content  = "<a href=\"#\" onclick=\"return false;\">Add " + Select_Lists[Namespace]["Name"];"</a>";
			}
			else
				Trigger_Item_Content = document.getElementById(Namespace + '_List_Item_' + List_Index).innerHTML;
				
			Trigger_Item_Element.innerHTML = Trigger_Item_Content;
		}
		
		// Display trigger item.
		Trigger_Item_Element.style.display = "list-item";
		
		// HIde the list items.
		List_Item_Count = Select_Lists[Namespace]["Items"].length;
		for (var List_Index = 1; List_Index < List_Item_Count; List_Index++)
		{
			document.getElementById(Namespace + "_List_Item_" + List_Index).style.display = "none";
		}
		
		// Display list behind other lists
		var Select_List_Element = document.getElementById(Namespace + "_Select_List");
		Select_List_Element.style.zIndex = "1";
		
		// Register status
		Select_Lists[Namespace]["Open"] = false;
	}
	
	function Select_Show_List(Namespace)
	{	
		Log("Show");
		
		// Hide trigger Item
		document.getElementById(Namespace + "_List_Item_0").style.display = "none";
		
		// Display each list item.
		List_Item_Count = Select_Lists[Namespace]["Items"].length;
		for (var List_Index = 1; List_Index < List_Item_Count; List_Index++)
		{
			Log(List_Index);
			document.getElementById(Namespace + "_List_Item_" + List_Index).style.display = "list-item";
		}
		
		// Display list above other lists.
		var Select_List_Element = document.getElementById(Namespace + "_Select_List");
		Select_List_Element.style.zIndex = "10";
		
		// Select the top item.
		Select_Item_Hover(Namespace, 1);
		
		// Register status
		Select_Lists[Namespace]["Open"] = true;
		
		// Register hide function.
		Document_Click_Function =  function(){Select_Hide_List(Namespace); Document_Click_Function = null;}
	}
	
	// On click or on enter key.
	function Select_Item_Select(Namespace, List_Index)
	{
		// If Create New... is selected, execute add action and return
		if (List_Index == 1)
		{
			Execute_Action_With_Parameters({'Action': 'Add', 'Namespace': Namespace + "_Add_" + Select_Lists[Namespace]["Value_Type"], 'Parameters': {'Add_Type': Select_Lists[Namespace]["Value_Type"]}});
			return;
		}

		// Populate the form with the Selected Item ID.
		Selected_Item_ID = Select_Lists[Namespace]["Items"][List_Index];
		document.getElementById(Namespace).value = Selected_Item_ID;
	
		// Hide List
		Select_Hide_List(Namespace, List_Index);
	}
		
	// Highlight an item in the search list either on mouse over or on arrow key selection.
	function Select_Item_Hover(Namespace, List_Index)
	{
		// Unhighlight hovered item
		Hovered_Index = Select_Lists[Namespace]["Hovered_Index"]
		if (Hovered_Index > 0)
		{
			List_Item_Element = document.getElementById(Namespace + "_List_Item_" + Hovered_Index);
			if (List_Item_Element)
//				List_Item_Element.className = "Select_List_Item";
				List_Item_Element.style.backgroundColor = "white";
		}
			
		// Highlight item
		List_Item_Element = document.getElementById(Namespace + "_List_Item_" + List_Index);
		if (List_Item_Element)
//			List_Item_Element.className = "Select_List_Item_Hover";
			List_Item_Element.style.backgroundColor = "#ddddff"
		
		// Register new hovered index.
		Select_Lists[Namespace]["Hovered_Index"] = List_Index;
	}	
	
	// Clear the list of items for a namespace.
	function Select_Register_List(Namespace, Name, Value_Type)
	{	
		Select_Lists[Namespace] = new Object({"Items":new Array(), "Name":Name, "Value_Type":Value_Type, "Hovered_Index": -1, "Open":false});
	}
	
	// Store a search item in the array for a namespace.	
	function Select_Register_Item(Namespace, ID)
	{
		Select_Lists[Namespace]["Items"].push(ID);
	}


/* Utility Functions */

// Parse HTML text into a DOM element.
function Parse_HTML_Text(HTML_Text)
{
//		var New_HTML_Text = "<div>" + HTML_Text + "</div>";
	var Elem = document.createElement("div");
	Elem.innerHTML = HTML_Text;
	return Elem.childNodes;
}

function Parse_HTML_Text_Better(HTML_Text)
{
	var New_HTML_Text = "<div>" + HTML_Text + "</div>";
	try
	{
		var XML_Document = new ActiveXObject("Microsoft.XMLDOM");
		XML_Document.async = "false";
		XML_Document.loadXML(New_HTML_Text);
	}
	catch (e)
	{
		try
		{
			var XML_Parser = new DOMParser();
			var XML_Document = XML_Parser.parseFromString(New_HTML_Text, "text/xml");
		}
		catch (e)
		{
			alert("Parse HTML message: " + e.message);
			return;
		}
	}
	
	// Return a collection of elements if necessary, otherwise return a single element.
	return XML_Document.documentElement.childNodes;
}

function Generate_Control(Control_ID)
{
	var Node_List = Parse_HTML_Text(Controls[Control_ID]);
//		Log(Node_List);
	return Node_List[0];
}

function Clean_HTML(Text, Original_Text)
{
	// Do not clean code unless it has changed
	if (Text == Original_Text)
		return Text;
	
	// Remove bad HTML
	Text = Text.replace(/<br class\="webkit-block-placeholder">/gi, "<br />");
	Text = Text.replace(/<span class="Apple-style-span">(.*)<\/span>/gi, 'document.getElementById1');
	Text = Text.replace(/<span style="font-weight: bold;">(.*)<\/span>/gi, '<b>document.getElementById1</b>');
	Text = Text.replace(/<span style="font-style: italic;">(.*)<\/span>/gi, '<i>document.getElementById1</i>');
	Text = Text.replace(/<span style="text-decoration: underline;">(.*)<\/span>/gi, '<u>document.getElementById1</u>');
	Text = Text.replace(/<font size="7">(.*)<\/font>/gi, '<h1>document.getElementById1</h1>');
	Text = Text.replace(/<font size="6">(.*)<\/font>/gi, '<h2>document.getElementById1</h2>');
	Text = Text.replace(/<font size="5">(.*)<\/font>/gi, '<h3>document.getElementById1</h3>');
	Text = Text.replace(/<font size="4">(.*)<\/font>/gi, '<h4>document.getElementById1</h4>');
	Text = Text.replace(/<font size="3">(.*)<\/font>/gi, '<h5>document.getElementById1</h5>');
	Text = Text.replace(/<font size="2">(.*)<\/font>/gi, 'document.getElementById1');
	Text = Text.replace(/<font size="1">(.*)<\/font>/gi, '<h7>document.getElementById1</h7>');
	Text = Text.replace(/ class="Apple-style-span"/gi, '');
	Text = Text.replace(/<span style="">/gi, '');
	Text = Text.replace(/<br>/gi, "<br />");
	
	/*
	// Format HTML
	var Node = Parse_HTML_Text_Better(Text);
	Text = Clean_Node_List(Node, "");
	*/
	
	return Text;
}

var Depth = 30;

function Clean_Node(Node, Indentation)
{
	Depth--;
	if (Depth == 0)
		return;
	
	if (Node.nodeType == 1 && Node.hasChildNodes)
	{
		var Text = "";
		
		if (Node.tagName == "br")
			return Indentation + "<br />";
		
		// Parse attributes
		var Node_Attributes = Node.attributes;
		var Attributes_Text = "";
		for (var Attribute_Index = 0; Attribute_Index < Node_Attributes.length; Attribute_Index++)
		{
			Child_Attribute = Node_Attributes[Attribute_Index];
			
			var Attribute_Name = Child_Attribute.nodeName
			var Attribute_Value = Child_Attribute.value;
			
			Attributes_Text += " ";
			Attributes_Text += Attribute_Name;
			Attributes_Text += "=";
			Attributes_Text += "\"";
			Attributes_Text += Attribute_Value;
			Attributes_Text += "\"";
		}
		
		Text += Indentation + "<" + Node.tagName + Attributes_Text + ">";
		
		Text += "\r";
		var Node_List = Node.childNodes;
		Text += Clean_Node_List(Node_List, Indentation);
		Text += Indentation + "</" + Node.tagName + ">"
		return Text;
	}
}

function Clean_Node_List(Node_List, Indentation)
{
	var Text = "";
	for (var Node_Index = 0; Node_Index < Node_List.length; Node_Index++)
	{
		var Child_Node = Node_List[Node_Index];
		if (Child_Node.nodeType == 3)
		{
			var Node_Text = Child_Node.nodeValue;
			Node_Text = Trim_String(Node_Text);
			if (Node_Text != "")
			{
				Text += Indentation + "\t" + Node_Text;
				Text += "\r";
			}
		}
		else
		{
			Text += Clean_Node(Child_Node, Indentation + "\t");
			Text += "\r";
		}
	}
	return Text;
}

function Trim_String(Text)
{
	var Text = Text.replace(/^\s+|\s+document.getElementById/g,"");
	if (Text == null)
		return "";
	return Text;
}

function Ramp_Value(Parameters)
{// Parameters: Command, Start_Value (default: 0), End_Value (default: 1), Duration (milliseconds, default: 500), Start_Time (default: now)
	
	var d = new Date();
	var Current_Time = d.getTime();
	if (!Parameters["Duration"])
		Parameters["Duration"] = 500;
	if (!Parameters["Start_Time"])
		Parameters["Start_Time"] = Current_Time;
	if (!Parameters["Start_Value"])
		Parameters["Start_Value"] = 0;
	if (!Parameters["End_Value"])
		Parameters["End_Value"] = 1;
	
	var Ramp_Value_Recursive = function()
	{
		var d = new Date();
		var Current_Time = d.getTime();
		
		var Partial = (Current_Time - Parameters["Start_Time"]) / Parameters["Duration"];
		if (Partial > 1)
			Partial = 1;
		Partial = (1 - Math.pow((1 - Partial), 4));
		
		var Value = Parameters["Start_Value"] + (Parameters["End_Value"] - Parameters["Start_Value"]) * Partial;
		
		var Command = Parameters["Command"];
		Command = Command.replace(/VALUE/g, Value);
		try
		{
//				Log(Command);
			eval(Command);
		}
		catch(Error)
		{
		}
		
		if (Partial < 1)
			setTimeout(Ramp_Value_Recursive, 0);
		else
			if (Parameters["On_Complete"])
				Parameters["On_Complete"]();
	}
	
	setTimeout(Ramp_Value_Recursive, 0);
}

function Find_Scroll_Position()
{
	Scroll_Left = 0;
	Scroll_Top = 0;
	if (pageXOffset)
	{
		Scroll_Left = pageXOffset;
		Scroll_Top = pageYOffset;
	}	
	else if (document.documentElement)
	{
		Scroll_Left = document.documentElement.scrollLeft;
		Scroll_Top = document.documentElement.scrollTop;
	}
	else if (document.body)
	{
		Scroll_Left = document.body.scrollLeft;
		Scroll_Top = document.body.scrollTop;
	}
	
	return [Scroll_Left, Scroll_Top];
}

function Find_Position(Current_Object)
{
	var Current_Left = 0;
	var Current_Top = 0;
	if (Current_Object.offsetParent)
	{
		do
		{
			Current_Left += Current_Object.offsetLeft;
			Current_Top += Current_Object.offsetTop;
		}
		while (Current_Object = Current_Object.offsetParent);
	}
	return [Current_Left, Current_Top];
}

function Find_Input_Cursor_Position(Current_Object)
{
	var Selection_Start, Selection_End, Selection_Left, Selection_Top;
	
	if(document.selection)
	{
		// TODO: Internet Explorer. You can get left and top directly!
	
		Selection_Start = 0;
		Selection_End = 0;
//		Selection_Left = 0;
//		Selection_Top = 0;
	}
	else if(Current_Object.setSelectionRange)
	{
		Selection_Start = Current_Object.selectionStart;
		Selection_End = Current_Object.selectionEnd;
		var Selection_Last_Line_Break = Current_Object.value.substr(0,Selection_Start).lastIndexOf('\n');
		
		//TODO: tee hee there's just no good way to get top and left, what was i thinking
		var Current_Object_Position = Find_Position(Current_Object);
		var Current_Object_Style = window.getComputedStyle(Current_Object, null);		
		var Current_Object_Font_Size = Current_Object_Style.getPropertyValue("font-size");
		var Current_Object_Font_Family = Current_Object_Style.getPropertyValue("font-family");
		
		//TODO: clean up tabs with computed "text-indent", account for scrollbar size. :( 
		var Cursor_Size_Element = document.createElement("div");
		Cursor_Size_Element.id = "Cursor_Size_Element";
		Cursor_Size_Element.style.position="absolute";
		Cursor_Size_Element.style.left="-1000px";
		Cursor_Size_Element.style.top="1000px";
		Cursor_Size_Element.style.border ="solid 1px black";
		Cursor_Size_Element.style.fontSize = Current_Object_Font_Size;
		Cursor_Size_Element.style.fontFamily = Current_Object_Font_Family;
		document.getElementById("Body").appendChild(Cursor_Size_Element);
		
		Current_Object_Value = Current_Object.value.substring(Selection_Last_Line_Break,Selection_Start).replace(/\t/g,"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;").replace(/\s/g,"&nbsp;").replace(/</g,'&lt;').replace(/>/g,'&gt;');
		Cursor_Size_Element.innerHTML = Current_Object_Value;
		Selection_Left = (Cursor_Size_Element.offsetWidth % Current_Object.offsetWidth)+ Current_Object_Position[0] - Current_Object.scrollLeft;
		
		Current_Object_Value = Current_Object.value.substring(0,Selection_Start).replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\n/g,'<br/>').replace(/\s/g,"&nbsp;");
		Cursor_Size_Element.innerHTML = Current_Object_Value;
		Cursor_Size_Element.style.width = Current_Object.offsetWidth + "px";
		Selection_Top = Cursor_Size_Element.offsetHeight + Current_Object_Position[1] - Current_Object.scrollTop;
		
		document.getElementById("Body").removeChild(Cursor_Size_Element);
	}
	else 
		return false;
	
	return [Selection_Start, Selection_End, Selection_Left, Selection_Top];
}

// TODO: Test, make work reliably
function Find_Size(Current_Element, Levels)
{
	var Current_Width = 0;
	var Current_Height = 0;
	Current_Width = Current_Element.offsetWidth;
//	Log("WID: " + Current_Width);
	Current_Height = Current_Element.offsetHeight;
	
	if (Levels > 0 && Current_Element.style.display != "block")
	{
//		Log(Current_Element.childNodes.length);
		for (var Child_Index = 0; Child_Index < Current_Element.childNodes.length; Child_Index++)
		{
			var Current_Child = Current_Element.childNodes[Child_Index];
			
			if (Current_Child.nodeType == 1)
			{
				var Child_Size = Find_Size(Current_Child, Levels - 1);
				if (Child_Size[0])
					Current_Width = Math.max(Current_Width, Current_Child.offsetLeft - Current_Element.offsetLeft + Child_Size[0]);
				if (Child_Size[1])
					Current_Height = Math.max(Current_Height, Current_Child.offsetTop - Current_Element.offsetTop + Child_Size[1]);
			}
			
		}
	}
	return [Current_Width, Current_Height];
}

window.size = function()
{
	var w = 0;
	var h = 0;

	//IE
	if(!window.innerWidth)
	{
		//strict mode
		if(!(document.documentElement.clientWidth == 0))
		{
			w = document.documentElement.clientWidth;
			h = document.documentElement.clientHeight;
		}
		//quirks mode
		else
		{
			w = document.body.clientWidth;
			h = document.body.clientHeight;
		}
	}
	//w3c
	else
	{
		w = window.innerWidth;
		h = window.innerHeight;
	}
	return {width:w,height:h};
}