/*
 POP-UP MENU CLASS (JAVASCRIPT)               ** KARL CASSAR  (LAST UPDATD 01/03/2007)
 
 How to use this class:
 ----------------------
 
 You need first to create an instance of the class in the HTML document where you want to use it.
 It's default name should be 'PM'.  However, if you wish to change it you can name the variable anything
 you like, as long as you change the instances 'popUpMenuName' property to the relevant name.
 
 E.g:   <script type="text/javascript">
			var MyPopUpMenu = new popUpMenu();
			MyPopUpMenu.popUpMenuName = 'MyPopUpMenu';
		</script>
		
 You can also specifiy it as the first parameter to the constructor:
		
 E.g:   <script type="text/javascript">
			var MyPopUpMenu = new popUpMenu('MyPopUpMenu');
		</script>

 Just a note, this is used for the 'SetTimeOut' function to call the relevant timerTick function, because the function is called as a global scope, i.e. which would be the [popupmenuname].timerTick(id);
 
 After creating the instance of the PopUpMenu, all the HTML elements that are part of this popupmenu
 must have an id tag (<ID>), and also a corresponding DIV element that will be shown when rolled over,
 that  has its id as "div_<ID>".
 
 E.g:  <td id="td_popup1">
 		...
		</td>
		...
		</body>
		<div id="div_td_popup1">
		...
		</div>
		
 The corresponding DIV element will be the shown element next to it, when it is clicked on.
 
 Also, all the HTML elements that will have a popup menu associated with them, and their corresponding
 DIV elements should have these events calling:
 
 	HTML_ELEM.onmouseclick/onmouseup/onmousedown (either choice) = "<popupmenu>.mouseClick([id])"
 	HTML_ELEM.onmouseover = "<popupmenu>.mouseOver([id])"
 	HTML_ELEM.onmouseout = "<popupmenu>.mouseOut([id])"
 	DIV_ELEM.onmouseover = "<popupmenu>.mouseOver([id])"
 	DIV_ELEM.onmouseout = "<popupmenu>.mouseOut([id])"
	
	[ID] must be the id of the HTML_ELEM or the DIV_ELEM.  In almost all cases, this can be replaced
	with a "this.id" to reference its own id.
	
E.g:
		<td id="pm1" onmouseout="PM.mouseOut(this.id);" 
				     onmouseover="PM.mouseOver(this.id);" 
					 onmouseup="PM.mouseClick(this.id);">
			<a>1</a>
		</td>	
		...
		</body>
		<div id="div_pm1" style="visibility:hidden;" 
		                  onmouseover="PM.mouseOver(this.id);"
						  onmouseout="PM.mouseOut(this.id);">
			...
		</div>
		
		Note that PM is the popup menu created in the beginning.  
		This could be any variable that you named. (See first section for more details on variable name)
		
	All the DIV elements should obviously have their visibility attribute set to hidden at start.
	Once all the events have been set for both DIV elements and the HTML elements,
	the popup menu is ready to go!
	
	Then simply call createMenu(itemID,divID) which will add the items to the menu
	for each item.  ItemID is the item's id, while divID is the ID of the panel to show
	next to the item.

	setParent(parent,child)
	
	Simply pass it as parameters the parent id and the child id, and the child id.  Once
	the parent id is hidden, all children are also hidden.
	
	

	
	These are several properties for fine-tuning the menu according to your needs:
		
		showDelay | hideDelay -> The timeout before the popup menu disappears after the 
		                        user has moved out the mouse or appears.
		                        Must be in multiples of 50ms. 
		popUpMenuName ->  The name of the variable used for the PopUpMenu.  See first section for more
						  details
		slideTo -> Where the popup menu slides.  Takes values of either:  right, left, top, bottom.
		spaceX ->  Wheter a space between the HTML element and the DIV should be left corresponding to the
					X-Axis.
		spaceY -> Same as spaceX, but in the Y-Axis.
		
		

*/

var allMenus = new Array();

function menu(id)
{
	this.leftTimeout = 0;
	this.showing = false;
	this.id = id
	this.counting_hide = false;
	this.counting_show = false;
	this.counting_showing = false;
	this.counting_hiding = false;
	this.startX = this.startY = this.endX = this.endY = this.currX = this.currY = 0;
	
	this.divElem = null;
}



