
//// THIRD_LEVEL ///////////////////////////////////////////////////////////////
//	
//	--[ xMenuManager ]------------------------------------------------------
//	version 0.0.3.0				date 29.11.2005
//	author sebastian 'xenon' goendoer	copyright by xenon | third_level
//	------------------------------------------------------------------------
//	
////////////////////////////////////////////////////////////////////////////////
//	
//	!!! this is NOT free software !!!
//	if you like to use this script for your own website, you can contact
//	third_level via http://www.3rd-level.org/xenon
//	
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////
// vars
////////////////////////////////

// keep open feature // set to false if you want to disable this feature
var keepMenuOpen = true;

// set to true for debugging // set to true if you want to debug sth
var verbose = false;

// !!! DO NOT EDIT BELOW !!! ///////////////////////////////////////////////////

// openMenuArray[] registeres all current menu objects
var openMenuArray = new Array();

// the level of the last menu
var maxMenuLevel = 0;

// the menuObject
var menuObject;

// eventhandler for window.document to close all menus
document.onclick = handleDocumentOnClick;
document.onrightclick = handleDocumentOnClick;
document.ondblclick = handleDocumentOnClick;

// needed to block close event on menus
var blockCloseEvent = false;

////////////////////////////////
// CMenuObject
////////////////////////////////

// function CMenuObject() //////////////////////////////////////////////////////
// constructor
function CMenuObject(id, level)
{
	// the menuID
 	this.menuID = id;
	
	// the level of the menu
	this.menuLevel = level;
	
	// add eventhandler onClick, onRightClick, onDblClick
	window.document.getElementById(this.menuID).onclick = handleMenuOnClick;
	window.document.getElementById(this.menuID).onrightclick = handleMenuOnClick;
	window.document.getElementById(this.menuID).ondblclick = handleMenuOnClick;
	
	// binding method closeMenu() to the object
	this.closeMenu = closeMenu;
}

// function closeMenu() ////////////////////////////////////////////////////////
// closes the given menu
function closeMenu()
{
	// if openMenuArray[this.level].menuID != this.menuID sth went wrong
	if(openMenuArray[this.menuLevel].menuID != this.menuID)
	{
		closeAllMenus();
		if(verbose) alert("error! cannot close another menu");
	}
	
	// if this isnt the highest menu, we need to close all child menus recursiv
	if(this.menuLevel > maxMenuLevel)
	{
		openMenuArray[this.menuLevel + 1].closeMenu();
	}
	window.document.getElementById(this.menuID).style.display = "none";
	openMenuArray[this.menuLevel] = undefined;
}

// end CMenuObject /////////////

////////////////////////////////
// global functions
////////////////////////////////

// function openMenu() /////////////////////////////////////////////////////////
// opens the menu
function openMenu(menuID, menuLevel)
{
	// prevent working with non existing menus
	if(!window.document.getElementById(menuID))
	{
		return false;
	}
	
	// create menu object
	menuObject = new CMenuObject(menuID, menuLevel);
	
 	// prevent re-opening an open menu
	if(openMenuArray[maxMenuLevel] && openMenuArray[maxMenuLevel].menuID == menuObject.menuID)
	{
		return false;
	}

	// check if the menu exists
	if(window.document.getElementById(menuObject.menuID) == undefined)
	{
		if(verbose) alert("error! not existing menu");
		return false;
	}
	
	// if this happens, something went wrong and we need to close all menus
	if(maxMenuLevel < menuLevel-1)
	{
		for(key in openMenuArray)
		{
			openMenuArray[key].closeMenu();
		}
		maxMenuLevel = 0;
		if(verbose) alert("error! menu has no parent menu");
		return false;
	}
	
	// if menus of the same level or above are open, we need to close each one
	if(maxMenuLevel >= menuLevel)
	{
		// running backwards through openMenuArray closing the open menus
		for(var i=maxMenuLevel; i>=menuLevel; i--)
		{
			openMenuArray[i].closeMenu();
			maxMenuLevel--;
		}
	}
	
	// now we can register the new menu
	openMenuArray[menuLevel] = menuObject;
	maxMenuLevel++;
	
	// we need to check if the new menu would clip with the browser window or else
	// %TODO% detection of overlapping menus
	// %TODO% detection of menu displayed off window boundries
	// %TODO% recalibrating menu if neccessary
	
	// now we can open the menu
	slideOpen(menuObject.menuID, 0, 0, 300, 300);
	if(verbose)
	{
		alert("verbose information:\n____________________________________________\n\nmaxMenuLevel: " + maxMenuLevel + "\nopenMenuArray: " + openMenuArray + "\nLevel of this menu: " + menuLevel + "\n____________________________________________\n");
	}
}

