/*
ELEMENTS BORROWED HEAVILY FROM WebFX (http://webfx.eae.net) XMenu
AND http://www.xs4all.nl/~ppk/js/findpos.html

LEARNING EXPERIENCE USING OBJECT ORIENTATED JavaScript
ORIGINAL SUFFERED BY NOT WORKING EFFECTIVELY ON IE-MAC PLATFORM

THIS CODE IS FOR IE5+, Moz1+... OPERA IS SUPPORTED ONLY IF mMenuUseHover = true

-------- JAVASCRIPT MENU DEFINITIONS -------------------------
mDefaultWidth = 100;
mDefaultTitle = "DEFAULT";
mDefaultHREF = "javascript:void(0);";
mShowMenuTime = 100;
mHideMenuTime = 200;
mMenuUseHover = true;

myTest01 = new menu;
myTest01.add(new menuItem("Title01", "HREF", "toolTip"));
	mySubTest = new menu;
	mySubTest.add(new menuItem("sub01", "href", "wagga"));
		mySubTest2 = new menu;
		mySubTest2.add(new menuItem("sub0101", "href"));
		mySubTest2.add(new menuItem("sub0102", "href"));
	mySubTest.add(new menuItem("sub02...", "href", "", mySubTest2));
myTest01.add(new menuItem("Title02...", "HREF", "", mySubTest));
document.write(myTest01);

myTest02 = new menu;
myTest02.add(new menuItem("Title01", "HREF", "toolTip"));
	mySubTest03 = new menu;
	mySubTest03.add(new menuItem("sub01", "href", "wagga"));
myTest02.add(new menuItem("Title02...", "HREF", "", mySubTest03));
document.write(myTest02);

---------- CSS CLASSES ---------------------------------------

.menuWrapper				:	bounding box for entire drop-down
.menuWrapper div.menuItem	:	div per menu item
.menuWrapper a				:	menu item link text
.menuWrapper div.seperator	:	menu seperator

---------- HTML TO CALL MENUS --------------------------------
<a href="#" onFocus="if (!mMenuUseHover) myTest01.show(this);"
	onMouseover="if (mMenuUseHover) myTest01.show(this)"
	onBlur="if (!mMenuUseHover) menuHandler.hideMenu()"
	onMouseout="if (mMenuUseHover) menuHandler.hideMenu()"
	onMousedown=""
	onMouseUp="">HREF</a>
<a href="#" onFocus="if (!mMenuUseHover) myTest02.show(this);"
	onMouseover="if (mMenuUseHover) myTest02.show(this)"
	onBlur="if (!mMenuUseHover) menuHandler.hideMenu()"
	onMouseout="if (mMenuUseHover) menuHandler.hideMenu()"
	onMousedown=""
	onMouseUp="">HREF</a>
*/

/*
-------------------------------------------------------------------------
MENU DEFAULTS
-------------------------------------------------------------------------
*/

mDefaultWidth = 115;
mDefaultTitle = "DEFAULT";
mDefaultHREF = "javascript:void(0);";
mShowMenuTime = 100;
mHideMenuTime = 200;
mMenuUseHover = true;
mMouseOverText = "#ffffff";
mMouseOverBackground = "#000066";
mMouseOutText = "#000000";
mMouseOutBackground = "#D6D3CE";


/*
-------------------------------------------------------------------------
POSITIONING FUNCTIONS
-------------------------------------------------------------------------
*/
// loop through all 'offsetParents' to calculate actual distance from the left / top of browser window
function findPosX(obj){
	var curleft = 0; // start at zero
	if (document.getElementById || document.all){
		// modern browsers
		while (obj.offsetParent){
			// loop through all offset parents
			curleft += obj.offsetLeft // add parent value
			obj = obj.offsetParent; // set the next object
		}
	}else if (document.layers){
		// ns4!!!!
		curleft += obj.x;
	}
	return curleft; // return resul
}

