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)
{

}

// Open the object's context menu on right or control click.
var Handle_Context_Click_Bubble = false;
function Handle_Context_Click(event)
{

}


/* 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.Type_Template_ID)
{
	var Item_Type = "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.Type_Template_ID + "','URL':'" + Directory +  "/Action/Edit/Raw:Namespace=" + Dependency.Namespace + "_Edit_" + Item_Type + "_" + Dependency.Type_Template_ID + ",Edit_Item_Type=" + Item_Type + ",Edit_Item_ID=" + Dependency.Type_Template_ID + "'}); return false;\">" + "Edit" + " <b>" + Dependency.Template + "</b> " + "Template for " + Dependency.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};
}





