var Dependencies = new Object();
var Dependencies_By_Namespace = new Object();

var Focused_Action_Namespace = "";
var Last_Path = "";
var Last_Path_Item_Namespace;
var Default_Path = "Site/Default_Page";
					
var Directory;
//TODO: Directory_Set
var Directory_Set = false;

var Fills = new Object();

function Start_Jelly(New_Directory)
{
	Directory = New_Directory;
	Directory_Set = true;
		
	// Watch address bar
	setInterval("Watch_Address_Bar();", 100);
	
	// Write flash element for special case features.
	Body_Item = document.getElementById("Body");
	Flash_Container_Item = Generate_Control("Flash");
	Body_Item.appendChild(Flash_Container_Item);
	
	var Flash_Vars = {};
	var Flash_Params = {"wmode": "transparent"};
	var Flash_ID = {id : "Jelly_Flash_Audio_Player"};
	swfobject.embedSWF(Directory + "/jelly/Flash/Jelly_Flash_Audio_Player.swf", "Jelly_Flash_Audio_Player_Container", "1", "1", "9.0.0", "/jelly/Flash/expressInstall.swf", Flash_Vars, Flash_Params, Flash_ID);

	
}

// Gather namespaced parameters from the document and submit an ajax request.
function Execute_Action(Namespace)
{
	Log(Namespace);
	// Prepare namespace and action parameters.
	var Parameters = new Object();
	Parameters["Namespace"] = Namespace;
	Log(document.getElementById(Namespace + "_Action").value);
	Parameters["Action"] = document.getElementById(Namespace + "_Action").value;
	Parameters["Parameters"] = new Object();
	
	// Gather parameters from namespaced input elements.
	var Inputs = document.getElementsByTagName("input");
	for (var InputIndex = 0; InputIndex < Inputs.length; InputIndex++)
	{
		if (Inputs[InputIndex].id.substring(0, Namespace.length) == Namespace)
		{
			if (Inputs[InputIndex].type == "checkbox")
			{
				if (Inputs[InputIndex].checked)
					Parameters["Parameters"][Inputs[InputIndex].name] = "1";
				else
					Parameters["Parameters"][Inputs[InputIndex].name] = "0";
			}
			else
				Parameters["Parameters"][Inputs[InputIndex].name] = Inputs[InputIndex].value;
		}
	}
		
	// Gather parameters from namespaced select elements.
	var Inputs = document.getElementsByTagName("select");
	for (var InputIndex = 0; InputIndex < Inputs.length; InputIndex++)
		if (Inputs[InputIndex].id.substring(0, Namespace.length) == Namespace)
			Parameters["Parameters"][Inputs[InputIndex].name] = Inputs[InputIndex].value;
	
	
	// Gather parameters from namespaced textarea elements.
	var Inputs = document.getElementsByTagName("textarea");
	for (var InputIndex = 0; InputIndex < Inputs.length; InputIndex++)
		if (Inputs[InputIndex].id.substring(0, Namespace.length) == Namespace)
			Parameters["Parameters"][Inputs[InputIndex].name] = Inputs[InputIndex].value;

	// Submit an AJAX request
	Execute_Action_With_Parameters(Parameters);
}