// same as above but for offsetTop values
function findPosY(obj){
	var curtop = 0;
	if (document.getElementById || document.all){
		while (obj.offsetParent){
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}else if (document.layers){
		curtop += obj.y;
	}
	return curtop;
}

/*
-------------------------------------------------------------------------
OBJECT FUNCTIONS
-------------------------------------------------------------------------
*/

/* MOVED TO GENERAL.JS
// find an object by referenceing its ID in the DOM
function getObject(id){	
	if (document.getElementById){
		// modern browsers
		return document.getElementById(id);
	}else if (document.all){
		// IE 4
		return document.all[id];
	}else{
		// ALL OTHERS... NO SUPPORT
		return null;
	}
}*/


/*
-------------------------------------------------------------------------
MENU HANDLE OBJECT
-------------------------------------------------------------------------
*/

/*
menuHandler is an object manages the menu elements
.all			:	object containing references to all menu items created
.allIDs			:	IDs of all menu div's - ie menu tabs
.getId			:	generates a new id for a menu / menuItem to use
.clearAll		:	hides all menu tabs
.overMenuItem	:	cursor is over a menuItem - clears any timeouts running
					calls '_over' method on timeout
.outMenuItem	:	roll off event - clears any timeouts
					calls '_out' method on timeout
._over			:	check for sub menu and show it if it exists
._out			:	hide any sub menus			
.hideMenu		:	sets a timeout to hide all the menus
*/
 

var menuHandler = {
	idCounter		:	0,
	idPrefix		:	"menu-object-",
	all				: 	{},
	allIDs			:	[],
	getId			:	function () { return this.idPrefix + this.idCounter++; },
	clearAll		: 	function (){
		// loop through all menu tab id's
		for(var i=0; i<this.allIDs.length; i++){					
			thisItem = getObject(this.allIDs[i]); // get the DOM object
			thisItem.style.visibility = "hidden"; // set the style to hidden
		}
	},
	mouseOver		:	function (oItem) {
		oItem.style.color = mMouseOverText;
		oItem.style.background = mMouseOverBackground;
	},
	mouseOut		:	function (oItem) {
		oItem.style.color = mMouseOutText;
		oItem.style.background = mMouseOutBackground;
	},
	overMenuItem	:	function (oItem) {
		if(oItem.className != "seperator"){
			this.mouseOver(oItem);
		}
		// clear any timeouts that exists...
		if (this.showTimeout != null){
			window.clearTimeout(this.showTimeout);
		}
		if (this.hideTimeout != null){
			window.clearTimeout(this.hideTimeout);
		}
		
		var jsItem = this.all[oItem.id]; // get rollover item menu reference from this.all
		if (mShowMenuTime <= 0){
			this._over(jsItem); // show menu imediately
		}else{
			// show item on timeout
			//this.showTimeout = window.setTimeout(function () { webFXMenuHandler._over(jsItem) ; }, webfxMenuShowTime);
			// I hate IE5.0 because the piece of shit crashes when using setTimeout with a function object
			this.showTimeout = window.setTimeout("menuHandler._over(menuHandler.all['" + jsItem.id + "'])", mShowMenuTime);
		}
	},
	outMenuItem	:	function (oItem) {
		this.mouseOut(oItem);
		// clear any timeouts that exists...
		if (this.showTimeout != null){
			window.clearTimeout(this.showTimeout);
		}
		if (this.hideTimeout != null){
			window.clearTimeout(this.hideTimeout);
		}
		var jsItem = this.all[oItem.id]; // get rollover item menu reference from this.all		
		if (mHideMenuTime <= 0){
			this._out(jsItem); // hide menu imediaely
		}else{
			// hide menu on timeout
			//this.hideTimeout = window.setTimeout(function () { webFXMenuHandler._out(jsItem) ; }, webfxMenuHideTime);
			this.hideTimeout = window.setTimeout("menuHandler._out(menuHandler.all['" + jsItem.id + "'])", mHideMenuTime);
		}
	},
	_over	:	function (jsItem) {
		if (jsItem.subMenu) {
			jsItem.parentMenu.hideAllSubs(); // hide all other sub menus
			jsItem.subMenu.show(); // show the sub menu for this menu item
		}else{
			jsItem.parentMenu.hideAllSubs(); // no sub menu - so just hide any other that might be open
		}
	},
	_out	:	function (jsItem) {			
		if(mMenuUseHover){
			menuHandler.clearAll(); // clear all menus on roll-off
		}else{
			if (jsItem.subMenu != null)
				jsItem.subMenu.hide(); // hide sub menu if it exists
		}
	},
	hideMenu	:	function () {
		if (this.showTimeout != null){
			window.clearTimeout(this.showTimeout);
		}
		if (this.hideTimeout != null){
			window.clearTimeout(this.hideTimeout);
		}
		this.hideTimeout = window.setTimeout("menuHandler.clearAll()", mHideMenuTime);
	}
};


/*
-------------------------------------------------------------------------
MENU OBJECT
-------------------------------------------------------------------------
*/

/*
menu is an object that defines a menu 'tab' into which menu items can be added
.add			:	attaches a new menu item to the tab
.toString		:	effectively becomes document.write(menu); - this writes the menu elements to the page
.show			:	makes this menu tab visible
.hide			:	hides this menu tab
.hideAllSubs	:	hides any sub menus that are attached to this menu tab
*/

function menu(){
	this._menuItems	= []; // array of all menu items in this tab
	this._subMenus	= []; // array of all sub menus coming off this tab
	this.top = 0; // top x/y location
	this.left = 0; // left x/y location
	this.width = mDefaultWidth; // defualt width property
	this.visible = "hidden"; 
	this.id = menuHandler.getId(); // get myself an id
	this.parentMenu = null;
	this.parentMenuItem = null;
	menuHandler.all[this.id] = this; // add my reference to the menuHandler
	menuHandler.allIDs[menuHandler.allIDs.length] = this.id; // I am a menu tab - so add my reference to the menuHandler
}

menu.prototype.width = mDefaultWidth; // defualt width property

menu.prototype.add = function(oMenuItem){
	this._menuItems[this._menuItems.length] = oMenuItem; // add menu item to array
	if (oMenuItem.subMenu) {
		this._subMenus[this._subMenus.length] = oMenuItem.subMenu; // if the item has a sub menu - add the sub menu to array
		oMenuItem.subMenu.parentMenu = this; // let the sub menu know who its parent tab is
	}	
	oMenuItem.parentMenu = this; // let the menu item know who its parent is
};


menu.prototype.toString = function () {
	// contruct div element to contain menu items
	var str = "<div id=\"" + this.id + "\" class=\"menuWrapper\" style=\"" + 
		"left:" + this.left + "px;" + 
		"top:" + this.top + "px;" + 
		"visibility:" + this.visible + ";" + 
		"width:" + this.width + "px;" + 
		//"z-index:" + menuHandler.idCounter + ";" + 
		"\">";
		
	// insert all menu items here
	for(var i=0; i<this._menuItems.length; i++){
		str += this._menuItems[i]; // effectively calls menuItem.toString()
	}
	
	str += "</div>";
	
	for (var i=0; i<this._subMenus.length; i++) {
		str += this._subMenus[i]; // calls the toString method for any sub menus on the tab
	}

	return str; // output the HTML
};


menu.prototype.show = function(clickObj){
	// clear any timeouts...
	if (menuHandler.showTimeout != null){
		window.clearTimeout(menuHandler.showTimeout);
	}
	if (menuHandler.hideTimeout != null){
		window.clearTimeout(menuHandler.hideTimeout);
	}
	
	var doShow = true;
	if (clickObj){
		// find position from click (menu parent or root)
		var myTop = findPosY(clickObj) + clickObj.offsetHeight; // always at the bottom
		
		// check for the menu going off the right edge of the screen
		var clickPos = findPosX(clickObj);
		
		// get window width...
		if(window.innerWidth){
			var browserWidth = window.innerWidth; // ie
		}else if(document.body.clientWidth){
			var browserWidth = document.body.clientWidth; // mozilla
		}else{
			var browserWidth = 0; // others
		}
		
		// check positions and include 16 px for scroll bar
		if((browserWidth > 0) && (clickPos + this.width > browserWidth - 16)){
			var myLeft = browserWidth - this.width - 16;
		}else{
			var myLeft = clickPos;
		}
		
		//var myLeft = findPosX(clickObj);
		menuHandler.clearAll(); // clear all menus
	}else{
		// get parentElement loc
		var parentItem = getObject(this.parentMenuItem.id);
		var myTop = findPosY(parentItem);
		var parentRootX = findPosX(parentItem);
		var myLeft = parentRootX + parentItem.offsetWidth; // always to the right
		
		// check to make sure that there is room for the menu...
		if(window.innerWidth){
			var browserWidth = window.innerWidth; // ie
		}else if(document.body.clientWidth){
			var browserWidth = document.body.clientWidth; // mozilla
		}else{
			var browserWidth = 0; // others
		}
		
		var rightOK = false;
		var leftOK = false;
		if(browserWidth > 0){
			if(myLeft + this.width <= browserWidth){
				var rightOK = true;
			}else if(parentRootX - this.width >= 0){
				var leftOK = true;
			}
		}else{
			var rightOK = true;
		}
		if(rightOK){
			// nothing
		}else if(leftOK){
			myLeft = parentRootX - this.width;
		}else{
			doShow = false;
		}
	}
	
	if(doShow){
		// set menu tab location
		//alert(document.body.clientWidth + " - " + window.innerWidth);
		var divElement = getObject(this.id);
		divElement.style.left=myLeft+"px";
		divElement.style.top=myTop+"px";
		divElement.style.visibility="visible"; // we can see the menu tab
	}
}


menu.prototype.hide = function () {
	this.hideAllSubs(); // hide any sub menus that might be open
	var divElement = getObject(this.id);
	menuHandler.mouseOut(divElement);
	divElement.style.visibility = "hidden"; // hide this menu tab
};


menu.prototype.hideAllSubs = function () {
	// loop through all sub menus to hide them
	for (var i=0; i<this._subMenus.length; i++) {
		var divElement = getObject(this.id); // get object reference
		menuHandler.mouseOut(divElement);
		if(divElement.style.visibility != "hidden"){
			this._subMenus[i].hide(); // hide it if it is not already hiden
		}
	}
};


/*
-------------------------------------------------------------------------
MENU ITEM OBJECT
-------------------------------------------------------------------------
*/

/*
menuItem object holds properties for each menu item
.toString		:	effectively becomes document.write(menuItem); - this writes the HTML to the page
*/

function menuItem(sText, sHref, sToolTip, oSubMenu){
	this.text = sText || mDefaultTitle; // item text
	this.href = (sHref == null || sHref == "") ? mDefaultHREF : sHref; // item href
	this.subMenu = oSubMenu; // seb menu object	
	this.toolTip = sToolTip; // tool tip text
	this.id = menuHandler.getId(); // get an id for this item
	menuHandler.all[this.id] = this; // add reference to menuHandler array
	if (oSubMenu) oSubMenu.parentMenuItem = this;// tell sub menu who its parent item is
}

menuItem.prototype.toString = function(){
	// output is an <a href></a> with mouse over/out events for displaying / hideing sub menu
	/*var str = "<a id=\"" + this.id + "\" href=\"" + this.href + "\"" +
		(this.toolTip ? " title=\"" + this.toolTip + "\"" : "") +
		" onMouseOver=\"menuHandler.overMenuItem(this)\"" +
		(mMenuUseHover ? " onmouseout='menuHandler.outMenuItem(this)'" : "") +
		"><div class=\"menuItem\" id=\"" + this.id + "\">" + this.text + "</div></a>";*/
	var str = "<a href=\"" + this.href + "\"><div class=\"menuItem\" id=\"" + this.id + "\"" +
		(this.toolTip ? " title=\"" + this.toolTip + "\"" : "") +		
		" onMouseOver=\"menuHandler.overMenuItem(this);\"" +
		" onMouseOut=\"" + (mMenuUseHover ? ";menuHandler.outMenuItem(this)\"" : "") +";\"" +
		//(mMenuUseHover ? " onmouseout=\"menuHandler.outMenuItem(this);menuHandler.mouseOut(this);\"" : "") +
		">" + this.text + "</div></a>";	
	//alert(this.parentMenu.width);
	return str;
};



/*
-------------------------------------------------------------------------
MENU SEPERATOR OBJECT
-------------------------------------------------------------------------
*/

/*
menuSeparator object simple <div></div> construction for separator
.toString		:	effectively becomes document.write(menuItem); - this writes the HTML to the page
*/
function menuSeparator() {
	this.id = menuHandler.getId(); // get an id
	menuHandler.all[this.id] = this; // add id to redrence array just like a menu item
}

menuSeparator.prototype.toString = function () {
	var str = "<div" + " id=\"" + this.id + "\"" + 
		" onmouseover=\"menuHandler.overMenuItem(this)\"" +
		" onmouseout=\"menuHandler.outMenuItem(this)\"" + 
		" class=\"seperator\"" + 
		"></div>";
	return str;
};