/** cnPrimaryNavMenuManagerPurpose:		Singleton class to manage "primary" navigation menus on Xerox web sitesAssumptions:	This class assumes that the menus it manages are structured such that,	initially, there is a visible "header" element representing a menu in it's	"off" state.  Also, there is a "menu" element that, initially, is not	rendered representing the menu in it's "on" state.  When a menu is	"turned on", the "header" is removed from the displayed content and the	"menu" is inserted in it's place.	Usage:		cnPrimaryNavMenuManager.toggleMenu(menuElemToTurnOn);	cnPrimaryNavMenuManager.turnOffNow(disableMenuCompletelyFlag);	cnPrimaryNavaMenuManager.VERSION; // version number of this libary		Configuration:	The following attributes can be adjusted to fit your liking			MENU_ON_DELAY    - delay (in milliseconds) before menu is turned on		MENU_OFF_DELAY   - delay (in milliseconds) before menu is turned off		MENU_OFF_CLASS   - String CSS class for "off" menu header elements		MENU_ON_CLASS    - String CSS class for "on" menu header elements (i.e. menu header for current site)		MENU_HOVER_CLASS - String CSS class for menu header element currently under mouse pointer		MENU_MAT_CLASS   - String CSS class for "mat" <IFRAME> used on Windows/IE to prevent <SELECT> elements from occluding menus		MENU_MAT_SRC     - String to use as "src" attribute value in "mat" <IFRAME>s (must be local to domain hosting page to prevent SSL errors)		MENU_ELEM_SUFFIX - String of suffix appended to CSS id of "header" element to find "menu" element		MENU_GROUP_ID    - String of CSS id for element containing all menu elements		MENU_EXCLUDE_USER_AGENTS - Array of strings (partial or complete) to match against the navigator.userAgent strings when determining whether or not to display menus		MENU_PRELOAD_URL - String of server URL to use when loading images (assumes all images are in the same directory)		MENU_PRELOAD_IMAGES - Array of string-names of images to preload**/cnPrimaryNavMenuManager = new function(){	// public configuration data	this.VERSION          = '1.1';	this.MENU_ON_DELAY    = 150;	this.MENU_OFF_DELAY   = 5;	this.MENU_OFF_CLASS   = 'cn_pnav_link';	this.MENU_ON_CLASS    = 'cn_pnav_link_on';	this.MENU_HOVER_CLASS = 'cn_pnav_link_hover';	this.MENU_MAT_CLASS   = 'cn_pnav_fmenu_ie_select_block';	this.MENU_MAT_SRC     = '/images/world/s/spacer.gif';	this.MENU_ELEM_SUFFIX = '_menu';	this.MENU_GROUP_ID    = 'cn_pnav';	this.MENU_EXCLUDE_USER_AGENTS = [];	this.MENU_PRELOAD_URL    = '/images/world/';	this.MENU_PRELOAD_IMAGES = ['b/bg-menulink-blue.png','g/gradient_bg.jpg','b/bg_drop.png','b/bottom_cap_drop.png','t/top_cap_drop.png','c/country_icon.gif','x/xog_menu_slice.gif','p/psg_menu_slice.gif','b/bg-menulink-green.png','x/xgs_menu_slice.gif','b/bg-menulink-purple.png','m/module_top_740x5.gif','f/footer_740x31.gif'];		// "private" data/methods for set/clearInterval calls	this._onTimerId     = null;	this._offTimerId    = null;	this._turnOnMenu    = function(){};	this._turnOffMenu   = function(){};		this._clearOnTimer = function ()	{		clearTimeout(this._onTimerId);				this._onTimerId  = null;		this._turnOnMenu = function(){};	};		this._clearOffTimer = function ()	{		clearTimeout(this._offTimerId);				this._offTimerId  = null;		this._turnOffMenu = function(){};	};		// "private" data	this._skipMenuDisplay = false; // assume we want to show the menu	this._onHdrElemId     = null;  // current "on" element	this._activeHdrElemId = null;  // header of "active" site	this._hdrMenuObjs     = null;  // array of Objects holding header/menu data	this._menuDisabled    = false; // flag indicating that menus are disabled		// declare our public methods	this.turnOffMenuNow = function(){}; // this is actually defined when a menu is activated		this.toggleMenu = function(toggleElem)	{		if (this._menuDisabled)       return;		if (!document.getElementById) return;		if (!this._hdrMenuObjs)       this._initialize();		if (this._onTimerId)          this._clearOnTimer();				var self = this; // set up local copy of instance for use via closure by on/off functions				for ( var i = 0; i < this._hdrMenuObjs.length; ++i )		{			var hdrMenuObj = this._hdrMenuObjs[i];			var hdrElem    = hdrMenuObj['hdr'];			var menuElem   = hdrMenuObj['menu'];					if ( toggleElem.id && toggleElem.id == hdrElem.id && menuElem )			{				var onHdrElem  = document.getElementById(toggleElem.id);				var onMenuElem = menuElem;								onHdrElem.className = this.MENU_HOVER_CLASS;								// register mouseout handler in case they leave before menu displays				registerEventHandler(onHdrElem, 'mouseout', mouseOutHandler);								if (this._skipMenuDisplay) continue;				this._turnOnMenu = function()				{					if ( self._onHdrElemId )					{						self._turnOffMenu();						self._clearOffTimer();					}										self._showMenu(onHdrElem, onMenuElem);						unregisterEventHandler(onHdrElem, 'mouseout', mouseOutHandler);										registerEventHandler(document,   'mousedown', mouseDownHandler);					registerEventHandler(onMenuElem, 'mouseout',  mouseOutHandler);										self._clearOnTimer();					self._onHdrElemId = onHdrElem.id;										self._resetHdrClass(onHdrElem);				};								this._onTimerId = setTimeout('cnPrimaryNavMenuManager._turnOnMenu()', this.MENU_ON_DELAY);								this.turnOffMenuNow = function(disableCompletely)				{					turnOffMenu(onHdrElem, onMenuElem);										self._clearOffTimer();					self._onHdrElemId = null;										if (disableCompletely) this._menuDisabled = true;				};			}			else if ( menuElem && menuElem.style.display == 'block' )			{				var offHdrElem  = hdrElem;				var offMenuElem = menuElem;								this._resetHdrClass(offHdrElem);								if (this._skipMenuDisplay) continue;								this._turnOffMenu = function()				{					turnOffMenu(offHdrElem, offMenuElem);										self._clearOffTimer();					self._onHdrElemId = null;				};								this._offTimerId = setTimeout('cnPrimaryNavMenuManager._turnOffMenu()', this.MENU_OFF_DELAY);			}		}				// define our handler functions to take advantage of closure		function mouseOutHandler(e)		{			var event  = pullEvent(e);			var target = pullTarget(event);			var toElem = pullDestination(event);			if ( !self._skipMenuDisplay && toElem && !isChildOf(toElem, onMenuElem) )			{				var myHdrElem  = onHdrElem;				var myMenuElem = onMenuElem;								if (self._onTimerId) self._clearOnTimer();								self._turnOffMenu = function()				{					turnOffMenu(myHdrElem, myMenuElem);										self._clearOffTimer();				};				self._offTimerId = setTimeout('cnPrimaryNavMenuManager._turnOffMenu()', self.MENU_OFF_DELAY);			}			// no else, just cancel bubbling						self._resetHdrClass(onHdrElem);						if (event.stopPropagation) event.stopPropagation();			else event.cancelBubble = true;		}				function mouseDownHandler(e)		{			var event  = pullEvent(e);			var target = pullTarget(event);				if ( !isChildOf(target, onMenuElem) )			{				turnOffMenu(onHdrElem, onMenuElem);										self._turnOffMenu();				self._clearOffTimer();				self._resetHdrClass(onHdrElem);			}		}				function turnOffMenu(hdrElem, menuElem)		{			hideMenu(hdrElem, menuElem);						unregisterEventHandler(hdrElem,  'mouseout',  mouseOutHandler);			unregisterEventHandler(document, 'mousedown', mouseDownHandler);		}	};				this.preloadImages = function()	{		var preloadImages = this.MENU_PRELOAD_IMAGES;		var tmpLoad       = new Array(preloadImages.length);				for ( var i = 0; i < preloadImages.length; ++i )		{			tmpLoad[i]     = new Image();			tmpLoad[i].src = this.MENU_PRELOAD_URL + preloadImages[i];		}	}		// "private" methods	this._initialize = function ()	{		this._skipMenuDisplay = this._verifyUserAgent();				this._hdrMenuObjs = new Array();				var hdrElems = getElementsByClassNames(this.MENU_GROUP_ID, [this.MENU_OFF_CLASS, this.MENU_ON_CLASS]);				for ( var i = 0; i < hdrElems.length; ++i )		{			var hdrElem   = hdrElems[i];			var hdrElemId = hdrElem.id;						if ( hdrElemId )			{				var menuElem = document.getElementById(hdrElemId + this.MENU_ELEM_SUFFIX);				if ( menuElem )				{					var menuId = menuElem.id;										if (menuId) this._hdrMenuObjs[this._hdrMenuObjs.length] = { hdr: hdrElem, menu: menuElem };										if (hdrElem.className == this.MENU_ON_CLASS) this._activeHdrElemId = hdrElemId;				}			}		}				return;	};		this._resetHdrClass = function (hdrElem)	{		hdrElem.className = (hdrElem.id == this._activeHdrElemId) ? this.MENU_ON_CLASS : this.MENU_OFF_CLASS;	}				this._showMenu = function (hdrElem, menuElem)	{		hdrElem.style.display  = 'none';		menuElem.style.display = 'block';				if ( document.all && navigator.appVersion.indexOf('Win') != -1 )		{			var matId = menuElem.id+'_ie_mat';			var ieMat = document.getElementById(matId);						if ( !ieMat )			{				ieMat = document.createElement('IFRAME');				ieMat.setAttribute('scrolling', 'no');				ieMat.setAttribute('frameborder', 0);				ieMat.setAttribute('src', this.MENU_MAT_SRC);								var menu  = (menuElem.getElementsByTagName('div'))[1];				ieMat.id            = matId;				ieMat.className     = this.MENU_MAT_CLASS;				ieMat.style.width   = menu.offsetWidth;				ieMat.style.height  = menu.offsetHeight;				ieMat.style.zIndex  = menu.style.zIndex - 1;				ieMat.style.display = 'block';												menu.appendChild(ieMat);			}		}	}		this._verifyUserAgent = function()	{		var userAgent = navigator.userAgent;				for ( var i = 0; i < this.MENU_EXCLUDE_USER_AGENTS.length ; ++i )		{			if ( userAgent.indexOf(this.MENU_EXCLUDE_USER_AGENTS[i]) != -1 )			{				return true;			}		}				return false;	};		/** PRIVATE FUNCTIONS (alphabetized) **/		function getElementsByClassNames(rootElemId, classNames)	{		var rootElem         = document.getElementById(rootElemId);			var elements         = new Array();		var captureClassName = new Object();		for ( var i = 0; i < classNames.length; ++i ) captureClassName[classNames[i]] = true;				if (rootElem) _pullElements(rootElem);			function _pullElements(node)		{			if (captureClassName[node.className]) elements[elements.length] = node;						if ( node.hasChildNodes )			{				var children = node.childNodes;								for ( var i = 0; i < children.length; ++i )				{					_pullElements(children[i]);				}			}		}			return elements;	}		function hideMenu(hdrElem, menuElem)	{		hdrElem.style.display  = 'block';		menuElem.style.display = 'none';	}		function isChildOf(node, parentNode)	{		var isChild = parentNode == node;				if ( !isChild && node.parentNode )		{			isChild = isChildOf(node.parentNode, parentNode);		}				return isChild;	}		function pullDestination(e)	{		return (e.relatedTarget) ? e.relatedTarget : (e.toElement) ? e.toElement : null;	}		function pullEvent(e)	{		return (e) ? e : (window.event) ? window.event : null;	}		function pullTarget(e)	{		return (e.target) ? e.target : (e.srcElement) ? e.srcElement : null;	}		function registerEventHandler(elem, event, handler)	{		if ( document.addEventListener )		{			elem.addEventListener(event, handler, false);		}		else if ( document.attachEvent )		{			elem.attachEvent('on'+event,  handler);		}		else // probably on a Mac IE		{			elem['on'+event] = handler;		}	}		function unregisterEventHandler(elem, event, handler)	{		if ( document.removeEventListener )		{			elem.removeEventListener(event, handler, false);		}		else if ( document.detachEvent )		{			elem.detachEvent('on'+event, handler);		}		else // probably on a Mac on IE		{			elem['on'+event] = null;		}	}}// function used for secondary navigationfunction changeClass(elemId, newClass){	var elem = null;		if ( document.getElementById )	{		elem = document.getElementById(elemId);	}	else if ( document.all )	{		elem = document.all[elemId];	}		if (elem) elem.className = newClass;}cnPrimaryNavMenuManager.preloadImages();// end of  Javascript// 