// Submit an AJAX request with the given parameters.
function Execute_Action_With_Parameters(Parameters)
{
	// TODO: ?
	if (Parameters["Namespace"])
		Namespace = Parameters["Namespace"];
	else
		Namespace = "Action";
		
	// Show named "_Loading" status indicator for the action, if it exists.
	var LoadingElement = document.getElementById(Namespace + "_Loading");
	if (LoadingElement)
		LoadingElement.style.display = "inline";		
	
	// Prepare POST parameters.
	Post_Parameters = "";
	Post_Parameters += "&" + "Submit_Action" + "=" + Parameters["Action"];
	Post_Parameters += "&" + "Submit_Namespace" + "=" + Namespace;
	Post_Parameters += "&" + "Submit_Method" + "=" + "AJAX";
	
	for (var Parameter_Index in Parameters["Parameters"])
		Post_Parameters += "&" + (Namespace + "_" + Parameter_Index) + "=" + encodeURIComponent(Parameters["Parameters"][Parameter_Index]);
	Post_Parameters = Post_Parameters.replace("+", "%2B");
	
	var URL = Directory + "/";
	
	// Submit form data to the server asynchronously.
	AJAX_Request(
		{
			URL: URL,
			Post_Variables: Post_Parameters,
			Callback: function (HTTP_Request)
				{	
					var Result = HTTP_Request.responseText;
					
					// Display response in the named "_Result" container for this action, if it exists.
					var Result_Div = document.getElementById(Namespace + "_Result");
					if (Result_Div)
						Result_Div.innerHTML = Result;
						
					// Evaluate response javascript, including registering changed items.
					Execute_Scripts(Result);
					
					// Hide named "_Loading" status indicator for this action, if it exists.
					var LoadingElement = document.getElementById(Namespace + "_Loading");
					if (LoadingElement)
						LoadingElement.style.display = "none";
						
					// Update elements dependent on changed items.
					Refresh_Fills();
				}
		}
	)
}

// Register action in focus.
function Set_Focused_Action_Namespace(Namespace)
{
	Focused_Action_Namespace = Namespace;
}

// Execute focused action. (for example, on enter key)
function Execute_Focused_Action()
{
	Execute_Action(Focused_Action_Namespace);
}

// Execute focused action on enter key.
function Handle_Input_Key_Down(e)
{
	var code;
	if (!e) var e = window.event;
	if (e.keyCode) code = e.keyCode;
	else if (e.which) code = e.which;
	var character = String.fromCharCode(code);
	if (code == 13)
	{
		Execute_Focused_Action();
		return false;
	}
	return true;
}