function popUpMenu(name)
{
    var started = false;
	var menus = new Array();
	var INTERVAL = 50;
	if (name != null && name != '')
		this.popUpMenuName = name;
	else
		this.popUpMenuName = 'PM';
	this.hideDelay = 50 ; //multiples of interval only please
	this.showDelay = 50;
	this.slideSpeed = 1;
	this.slideTo = "right"; //right, left, top, bottom
	this.spaceX = this.spaceY = 1;
	var parent = new Array();
	
	this.setParent = function setParent(par,child)
	{
		
		parent[child] = par;
	}
	
	this.recalcLocation = function recalcLocation(id)
	{
	    var div = menus[id].divElem;
	    
	    offsetX = offsetY = 0;
		switch (this.slideTo)
		{
			case "top":
				offsetY -= div.clientHeight;
				break;
			case "left":
				offsetX -= div.clientWidth;
				break;
		}
		elem = getElem(id);
		
		switch (this.slideTo)
		{
			case "right": 
				offsetX += elem.clientWidth;
				offsetX += this.spaceX;
				break;
			case "bottom":
				offsetY += elem.clientHeight;
				offsetY += this.spaceY;
				break;
			case "top":
				offsetY -= this.spaceY;
				break;
			case "left":
				offsetX -= this.spaceX;
				break;
		}
		
		while (elem != null)
		{
			offsetX += elem.offsetLeft;
			
			offsetY += elem.offsetTop;
			elem = elem.offsetParent;
		}
		menus[id].endX = offsetX;
		menus[id].endY = offsetY;
		menus[id].currX = menus[id].endX;
		menus[id].currY = menus[id].endY;
		var x = document.getElementById(id);
		
		div.style.left = "" + offsetX + "px";
		div.style.top = "" + offsetY + "px";
		
	    
	}
	
	
	this.createMenu = function createMenu(id,divid)
	{
		var elem,offsetX,offsetY,div;
		div = getElem(divid);
		allMenus.push(id);
		
		
		if (div != null)
		{
			menus[id] = new menu(id);
			menus[id].divElem = div;
			this.recalcLocation(id);
			
			elem = getElem(id);
			
			
		}
		else
		{
			//alert('No DIV element defined for the element with id of [' + id + ']\n\n' +
			//      'ID of DIV element should be "' + divid + '"');	
			}
		started= true;
	}
	
	this.startSliding = function startSliding(id)
	{
	    if (!started) return;
		//sliding ready
		menus[id].counting_toshow = false;
		menus[id].counting_showing = false;
		
		menus[id].showing = true;
		menus[id].divElem.style.visibility = 'inherit';
	}
	
        
	this.startHiding = function startHiding(id)
	{
		menus[id].counting_showing = false;
		menus[id].counting_toshow = false;
		menus[id].count_toshow = 0;

		//sliding ready
		
		menus[id].counting_tohide = false;
		menus[id].counting_hiding = false;
		
		menus[id].showing = false;
		menus[id].divElem.style.visibility = 'hidden';
	}
	
	
	this.showMenu = function showMenu(id)
	{
	    if (!started) return;
		/*for (var i = 0; i < allMenus.length; i++)
			if (menus[allMenus[i]].showing)
				hideMenu(allMenus[i]);*/
		menus[id].counting_tohide = false;
		menus[id].counting_showing = false;
		menus[id].counting_hiding = false;
		
		menus[id].showing = false;
		if (this.showDelay > 0) 
		{
			menus[id].counting_toshow = true;
			menus[id].count_toshow = 0;
			menus[id].timerFunc = setTimeout(this.popUpMenuName + '.timerTick("' + id + '")',INTERVAL);
		}
		else
			this.startSliding(id);
		
	}
	
	this.hideMenu = function hideMenu(id)
	{
		if (this.hideDelay > 0)
		{
			menus[id].counting_tohide = true;
			menus[id].count_tohide = 0;
			menus[id].timerFunc = setTimeout(this.popUpMenuName + '.timerTick("' + id + '")',INTERVAL);
		}
		else
			this.startHiding(id);
		
	}
	
	this.resetTimeout = function resetTimeout(id)
	{
		menus[id].counting = false;
		if (menus[id].timerFunc != null)
		{
			clearTimeout (menus[id].timerFunc);
			menus[id].timerFunc = null;
		}
		menus[id].leftTimeout = this.timeout;
	}
	
	this.timerTick = function timerTick(id)
	{
	    if (!started) return;
		var retick = true;
		if (menus[id].counting_toshow)
		{
			menus[id].count_toshow += INTERVAL;
			if (menus[id].count_toshow >= this.showDelay) //Time to show elapsed
			{
				this.startSliding(id);
				retick = false;
			}
		}
		else if (menus[id].counting_tohide)
		{

			menus[id].count_tohide += INTERVAL;
			if (menus[id].count_tohide >= this.hideDelay) //Time to hide elapsed
			{
				this.startHiding(id);
				retick = false;
			}
		}
		else if (menus[id].counting_hiding)
		{
		}
		else if (menus[id].counting_showing)
		{
		}
		else 
			retick = false;
		if (retick)
		{
			var JS = this.popUpMenuName + ".timerTick('" + id + "');";
			menus[id].timerFunc = setTimeout(JS,INTERVAL);
		}
		else
			menus[id].timerFunc = null;
	}
	
	this.startTimeout = function startTimeout(id)
	{
	    if (!started) return;
		this.resetTimeout(id);
		menus[id].counting = true;
		var JS = this.popUpMenuName + ".timerTick('" + id + "');";
		menus[id].timerFunc = setTimeout(JS,INTERVAL);
	}
	
	
	this.mouseClick = function mouseClick(id,divid)
	{
	    if (!started) return;
		if (menus[id] == null)
			this.createMenu(id,divid);
		if (!menus[id].showing)
			this.showMenu(id);
	}
	
	this.mouseOver = function mouseOver(id,divid)
	{ 
		if (!started) return;
		
		var x = document.getElementById(id);
		
		if (id == '' || id == null) //No id chosen, hide all menus
		{
			for (var i = 0; i < allMenus.length; i++)
				if (menus[allMenus[i]].showing)
					this.hideMenu(menus[allMenus[i]].id);
		}
		else
		{
			var newid = id;
			if (menus[newid] == null)
				this.createMenu(newid,divid);
				
			if (menus[newid].counting_tohide)
			{
				menus[newid].counting_tohide = false;
				menus[newid].count_tohide = 0;
			}
			else if (menus[newid].counting_hiding)
				menus[newid].counting_hiding = false;
			if (!menus[newid].showing && !menus[newid].counting_toshow && !menus[newid].counting_showing)
			{
			    this.recalcLocation(id);
				this.showMenu(newid);
			}
			
			showParents(id);


		}
	}
	
	function showParents(id)
	{
		if (parent[id] != null)
		{
			curr = id;
			while (parent[curr] != null)
			{
				curr = parent[curr];
				if (menus[curr] != null)
				{
					menus[curr].counting_toshow = false;
					menus[curr].counting_showing = false;
					menus[curr].showing = true;
					menus[curr].divElem.style.visibility = 'inherit';
				}
			}
		}
	}
	
	this.hideParents = function hideParents(id)
	{
		if (parent[id] != null)
		{
			curr = id;
			while (parent[curr] != null)
			{
				curr = parent[curr];
				if (menus[curr] != null)
				{
					if (menus[curr].showing)
						this.hideMenu(curr);
					else if (menus[curr].counting_toshow)
					{
						menus[curr].counting_toshow = false;
						menus[curr].count_toshow = 0;
					}
					else if (menus[curr].counting_showing)
						this.startHiding(curr);
				}

			}
		}
	}
	
	this.mouseOut = function mouseOut(id,divid)
	{
	    if (!started) return;
		var newid;
    	newid = id;
		if (menus[newid] == null)
			this.createMenu(newid,divid);
		if (menus[newid].showing)
			this.hideMenu(newid);
		else if (menus[newid].counting_toshow)
		{
			menus[newid].counting_toshow = false;
			menus[newid].count_toshow = 0;
		}
		else if (menus[newid].counting_showing)
			this.startHiding(newid);
		this.hideParents(id);
	}
}
