/*
	DO NOT REMOVE THIS NOTICE !
	Copyright (c) 2005, ATConnect - All rights reserved
	You are not allowed to use, modify or copy this document without a valid license.
	
	This is the engine of the menu. It contains all vital functions to make it all work.
	
	User hooks can be implemented and are handled in the user.js file. See the file for
	more details around this subject.
	
	Planned work:
	-------------
	
		1.  Support for changing to a vertical layout with ease.


	Developer notes
	---------------
	
		button objects
		--------------
		Are links or seperators within a menu.
		The offsetParent property is used to determine the parent menu.
		When activated, following custom properties are assigned:
	
			currentMenu			Holds the menu activated by the button (if one)


		menu objects
		------------
		Are the div's that contain the button objects.
		When activated, following custom properties are assigned:
		
			parentButton		Holds the button object the menu was activated with
			currentButton		Holds the button object that is currently active within the menu
*/



/*
	Some adjustable variables for more specific views and layouts.
*/

var rootOffsetX = 0;
var rootOffsetY = 1;
var menuOffsetX = 4;
var menuOffsetY = 0;

var buttonDrawHandler = function (button) { };
var buttonHideHandler = function (button) { };



/*
	Some global variables for use with this script.
*/

var browser = new Browser();

var rootButton = null;
var menuTimeout = null;


function Browser()
{
	var ua, s, i;

	this.isIE = false;
	this.isOP = false;
	this.isNS = false;
	this.version = null;

	ua = navigator.userAgent;

	s = "Opera";
	if((i = ua.indexOf(s)) >= 0)
	{
		this.isOP = true;
		this.version = parseFloat(ua.substr(i + s.length));
		return;
	}

	s = "Netscape6/";
	if((i = ua.indexOf(s)) >= 0)
	{
		this.isNS = true;
		this.version = parseFloat(ua.substr(i + s.length));
		return;
	}

	// Treat any other "Gecko" browser as Netscape 6.1.
	s = "Gecko";
	if((i = ua.indexOf(s)) >= 0)
	{
		this.isNS = true;
		this.version = 6.1;
		return;
	}

	s = "MSIE";
	if((i = ua.indexOf(s)))
	{
		this.isIE = true;
		this.version = parseFloat(ua.substr(i + s.length));
		return;
	}
}



/*
	These are the event handlers used in the menu layout.
*/

function itemMouseOver(button, menuId)
{
	stopTimeout();
	
	showButton(button,menuId);
}

function menuMouseOver(menu)
{
	stopTimeout();
}

function menuMouseOut(menu)
{
	menuTimeout = setTimeout('hideButton(rootButton);',200);
}



/*
	These are the functions used by the script.
*/

function stopTimeout()
{
	if(menuTimeout != null) clearTimeout(menuTimeout);
	menuTimeout = null;
}

function showButton(button, menuId)
{
	var parentMenu = button.offsetParent;
	
	if(button == parentMenu.currentButton) return;

	if(parentMenu.currentButton)
		hideButton(parentMenu.currentButton);
	
	if(hasClassName(button,'menuButton'))
		button.className += ' menuButtonActive';

	if(hasClassName(button,'menuItem'))
		button.className += ' menuItemHighlight';
		
	parentMenu.currentButton = button;
	if(!rootButton) rootButton = button;

	if(menuId)
	{
		var menu = document.getElementById(menuId);
		
		showMenu(button,menu);
		button.currentMenu = menu;
	}
	
	buttonDrawHandler(button);
}

function hideButton(button)
{
	menuTimeout = null;
	
	if(!button) return;
	
	buttonHideHandler(button);
	
	var parentMenu = button.offsetParent;

	if(button.currentMenu)
	{
		hideMenu(button.currentMenu);
		button.currentMenu = null;
	}

	if(hasClassName(button,'menuButtonActive'))
		button.className = 'menuButton';

	if(hasClassName(button,'menuItemHighlight'))
		button.className = 'menuItem';
		
	parentMenu.currentButton = null;
	
	if(button == rootButton) rootButton = null;
}