// event handling functions ////////////////////////////////////////////////////
// event handling for menus
function handleMenuOnClick()
{
	blockCloseEvent = true;
}

// event handling for document
function handleDocumentOnClick()
{
	if(blockCloseEvent == false)
	{
		closeAllMenus();
	}
	blockCloseEvent = false;
}

// function closeAllMenus() ////////////////////////////////////////////////////
// closes all menus registered in openMenuArray[]
function closeAllMenus()
{
	// we run backwards trough openMenuArray[] closing each one
	for(var i=maxMenuLevel; i>=1; i--)
	{
		openMenuArray[i].closeMenu();
		maxMenuLevel--;
	}
}

// function slideOpen() ////////////////////////////////////////////////////////
//slides the menu open that is given by menuID
var menuID;
var currentHeight;
var currentWidth;
var maxHeight;
var maxWidth;

function slideOpen(menuID, currentHeight, currentWidth, maxHeight, maxWidth)
{
	if(currentHeight == 0)
	{
		window.document.getElementById(menuID).style.display = "block";
	}
	
	if(currentHeight <= maxHeight || currentWidth <= maxWidth)
	{
		// increase the width and height to set
		currentHeight+=10;
		currentWidth+=10;
		
		// apply new width and height values
		window.document.getElementById(menuID).style.clip = "rect(auto, " + currentHeight + "px, " + currentWidth + "px, auto);";
		
		// recursive call of slideOpen()
		timer = setTimeout("slideOpen('" + menuID + "', " + currentHeight + ", " + currentWidth + ", " + maxHeight + ", " + maxWidth + ");", 0);
	}
}

// function keepOpen() /////////////////////////////////////////////////////////
// slides the menu open that is given by menuID
function keepOpen(menuID, menuLevel)
{
	// if the keep open feature is disabled, we need to exit now
	if(keepMenuOpen == false)
	{
		return false;
	}
	
	// if a menu is opened atm, we can open all other menues onMouseOver
	if(maxMenuLevel > 0)
	{
		openMenu(menuID, menuLevel);
	}
}

////////////////////////////////////////////////////////////////////////////////
//	
//	--[ version history ]---------------------------------------------------
//	-- 0.0.3.0 -- 29.11.2005 ----------
//		- added eventhanding to close all menus on click
//		- fixed 
//	-- 0.0.2.1 -- 29.11.2005 ----------
//		- fixed check if opening menu is valid
//	-- 0.0.2.0 -- 28.11.2005 ----------
// 		- added keepOpen feature
//		- added check to prevent re-opening an already open menu
//	-- 0.0.1.0 -- 25.11.2005 ----------
// 		- first release
//
//	--[ todo and bugs ]-----------------------------------------------------
//	-	make menus slideable in all directions in selectable speeds
//	-	implement proper browser detection
//	-	need to test functionality with several other browsers
//	-	implement workaround for several browsers
//	-	bug: level 1 menus re-opening on click because vars are reseted by
//		some reason
//
//	--[ browser compatibility ]---------------------------------------------
//	--	fully compatible
//		- firefox 1.5 windows
//		- firefox 1.0 mac os x
//		- firefox 1.0 linux
//	--	working, but with problems
//		- internet explorer 6.0 windows
//		- opera 8.5 windows
//		- safari ?.? mac os x
//	--	not working at all
//		- N/A
//
////////////////////////////////////////////////////////////////////////////////