// Check for path changes after the anchor character and register change.
function Watch_Address_Bar()
{
	// Parse path by reading the URL after the anchor character and trimming the trailing backslash.
	var Current_Path = document.location.href;
	if (Current_Path.substring(Current_Path.length - 1) == "/")
		Current_Path = Current_Path.substring(0, Current_Path.length - 1);		
	var Pound_Position = Current_Path.indexOf("#");
	if (Pound_Position > -1)
		Current_Path = Current_Path.substring(Pound_Position + 1);
	
	// If no path is specified, set a default path.
	if (Current_Path == "" || Pound_Position == -1)
		Current_Path = Default_Path;
	
	// If the URL has changed since last check, register change.
	if (Current_Path != Last_Path)
	{
		Last_Path = Current_Path;
		
		// Clean current path, set a default path if necesary.
		Current_Path = Current_Path.replace(/\/*document.getElementById/g, "");		
		if (Current_Path == "")
			var Current_Path = Default_Path;
		
		// Register changed URL.
		Item_Changed("Last_Path_Item");
		
		// Refresh elements dependent on the URL.
		Refresh_Fills();
	}
}

// Set the address bar to the new path with a preceding anchor character.
function Set_Location(New_Path)
{
	var Pound_Position = New_Path.indexOf("#");
	if (Pound_Position != -1)
		New_Path = New_Path.substring(Pound_Position + 1);
	document.location.href = "#" + New_Path;
}

function Reload_Page()
{
	document.location.reload();
}

// Evaluate all <script></script> tags in text chunk.
function Execute_Scripts(HTML_Text)
{
	Get_Script_Tags_From_HTML_Text = new RegExp('<script[^>]*>([^]*?)<\/script>', 'img');
	Get_Code_From_Script_Tag = new RegExp('<script[^>]*>([^]*?)<\/script>', 'im');
	Script_Tags = (HTML_Text.match(Get_Script_Tags_From_HTML_Text));
	for (var Script_Tag_Index in Script_Tags)
	{
		// TODO: Not sure why, but a naming conflict with prototype returns the function Enumerable at the end of the array returned by match.
		// I wrote a typeof check to ensure compatibility with prototype, but this is weird.
		if (typeof(Script_Tags[Script_Tag_Index]) == "string")
			eval(("" + Script_Tags[Script_Tag_Index]).match(Get_Code_From_Script_Tag)[1]);
	}
}


// Form a POST request to the server and run a Callback function on response.
function AJAX_Request(Parameters)
{
	var URL = Parameters["URL"];
	var Callback = Parameters["Callback"];
	var Post_Variables = Parameters["Post_Variables"];
	var Target_Element = Parameters["Target_Element"];
	if (!Target_Element) Target_Element = document.getElementById(Parameters["Target_Element_ID"]);
		
	var HTTP_Request = new XMLHttpRequest();
	HTTP_Request.open("POST", URL, true)
	HTTP_Request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
	HTTP_Request.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
	HTTP_Request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=UTF-8');
	HTTP_Request.onreadystatechange = function() 
	{
		if (HTTP_Request.readyState == 4 && HTTP_Request.status == 200)
		{
			Callback.call(null,HTTP_Request);
		}
	};
	HTTP_Request.send(Post_Variables);
}

// Fill a target element with a url by performing an AJAX request, performing transition effects, and registering dependencies.
function Fill(Parameters)
{
	var Response_Function = Parameters["Response"];
	var Show_Loading = Parameters["Show_Loading"];
	var Transition = Parameters["Transition"];	
	var Not_From_Last_Path_Item = Parameters["Not_From_Last_Path_Item"];
	var Target_Element = Parameters["Element"];
	var Destination_URL = Parameters["URL"];
	if (!Target_Element) Target_Element = document.getElementById(Parameters["ID"]);
	if (!Target_Element) return;
	
	// Parse URL into location, item, and parameters.
	var URL_Parts = Destination_URL.split("/");
	Location_URL = (URL_Parts.slice(0,URL_Parts.length - 1) || []).join("/");
	URL_Parts = URL_Parts.pop().split(":");
	Item_URL = URL_Parts[0];
	Parameter_URL = URL_Parts[1];
		
	// Process location.
	if (!Location_URL)		
	   Location_URL = Directory;
	  
	// Process parameters.
	if (Not_From_Last_Path_Item)
		Parameter_URL += ",From_Last_Path_Item=1";
	
	// Rebuild URL.
	Destination_URL = Location_URL + "/" + Item_URL + ":" + Parameter_URL;		
	
	// Register dependency between element and URL.
	Add_Dependency({"Namespace": Target_Element.id, "URL": Destination_URL});	
	
	// Begin size transition effect.
	Transition = "None";
	if (Transition != "None")
	{
		var Original_Display = Target_Element.style.display;
		Target_Element.style.display = "block";
		Log("1:" + Target_Element.id);
		Log("1:" + Target_Element.offsetWidth);
		
		var Start_Width = Target_Element.offsetWidth;
		var Start_Height = Target_Element.offsetHeight;
		
		var Original_Overflow = Target_Element.style.overflow;
		Target_Element.style.overflow = "hidden";
		var Original_Height = Target_Element.style.height;
		Target_Element.style.height = Start_Height + "px";
		
		var Destination_Element = document.createElement("div");
		Destination_Element.id = Target_Element.id + "_Content";
		Destination_Element.style.position = "absolute";
		Destination_Element.style.visibility = "hidden";
		Destination_Element.style.width = Target_Element.offsetWidth + "px";
		Target_Element.parentNode.insertBefore(Destination_Element, Target_Element);
	}	
	
	// Begin loading transition effect.
	if (Show_Loading != "False")
	{
		var Loading_Element = document.getElementById(Target_Element.id + "_Loading");
		if (!Loading_Element)
		{
			Loading_Element = Generate_Control("Loading");
			Loading_Element.id = Target_Element.id + "_Loading";
		}
//		Log("ID" + Target_Element.id);
		Target_Size = Find_Size(Target_Element, 3);
//		document.title = Target_Size[0] + ":" + Target_Size[1];
//		Log(Target_Size);
//		Loading_Element.style.width = Math.max(Target_Element.scrollWidth, 10) + "px";
		Loading_Element.style.width = Math.max(Target_Size[0], 10) + "px";
		
//		Log("Width: "  +Target_Size[0]);
//		Log("Width1: " + Target_Element.offsetWidth);
//		Log("Width2: " + Target_Element.scrollWidth);
//		Log("Width: " + Loading_Element.style.width);
//		Loading_Element.style.height = Math.max(Target_Element.scrollHeight, 10) + "px";
		Loading_Element.style.height = Math.max(Target_Size[1], 10) + "px";
		Target_Element.parentNode.insertBefore(Loading_Element, Target_Element);	
	}
	
	// Perform AJAX request
	AJAX_Request(
		{
			URL: Destination_URL,			
			Callback: function (Request_Object)
				{
					var Result = Request_Object.responseText;
			
					// Fill target element.
					Target_Element.innerHTML = Result;
					
					// Finish loading transition effect.
					if (Show_Loading != "False")
						if (Loading_Element.parentNode)
							Loading_Element.parentNode.removeChild(Loading_Element);
						
					// Finish size transition effect.
					if (Transition != "None")
					{
						Destination_Element.style.width = Target_Element.offsetWidth + "px";
						Destination_Element.innerHTML = Result;
						var End_Width = Destination_Element.offsetWidth;
						var End_Height = Destination_Element.offsetHeight;
						Destination_Element.parentNode.removeChild(Destination_Element);
						
						Ramp_Value({"Command": "document.getElementById('" + Target_Element.id + "').style.height = VALUE + 'px';", "Start_Value": Start_Height, "End_Value": End_Height, "On_Complete": function () {Target_Element.style.overflow = Original_Overflow; Target_Element.style.height = Original_Height; Target_Element.style.display = Original_Display;}});
					}
					
					// Execute embedded javascript.
					Execute_Scripts(Result);
					
					// Execute callback function.
					if (Response_Function)
					{
						Response_Function.call();
					}
				}
		}
	);

}


// Refresh elements that are registered for updates and their dependent elements.
function Refresh_Fills()
{
	for (var Fill_Index in Fills)
	{
		var Updates = "";
		Fill_Element = Fills[Fill_Index];
		
		var Dependency = Fill_Element;
		var Already = false;
		while (Dependency)
		{
			if (Dependency["Parent_Namespace"])
			{
//				Log(Dependency["Parent_Namespace"]);
				Dependency = Dependencies_By_Namespace[Dependency["Parent_Namespace"]];
			}
			else
				Dependency = null;
			
			if (Dependency)
			{
				for (var Second_Fill_Index in Fills)
				{
					if (Fills[Second_Fill_Index]["Namespace"] == Dependency["Namespace"])
					{
						var Already = true;
						break;
					}
				}
			}
		}
		
		if (!Already)
		{
//			Log("FILL: " + Fill_Element["Namespace"]);
			if (Fill_Element["URL"])
			{
//				Log(Fill_Element["URL"]);
				Fill({"ID": Fill_Element["Namespace"], "URL": Fill_Element["URL"], "Not_From_Last_Path_Item": true});
				Updates += Fill_Element["Namespace"] + " >>> " + Fill_Element["URL"] + "\n\n";
			}
			else
			{
				Fill({"ID": Fill_Element["Namespace"], "URL": Directory + "/" + Last_Path + "/" + "Raw" + ":" + "Namespace" + "=" + Fill_Element["Namespace"] + ",From_Last_Path_Item=1"});
			}
			
			/*
			
				if (Dependency["Template"] != "HTML")
					Fill({"ID": Dependency["Namespace"], "URL": Request_URL + "/" + Dependency["Template"] + "/" + "Raw" + ":" + "Namespace" + "=" + Dependency["Namespace"]});
				else
					Fill({"ID": Dependency["Namespace"], "URL": Request_URL + "/" + "Raw" + ":" + "Namespace" + "=" + Dependency["Namespace"]});
			*/
		}
	}
	
	Fills = new Object();
}

