//==========================
// prototype the push method
// for older browsers
//==========================
		if (Array.prototype.push && ([0].push(true)==true))
				Array.prototype.push = null;
	
		if(!Array.prototype.push) {
	
			function array_push() {
				for(i=0;i<arguments.length;i++){
					this[this.length] = arguments[i];
				}
				return this.length;
			}
			Array.prototype.push = array_push;
		}

//=========================
// prototype the pop method
// for older browsers
//=========================

		if(!Array.prototype.pop) {
		    function array_pop(){
		        lastElement = this[this.length-1];
		        this.length = Math.max(this.length-1,0);
		        return lastElement;
		    }
		    Array.prototype.pop = array_pop;
		}

//=============================
// main programming starts here
//=============================
		var menuDisplay = new Array();
		var cTime = null;
		var timeout = 1500;
		
		// to store the current stack of opened menu items
		function showMenu(triggerId,oEvent){

		clearTimeout(cTime);

		// declare variables
		var arrParams = new Array();		// an array to hold the current cell, trigger pair
		var parentId;				// to hold the calling menu id
		var previousParentId;	     		// to hold the previous menu action's current menu id
		var previousTriggerId;	     		// to hold the previous menu action's trigger menu id (if any)
		var triggerCell;				// points to the menu item triggered
		var lastMenuPos=0;		      // to hold the menu stacks upper dimension

			// check that the function was triggered by an event rather than a call from code
			// set the parentId = to the respective menu item accordingly
			if(oEvent){
			if(oEvent.type=='load')
				var srcE = document.body;
			else
				var srcE = (oEvent.srcElement)?oEvent.srcElement:oEvent.target;
				parentId = getMenuDiv(srcE);
			}else{parentId = triggerId;}

			//check if this is to be the first menu item in the stack (menuDisplay) ie start of browsing
			if(menuDisplay.length==0){
				arrParams[0]=triggerId;arrParams[1]='';
				menuDisplay.push(arrParams);
				triggerId='';
			}
			// initialise the remaining variables
			lastMenuPos = (menuDisplay.length>0) ? menuDisplay.length-1 : 0;
			previousParentId = menuDisplay[lastMenuPos][0];
			previousTriggerId = menuDisplay[lastMenuPos][1];
			arrParams[0] = parentId; arrParams[1] = triggerId;

			if(parentId=='none'){
			// check if the BODY tag called the function. If so, hide all menus except the top level one
				hideMenu('all');
			}else{
				if(triggerId!='BODY'){
				if(oEvent) triggerCell = (oEvent.srcElement)?oEvent.srcElement:oEvent.target;
				cTime = setTimeout("clearMenu()",timeout);
				// now consider the scenarios.
				// 1. same parentId but differing triggerIds = browsing the same menu
				// 2. different parentId irrespective of triggerIds
				//   2a. new parentId = previous triggerId = browsing newly triggered menu
				//   2b. new menu entirely - loop back through previous pairs, hiding them until either a previous
				//		 matching pair is found, or the top level menu is reached. Then show new menu.

				//1. same parentId but differing triggerIds = browsing the same menu
					if(parentId==previousParentId && triggerId!=previousTriggerId){
						if(isMenu(previousTriggerId)){
						// hide and pop the last stack item	
							hideMenu();
						}else{
						// if there was no menu triggered, just pop the menu item
							if(menuDisplay.length>1) menuDisplay.pop();
						}
						// Show any triggered menu
						if(isMenu(triggerId)) displayMenu(triggerId,true,parentId,triggerCell);
						menuDisplay.push(arrParams);
						return true;
					}else{
						if(!(parentId==previousParentId && triggerId==previousTriggerId)){
						// 2. different parentId irrespective of triggerIds
						//   2a. new parentId = previous triggerId = browsing newly triggered menu
							if(parentId!=previousParentId && parentId==previousTriggerId){
							// Show any triggered menu
								if(isMenu(triggerId)) displayMenu(triggerId,true,parentId,triggerCell);
								menuDisplay.push(arrParams);
								return true;
							}else{
							//   2b. new menu entirely - loop back through previous pairs, hiding them until either a previous
							//		 matching pair is found, or the top level menu is reached. Then show new menu.
								if(!hideMenu(parentId, triggerId, srcE)){
								// no matching pair was found so all menus have been closed, bar the top level
								// so treat the new event as a new menu completely
									if(isMenu(triggerId)) displayMenu(triggerId,true, parentId, triggerCell);
									menuDisplay.push(arrParams);
									return true;
								}else{
								// if a matching pair were found, the menus after that pair have been closed and 
								// popped from the stack so no further action needed
									return true;
								}
							}
						}
					}
				}
			}
		}
		
		function clearMenu(){
			hideMenu('all');
		}

		function getMenuDiv(oElement){
			var divElementId = ''
			if(oElement.tagName!='BODY'){
				while(oElement.parentNode && !divElementId){
					if(oElement.parentNode.tagName=='DIV'&&isMenu(oElement.parentNode.id)){
						// isMenu() checks that the DIV id is in the menu list
						divElementId=oElement.parentNode.id
					}else{
						divElementId = getMenuDiv(oElement.parentNode);
					}
				}
			}else{
				divElementId = 'none';
			}
		return divElementId;
		}

		function hideMenu(menuid){
		// check if a menuid parameter was passed
			if(menuid){
			// if a parameter was passed, check if all existing menus shoul be hidden
				if(menuid=='all'){
				// hide all menus that are open
					while(menuDisplay.length > 1){
					// i > 1 : leave the first menu item visible
						lastMenuNo = menuDisplay.length-1;
						// also make sure that only non-empty trigger values are hidden
						if(menuDisplay[lastMenuNo][1]) displayMenu(menuDisplay[lastMenuNo][1],false);
						menuDisplay.pop();
					}
					return true;
				}else{
				// a menuid has been passed in. Check if a parentId has also been passed in
				// if more than one argument is passed in, the two arguments are a self/trigger pair
				// loop through the displayed menus, hiding an popping each item until either 
				// 1. the top level is reached or..
				// 2. the same menu pair has been found, in which case stop hiding and popping...
					if(arguments.length>1){
						while(menuDisplay.length > 1){
						// > 1 : remembering to leave the first menu item visible
							lastMenuNo = menuDisplay.length-1
							if(menuDisplay[lastMenuNo][0]==arguments[0]){
								if(menuDisplay[lastMenuNo][1]==arguments[1]){
								// if a valid matching pair are found, return a true value
									return true;
									break;
								}else{
								// show the new menu if it's != ''
									if(menuDisplay[lastMenuNo][1]!='') hideMenu();
									if(isMenu(arguments[1])){
										displayMenu(arguments[1],true,arguments[0],arguments[2]);
									}
									menuDisplay.push(arguments);
									return true;
								}
							}else{
							// hide the previous menu and pop the stack
								if(menuDisplay[lastMenuNo][1]) displayMenu(menuDisplay[lastMenuNo][1],false);
								if(menuDisplay.length>1) menuDisplay.pop();
							}
						}
						// if after the loop no matching pairs were found, return a false value
						return false;
					}else{
					// a single lone menu id has been passed in for hiding. Don't pop as it may not be the last menu
					// displayed...
						displayMenu(menuid,false);
					}
				}
			}else{
				// if no parameter was passed, hide previous menu (if there was one triggered) and pop
				if(menuDisplay[menuDisplay.length-1][1]) displayMenu(menuDisplay[menuDisplay.length-1][1],false);
				if(menuDisplay.length>1) menuDisplay.pop();
			}
		}
		

		function isMenu(id){
			for(key in arrMenus){
				if(key==id) return true;
			}
			return false;
		}

		function displayMenu(id, on){
			var iLeft, iTop, iWidth			
			if(on){
				var parentEl = document.getElementById(arguments[2]);
				var triggerCell = arguments[3];
				var triggerWidth = triggerCell.offsetWidth;
				if(arrMenus[parentEl.id]=="true"){
					iLeft = getPageOffsetLeft(triggerCell);
					iTop = getPageOffsetTop(triggerCell) + parentEl.offsetHeight;
					iWidth='100%';
					//if(this.width==undefined||this.width<triggerWidth-20) this.width = triggerWidth-20;
				}else{
					iLeft = getPageOffsetLeft(parentEl)+parentEl.clientWidth;
					iTop = getPageOffsetTop(triggerCell);
					iWidth='100%' //document.getElementById(this.id).clientWidth;
				}
				displaySwitch='visible';}
			else{
				displaySwitch='hidden';
			}
			var el = document.getElementById(id);
			if(typeof(parentEl)!='undefined'){
				if(parentEl.id!="topLevel"){ 
					el.style.top=iTop+2;
					el.style.left=iLeft+eval((document.all)?0:triggerWidth)-5;
				}else{
					el.style.top=iTop-1;
					el.style.left=iLeft+10;
				}
				el.style.zIndex=parentEl.style.zIndex+5;
			//el.style.width=document.getElementById(this.id).offsetWidth+50;
				//el.childNodes[0].style.width=iWidth;
			}
			el.style.visibility=displaySwitch;
		}
		
		function getPageOffsetLeft(el) {
		var x;
			// Return the x coordinate of an element relative to the page.

			x = el.offsetLeft;
			if (el.offsetParent != null)
			x += getPageOffsetLeft(el.offsetParent);

		return x;
		}

		function getPageOffsetTop(el) {
		var y;

			// Return the x coordinate of an element relative to the page.

			y = el.offsetTop;
			if (el.offsetParent != null)
			y += getPageOffsetTop(el.offsetParent);

		return y;
		}
		
		function getPageOffsetWidth(el) {
		var z;

			// Return the x coordinate of an element relative to the page.

			z = el.offsetWidth;
			if (el.offsetParent != null)
			z += getPageOffsetWidth(el.offsetParent);

		return z;
		}

		function openPage(link, target, clicked){
		var hash = '';
		//if(link.indexOf('#')>0){
		//	hash = link.substring(link.indexOf('#'),link.length);
		//	link = link.substring(0,link.indexOf('#'));
		//}
			if(!document.location.pathname.match(link)){
				if(link=="index.htm")
					link="../".concat(link);// + (link.indexOf('?')>0?'&':'?') + 'parentMenu=' + clicked + hash;
				else if((document.location.pathname.match('index.htm')||document.location.pathname=='/')&&link.substr(0,4)!='http')
					link="pages/".concat(link);// + (link.indexOf('?')>0?'&':'?') + 'parentMenu=' + clicked + hash;
				//else
				//	link+=(link.indexOf('?')>0?'&':'?') + 'parentMenu=' + clicked + hash;
				if(target=="blank")
					window.open(link,"_blank")
				else
					window.location.assign(link);
			}
		}
