// library to control dynamic menu bars// by Thomas M. Farrell//// This code requires the use of several other libraries.// Before loading this library, you must load://    sniff.js by Netscape Communications//    layercontrol3.js by Thomas M. Farrell// The following variable defines the suffix which will be appended to the // ID strings of layers to obtain the ID string of the matching on // version of the layer. For example, if you have a layer called "top0sub0"// in the menu, and the string to append is "on", the matching on version // is "top0sub0on".var menuBarOnSuffix = "on";// The following variable holds the menu structure.var menuBarStructure = null;// You have to override the value with an array. This array contains // the IDs of the layers in the menu (off states only) in a structure // representing the structure of the menu bar and its submenus. For example,// assume that the menu bar has two menus listed on it. The off states of// the menu items are held in the layers with IDs "top0" and "top1". The // submenu for the top0 item has three menu items, with off states in layers// "top0sub0", "top0sub1", and "top0sub2". The top0sub0 and top0sub1 items // are direct links, but the top0sub2 has a sub-submenu with two items, // with off states in layers "top0sub2sub0" and "top0sub2sub1". //// Meanwhile, in the top1 menu, the menu items have their off states in the // "top1sub0" and "top1sub1" layers. For simplicity, neither has a// sub-submenu. // // Note that these layer names are arbitrary: the code doesn't actually care// what you call your layers as long as you can keep track of them.//// Anyway, the above described structure can be represented as:// menuBarStructure = [//   "ignore",//   ["top0",["top0sub0"],["top0sub1"],["top0sub2",["top0sub2sub0"],["top0sub2sub1"]]],//   ["top1",["top1sub0"],["top1sub1"]]//   ];// where "ignore" is a required placeholder, ignored by the software. // The following variable specifies which menu items, if any, // should default open.var menuBarDefaultOpen = [];// If you want to set a default state other than "everything is closed"// for the menu bar, override the value with an array of strings of// the IDs of the layers you want to default to visible. When the// menu returns to its default state, the listed layers will be // forced to visibility.// The following holds the interval for the menu bar's detection loop.// You shouldn't alter this value, the software handles it.var menuBarDetectionInterval = null;// Call the following function when the page is finished loading.// THIS FUNCTION KNOWN WORKING.function startMenuBar() {	// recurse through the structure and turn it into objects...	menuBarStructure = turnStructureIntoObjects(menuBarStructure);	// recurse through the default state arrays and objectify the strings	for (var x=0; x<menuBarDefaultOpen.length; x++) {		menuBarDefaultOpen[x] = new layerObject(menuBarDefaultOpen[x]);		} //end for loop	// start detecting the mouse location	loadMouse();	// start detecting if the mouse is actually in a menu...	menuBarDetectionInterval = setInterval("menuBarStatusUpdater()",200);	// make all of the top-level menu items visible...	// return the menu to its default state.	menuBarDefault();	} //end function// The following function returns the menu bar to its default state.// If you haven't changed the default state, that means all the menus// are closed and only the items on the bar itself show. If you have// changed the values of menuBarDefaultOpen and/or menuBarDefaultOn,// the default state will reflect your specifications.function menuBarDefault() {	// hide everything in all the submenus, leaving only the top level	menuBarCloseAll();	// recurse through the default open list and show all the layers...	for (var x=0; x<menuBarDefaultOpen.length; x++) {		menuBarOpen(menuBarDefaultOpen[x]);		} //end for loop	menuBarReturnedToDefault = true;	} //end function// The following variable contains an array of all the layer objects// that are currently open in the menubar.//// YOU SHOULD NOT MODIFY THIS ARRAY. THE CODE HANDLES THIS FOR YOU.var menuBarOpenItems = [];// The following variable contains an array of all the layer objects// that are currently on in the menubar in the on state.//// YOU SHOULD NOT MODIFY THIS ARRAY. THE CODE HANDLES THIS FOR YOU.var menuBarOnItems = [];function menuBarOpen(itemToOpen) {	menuBarOpenItems[menuBarOpenItems.length] = itemToOpen;	itemToOpen.show();	} //end functionfunction menuBarTurnOn(itemToOpen) {	menuBarOnItems[menuBarOnItems.length] = new layerObject(itemToOpen+menuBarOnSuffix);	menuBarOnItems[menuBarOnItems.length-1].show();	} //end functionfunction menuBarClose(idOfItemToClose) {	for (var x=0; x<menuBarOpenItems.length; x++) {		if (menuBarOpenItems[x].layerID==idOfItemToClose) {			menuBarOpenItems[x].hide();			menuBarOpenItems[x] = null;			break;			} //end if		} //end for loop;	menuBarOpenItems = compressArray(menuBarOpenItems);	} //end functionfunction menuBarCloseAll() {	for (var x=0; x<menuBarOpenItems.length; x++) {		menuBarOpenItems[x].hide();		} //end for loop	menuBarOpenItems = [];	if (menuBarOnSuffix!=null) {		for (var x=0; x<menuBarOnItems.length; x++) {			menuBarOnItems[x].hide();			} //end for loop		menuBarOnItems = [];		} //end if	} //end function// The following function takes an incoming array and returns a new array// with the same values as the incoming array, but with null values // eliminated.function compressArray(incomingArray) {	var result = [];	for (var x=0; x<incomingArray.length; x++) {		if (incomingArray[x]!=null) {			result[result.length] = incomingArray[x];			} //end if		} //end for loop	return result;	} //end function// The following function puts the new value onto the front of the // array, steps each value in the array one ahead, and keeps the// array within the specified maximum size. It returns the new// array.function pushArray(oldArray,newValue) {	var newArray = oldArray;	for (var x=(newArray.length-1); x>0; x--) {		newArray[x] = newArray[x-1];		} //end for loop	newArray[0] = newValue;	return newArray;	} //end function// The following function returns true if all values in the incoming array// are null, false if not. function allNull(incomingArray) {	var soFar = true;	for (var x=0; x<incomingArray.length; x++) {		if (incomingArray[x]!=null) {			soFar = false;			break;			} //end if		} //end for loop	return soFar;	} //end function// The following variable contains the mouse-in-menu-status. This is an// array of strings containing the names of the layers the mouse was pointing // at it was in the menu during recent update cycles, or null if the mouse was // pointing at no menu layer.//// YOU SHOULDN'T MODIFY THIS VALUE. THE SOFTWARE DOES IT FOR YOU.var menuBarMouseStatus = [null,null,null,null,null,null,null,null,null,null];// The following variable indicates if the menu bar has already been returned // to its default state. This prevents the update routine from constantly // redrawing the menu bar when the mouse is ignoring it.//// YOU SHOULDN'T MODIFY THIS VALUE. THE SOFTWARE DOES IT FOR YOU.var menuBarReturnedToDefault = true;// The following variable indicates if the software is adjusting the status// of the menu now. This prevents the menu from attempting a redraw while a// redraw is already occurring, possibly resulting in a nonsensical menu // state.//// YOU SHOULDN'T MODIFY THIS VALUE. THE SOFTWARE DOES IT FOR YOU.var menuBarAdjustingNow = false;// The following sets the value of menuBarMouseStatus.// YOU SHOULDN'T CALL THIS FUNCTION, THE SOFTWARE DOES IT FOR YOU.function menuBarStatusUpdater() {	var foundIt=false;	for (var x=0; x<menuBarOpenItems.length; x++) {		// If the mouse is in a menu item...		if (menuBarOpenItems[x].hasMouse()) {			menuBarMouseStatus = pushArray(menuBarMouseStatus,menuBarOpenItems[x].layerID);			menuBarReturnedToDefault = false;			foundIt = true;			break;			} //end if		} //end for loop	// If the mouse isn't in a menu item...	if (!foundIt) {		menuBarMouseStatus = pushArray(menuBarMouseStatus,null);		} //end if	// Next we check if the status has just changed. If so, and if the new	// status is not null, we adjust the menu.	if ((menuBarMouseStatus[0]!=null) && (menuBarMouseStatus[0]!=menuBarMouseStatus[1]) && (!menuBarAdjustingNow)) {		menuBarAdjust(menuBarMouseStatus[0]);		} //end if	//alert(menuBarMouseStatus);	// Now we determine if the mouse has been out of the menu bar for	// long enough to return to default state, and if it's necessary.	if ( (allNull(menuBarMouseStatus)) && (!menuBarReturnedToDefault) ) {		menuBarDefault();		} //end if	} //end function// The following function adjusts the appearance of the menu in// reaction to the current mouse location.// YOU SHOULDN'T CALL THIS FUNCTION, THE SOFTWARE DOES IT FOR YOU.function menuBarAdjust(currentItem) {	menuBarAdjustingNow = true;	menuBarReturnedToDefault = false;	// First close everything so extraneous stuff doesn't get left on...	menuBarCloseAll();	// then build up the new status of the menus...	var collectResult = menuBarRecurseStructure(menuBarStructure,currentItem);	// collectResult should always evaluate to true. If it doesn't, that means	// something has gone rather wrong in the menu. The following puts an error	// message in the window status display. This may be commented out.	if (!collectResult) {		window.status = "A difficulty was encountered while attempting to adjust navigation display.";		clearInterval(menuBarDetectionInterval);		menuBarDetectionInterval = null;		} //end if	menuBarAdjustingNow = false;	} //end function// The following function works its way through the menu bar structure,// finds the specified named item, and adjusts the menu accordingly.// YOU SHOULDN'T CALL THIS FUNCTION, THE SOFTWARE DOES IT FOR YOU.function menuBarRecurseStructure(incomingArray,searchingForString) {	// if the primary element of the array is the item being searched for,	// make all of the elements visible and return true.	if (incomingArray[0].layerID==searchingForString) {		if (incomingArray[0]!="ignore") {			menuBarOpen(incomingArray[0]);			if (menuBarOnSuffix!=null) {				menuBarTurnOn(incomingArray[0].layerID);				} //end if			} //end if		for (var x=1; x<incomingArray.length; x++) {			menuBarOpen(incomingArray[x][0]);			} //end for loop		return true;		} //end if	// Otherwise, check all of the subelements. If any of them contain	// it, make all of the elements visible and return true.	else {		var foundInSubitem = null;		for (var x=1; x<incomingArray.length; x++) {			if (menuBarRecurseStructure(incomingArray[x],searchingForString)) {				foundInSubitem = x;				break;				} //end if			} //end for loop		if (foundInSubitem!=null) {			if (incomingArray[0]!="ignore") {				menuBarOpen(incomingArray[0]);				if (menuBarOnSuffix!=null) {					menuBarTurnOn(incomingArray[0].layerID);					} //end if				} //end if			for (var x=1; x<incomingArray.length; x++) {				menuBarOpen(incomingArray[x][0]);				} //end for loop			return true;			} //end if		} //end else	// Otherwise this array does not contain the item being searched for.	// So, return false.	return false;	} //end function// The following function goes through the menu bar structure array and // turns all of the strings into layers.function turnStructureIntoObjects(incomingArray) {	var result = incomingArray;	if (result[0]!="ignore") {		result[0] = new layerObject(result[0]);		} //end if	if (result.length>1) {		for (var x=1; x<result.length; x++) {			result[x] = turnStructureIntoObjects(result[x]);			} //end for loop		} //end if	return result;	} //end function// The following function localizes the menu bar based on the URL of // the page the code is used in.function menuBarLocalize() {	var current = location.href;	current = current.split("/");	var local = current[3];	var suffix = "";	if (menuBarOnSuffix!=null) {		suffix = menuBarOnSuffix;		} //end if	menuBarDefaultOpen[menuBarDefaultOpen.length] = local + suffix;	} //end function