// TODO: Que?
// Register a dependency between elements or between an element and an item.
function Add_Dependency(Dependency, Add_Handlers)
{
	var Object_Wrapper = document.getElementById(Dependency["Namespace"]);
	if (Object_Wrapper && Add_Handlers)
	{
		// Add event handlers
		Object_Wrapper.onmousemove = Handle_Hover;
		Object_Wrapper.oncontextmenu = Handle_Context_Click;
		Object_Wrapper.onclick = Handle_Context_Click;
		Object_Wrapper.className = "Namespace";
	}
	
	// Store dependency by its ID
	if (!Dependencies[Dependency["ID"]])
		Dependencies[Dependency["ID"]] = new Array();
	Dependencies[Dependency["ID"]].push(Dependency);
	
	// Store dependency by its namespace so parent lookups can be easily found
	if (Dependency["Namespace"])
	{	
		/// If dependency for this namespace already exists, copy the parent namespace to the new dependency.
		if (Dependencies_By_Namespace[Dependency["Namespace"]])	
		{
			Original_Dependency = Dependencies_By_Namespace[Dependency["Namespace"]];
			Dependency["Parent_Namespace"] = Original_Dependency["Parent_Namespace"];
		}
		Dependencies_By_Namespace[Dependency["Namespace"]] = Dependency;
	}
	
	// Fill Last_Path_Items
	if (Dependency["ID"] == "Last_Path_Item" && Directory_Set)
		Fill({"ID": Dependency["Namespace"], "URL": Directory + "/" + Last_Path + "/" + "Raw" + ":" + "Namespace" + "=" + Dependency["Namespace"] + ",From_Last_Path_Item=1"});
}