function showMenu(button,menu)
{
	var parentMenu = button.offsetParent;
	
	if(!menu.menuInitialized)
	{
		var itemWidth = 0;

		// Find the width of a menu item.
		var itemList = menu.getElementsByTagName('a');
		if(itemList.length > 0)	itemWidth = itemList[0].offsetWidth;

		// For items with arrows, add padding to item text to make the
		// arrows flush right.
		for(i = 0; i < itemList.length; i++)
		{
			var spanList = itemList[i].getElementsByTagName('span');

			var textEl = null;
			var arrowEl = null;

			for(j = 0; j < spanList.length; j++)
			{
				if(spanList[j].className == 'menuItemText') textEl = spanList[j];
				if(spanList[j].className == 'menuItemArrow') arrowEl = spanList[j];
    		}

			if(textEl != null && arrowEl != null)
			{
				textEl.style.paddingRight = (itemWidth - (textEl.offsetWidth + arrowEl.offsetWidth)) + 'px';

				// For Opera, remove the negative right margin to fix a display bug.
    	  		if(browser.isOP) arrowEl.style.marginRight = '0px';
	    	}
	  	}

		// Fix IE hover problem by setting an explicit width on first item of the menu.
		if(browser.isIE)
		{
			var w = itemList[0].offsetWidth;
			itemList[0].style.width = w + 'px';
			var dw = itemList[0].offsetWidth - w;
	    	itemList[0].style.width = (w - dw) + 'px';
		}
		
		menu.menuInitialized = true;
	}

	if(parentMenu.parentButton == null) // This is the top level menu !
	{
		var x = getOffsetLeft(button);
		var y = getOffsetTop(button) + button.offsetHeight;

		// For IE, adjust position.
		if(browser.isIE)
		{
			x += button.offsetParent.clientLeft;
			y += button.offsetParent.clientTop;
		}
  
		if(browser.isNS) y += 2;
		if(browser.isIE) x -= 2;
		
		x += rootOffsetX - 1;
		y += rootOffsetY - 1;
	}
	else
	{
		var x = getOffsetLeft(button) + button.offsetWidth;
		var y = getOffsetTop(button);
  
		// Adjust position to fit in view.
		var maxX, maxY;
		
		if(browser.isIE)
		{
			maxX = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft)
				 + (document.documentElement.clientWidth != 0 ? document.documentElement.clientWidth : document.body.clientWidth);
			maxY = Math.max(document.documentElement.scrollTop, document.body.scrollTop)
				 + (document.documentElement.clientHeight != 0 ? document.documentElement.clientHeight : document.body.clientHeight);
		}
		
		if(browser.isOP)
		{
			maxX = document.documentElement.scrollLeft + window.innerWidth;
			maxY = document.documentElement.scrollTop  + window.innerHeight;
		}
		
		if(browser.isNS)
		{
			maxX = window.scrollX + window.innerWidth;
			maxY = window.scrollY + window.innerHeight;
		}
  
		maxX -= menu.offsetWidth;
		maxY -= menu.offsetHeight;
		
		x += menuOffsetX;
		y += menuOffsetY;
		
		if(x > maxX)
			x = Math.max(0, x - button.offsetWidth - menu.offsetWidth + (parentMenu.offsetWidth - button.offsetWidth) - (2 * menuOffsetX));
			
		y = Math.max(0, Math.min(y, maxY));
	}
	
	menu.parentButton = button;
	
	menu.style.left = x + 'px';
	menu.style.top = y + 'px';
	menu.style.visibility = 'visible';
}

function hideMenu(menu)
{
	if(menu.currentButton) hideButton(menu.currentButton);
	
	menu.parentButton = null;
	
	menu.style.visibility = 'hidden';
}



/*
	Some helper functions.
*/

function hasClassName(element, name)
{
	var tmp = ' ' + element.className + ' ';
		
	return (tmp.indexOf(' ' + name + ' ') > -1);
}

function getOffsetLeft(element)
{
	var x = element.offsetLeft;
	
	if(element.offsetParent != null)
		x += getOffsetLeft(element.offsetParent);

	return x;
}

function getOffsetTop(element)
{
	var y = element.offsetTop;
	
	if(element.offsetParent != null)
		y += getOffsetTop(element.offsetParent);

	return y;
}