// Register elements that are dependent on an item in a list of elements to be refreshed.
function Item_Changed(Item_ID)
{
	var Dependency;
	Log("Changed: " + Item_ID);
	if (Dependencies[Item_ID])
	{
		for (var Item_Index in Dependencies[Item_ID])
		{
			Dependency = Dependencies[Item_ID][Item_Index];
			if (Dependency["Namespace"])
			{
//				Log("Starting at: " + Dependency["Namespace"]);
				while (Dependency)
				{
					if (Dependency["URL"] || Dependency["Template"])
					{
//						Log("Fill: " + Dependency["Namespace"]);
						Dependency_Element = document.getElementById(Dependency["Namespace"]);
						if (Dependency_Element)
						{
							Fills[Dependency["Namespace"]] = Dependency;
							Dependency = null;
						}
						else
						{
							if (Dependency["Parent_Namespace"])
								Dependency = Dependencies_By_Namespace[Dependency["Parent_Namespace"]];
							else
								Dependency = null;
						}
					}
					else
					{
						if (Dependency["Parent_Namespace"])
							Dependency = Dependencies_By_Namespace[Dependency["Parent_Namespace"]];
						else
							Dependency = null;
					}
				}
			}
		}
	}
}

function Upload_Cancel(Namespace)
{
	// TODO
//	document.getElementById(Namespace + "_Jelly_Flash_Uploader").Cancel_Upload();
}


// Periodically continue upload and display status until completed.
// TODO : This uploader doesn't work in flash 10, doesn't support cancel, acts strangely for multiple invocations, etc. Code needs to be entirely redone. Need to change on flash end.
var Full_Bar_Width = 300;
var Starting_Bar_Width = 60;
var Last_Bar_Width = Starting_Bar_Width;
function Upload_Update(Namespace, Update_Type, Update_Description, Bytes_Loaded, Bytes_Total, Result)
{		
	// TODO : Make sure Flash can communicate these values somehow.
	Uploader_Namespace = Namespace + "_Uploader";
	File_Name = "File.png";
	
	Log(Update_Type + ": "+ Update_Description + ", " + Bytes_Loaded + ", " + Bytes_Total + ", " + Result + " (" + Namespace + ")");
	
	switch (Update_Type)
	{	
		case "Start":
			Show_Uploader({"Namespace": Uploader_Namespace, "File_Name": File_Name});
			Last_Bar_Width = Starting_Bar_Width;
			break;
		case "Update":
			break;
		case "Complete":
			Hide_Window();
			Execute_Scripts(Result);
			Refresh_Fills();
			Close_Menus();
			break;
		case "Progress":
			Percentage = Math.floor(Bytes_Loaded / Bytes_Total * 100);
			document.getElementById(Uploader_Namespace + "_Uploader_Bar_Progress").innerHTML = Percentage;
						
			Current_Bar_Width = (Full_Bar_Width - Starting_Bar_Width) * (Bytes_Loaded / Bytes_Total) + Starting_Bar_Width;
			Ramp_Value({"Command": "document.getElementById(\"" + Uploader_Namespace + "_Uploader_Bar_Fill\").style.width = \"VALUEpx\"", "Start_Value": Last_Bar_Width, "End_Value": Current_Bar_Width, "On_Complete": function () {Last_Bar_Width = Current_Bar_Width;}, "Duration": 250});
			
			break;
		case "Error":
			Hide_Window();
			alert("Error: " + Update_Description);
			break;
	}
}







function Sound_Load(Track_URL)
{
	var Player = document.getElementById("Jelly_Flash_Audio_Player");
	if (!Player)
	{
		Sound_Update("Error", "No Player present.");
		return;
	}
	Player.Sound_Load(Track_URL);
}

function Sound_Play()
{
	var Player = document.getElementById("Jelly_Flash_Audio_Player");
	if (!Player)
	{
		Sound_Update("Error", "No Player present.");
		return;
	}
	Player.Sound_Play();
}

function Sound_Stop()
{
	var Player = document.getElementById("Jelly_Flash_Audio_Player");
	if (!Player)
	{
		Sound_Update("Error", "No player present.");
		return;
	}
	Player.Sound_Stop();
}

function Embed_Flash(Parameters)
{
	swfobject.embedSWF(Parameters["File"], Parameters["Placeholder"], Parameters["Width"], Parameters["Height"], Parameters["Version"], Parameters["Install"], Parameters["Vars"], Parameters["Params"], Parameters["ID"]);
}

function Sound_Update(Update_Type, Update_Description, Bytes_Loaded, Bytes_Total)
{
	Log(Update_Type + ": " + Update_Description + ", " + Bytes_Loaded + ", " + Bytes_Total);
	/*
	switch (Update_Type)
	{
		case "Play":
			document.getElementById('Player_Pause_Controls').style.display = "block";
			document.getElementById('Player_Play_Controls').style.display = "none";
			document.getElementById('Player_Pause_Controls_Small').style.display = "block";
			document.getElementById('Player_Play_Controls_Small').style.display = "none";
			break;
		case "Stop":
			document.getElementById('Player_Pause_Controls').style.display = "none";
			document.getElementById('Player_Play_Controls').style.display = "block";
			document.getElementById('Player_Pause_Controls_Small').style.display = "none";
			document.getElementById('Player_Play_Controls_Small').style.display = "block";
			break;
		case "Complete":
			Play_Next_Track();
			break;
		case "Progress":
			break;
		case "Error":
			document.title = "Player error: " + Update_Description;
			document.getElementById('Player_Pause_Controls').style.display = "none";
			document.getElementById('Player_Play_Controls').style.display = "block";
			document.getElementById('Player_Pause_Controls_Small').style.display = "none";
			document.getElementById('Player_Play_Controls_Small').style.display = "block";
			break;
	}
	*/
}

function Log(Text)
{
	if (window.console)
		console.log(Text);
}

function Create_Window(Name, Modal)
{
	var Lightbox_Div = document.getElementById("Lightbox");
	if (!Lightbox_Div)
	{
		Lightbox_Div = document.createElement("div");
		Lightbox_Div.style.position = "fixed";
		Lightbox_Div.style.left = "0px";
		Lightbox_Div.style.top = "0px";
		Lightbox_Div.style.width = "100%";
		Lightbox_Div.style.height = "100%";
		Lightbox_Div.style.backgroundColor = "black";
		Lightbox_Div.style.opacity = ".5";
		document.getElementById("Body").appendChild(Lightbox_Div);
	}
}

var Save_Menu = null;
var Base_Menu = new Object();
Base_Menu.id = "Base";
Save_Menu = Base_Menu;
function Create_Menu(Parameters)
{
	if (Parameters["Parent_Menu"])
		var Parent_Menu_Div = document.getElementById(Parameters["Parent_Menu"]);
	else
		Close_Menus();

	if (document.getElementById(Parameters["ID"]))
		return;
	
	var Menu_Div = document.createElement("div");
	Menu_Div.id = Parameters["ID"];
	Menu_Div.className = "Jelly_Menu_Wrapper";
	if (Parameters["From_Element"])
	{
		var From_Element = document.getElementById(Parameters["From_Element"]);
		Menu_Div.className += " " + From_Element.className;
//		Menu_Div.style = From_Element.style;
//		Log("HEJ");
		Parameters["HTML"] = From_Element.innerHTML;
	}
	if (Parameters["URL"])
	{
		Parameters["HTML"] = "<div class=\"Jelly_Menu\" id=\"" + Parameters["ID"] + "_Content\"><div style=\"padding: 3px;\">Loading</div></div>";
	}
	if (Parameters["Position"] == "Mouse")
	{
		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));
		Menu_Div.style.left = (Pointer_X - 5) + "px";
		Menu_Div.style.top = (Pointer_Y - 5) + "px";
	}
	else
	{
		if (Parent_Menu_Div)
		{
			var Parent_Position = Find_Position(Parent_Menu_Div);
			Menu_Div.style.left = (Parent_Position[0] + 50) + "px";
			Menu_Div.style.top = (Parent_Position[1] + 50) + "px";
		}
		else
		{
			if (Parameters["Attach"])
			{
				var Attach_Element = document.getElementById(Parameters["Attach"]);
				var Attach_Position = Find_Position(Attach_Element);
				Log(Attach_Position);
				Log(Attach_Element.offsetHeight);
				Menu_Div.style.left = (Attach_Position[0] - 3) + "px";
				Menu_Div.style.top = (Attach_Position[1] + Attach_Element.offsetHeight + 4) + "px";
			}
		}
	}
	Menu_Div.style.display = "block";
	Menu_Div.innerHTML = Parameters["HTML"];
	
	if (Parameters["Position"])
		Menu_Div.style.position = Parameters["Position"];
	
	Menu_Div.onclick = function()
	{
		Save_Menu = this;
	};
	Save_Menu = Menu_Div;
	
	if (Parent_Menu_Div)
		Parent_Menu_Div.Child_Menu = Menu_Div;
	else
		Base_Menu.Child_Menu = Menu_Div;
	
	document.getElementById("Body").appendChild(Menu_Div);
	
	if (Parameters["URL"])
	{
		Fill({"ID": Parameters["ID"] + "_Content", "URL": Parameters["URL"], "Response": function()
			{
				var Menu_Div = document.getElementById(Parameters["ID"]);
				var Menu_Position = Find_Position(Menu_Div);
				
				if (Menu_Div.offsetWidth - 5 > window.innerWidth)
				{
					Menu_Div.style.left = "5px";
					Menu_Div.style.width = (window.innerWidth - 10) + "px";
				}
				else
				{
					if (Menu_Position[0] + Menu_Div.offsetWidth + 5 > window.innerWidth)
						Menu_Div.style.left = (window.innerWidth - Menu_Div.offsetWidth - 5) + "px";
				}
				if (Menu_Div.offsetHeight - 5 > window.innerHeight)
				{
					Menu_Div.style.top = "5px";
					Menu_Div.style.height = (window.innerHeight - 10) + "px";
				}
				else
				{
					if (Menu_Position[1] + Menu_Div.offsetHeight + 5 > window.innerHeight)
						Menu_Div.style.top = (window.innerHeight - Menu_Div.offsetHeight - 5) + "px";
				}
			}
		});
	}
}

function Handle_Menu_Click()
{
	var Found_Menu = false;
	var Child_Menu = Base_Menu;

	while (Child_Menu)
	{
		if (Found_Menu)
			Child_Menu.parentNode.removeChild(Child_Menu);
		
		if (Save_Menu)
			if (Child_Menu.id == Save_Menu.id)
				Found_Menu = true;
		
		var New_Child_Menu = Child_Menu.Child_Menu;
		if (Found_Menu)
			Child_Menu.Child_Menu = null;
		Child_Menu = New_Child_Menu;
	}
	Save_Menu = Base_Menu;
}

function Handle_Menu_Key_Press(Event)
{
	// Escape
	if (Event.keyCode == 27)
	{
		Handle_Menu_Click();
	}
}

function Close_Menus()
{
	Save_Menu = Base_Menu;
	Handle_Menu_Click();
}





