// start info
if(typeof jsReport != 'undefined'){
	jsVersion = new Array(
	/*Name			=*/ 'Unordered List Dropdown/Foldout Menu.',
	/*Version 		=*/ '0.992',
	/*Date 			=*/ 20030917,
	/*Author		=*/ 'Maurice van Creij',
	/*ProjectCode	=*/ 'list_menu',
	/*Summary		=*/ 'An event driven dropdown- and foldout-menu based on an unordered list (or any other nested tag, like tables).',
	/*Dependencies	=*/ new Array('list_menu.js','list_menu_dropdown.css','list_menu_foldout.css','lib_images.js'),
	/*Browsers		=*/ new Array('MO','IE','OP'),
	/*Changes		=*/ new Array(
						'0.992: Void links are replaced by menu togglers',
						'0.991: Foldout menu\'s can now also use "booUrlSense"',
						'0.99: Added "setListPeers()" to close peers before opening a node.',
						'0.98: Small bug in the default list "arrLists[0]", last element was left out.',
						'0.97: Images without a numeric suffix are now ignored',
						'0.96: Onclick events can still change the image even when "imageevents.js" integration isn\'t used.',
						'0.95: Mouseover effects on the images is now optional (booUseImageCache)',
						'0.94: Optimizes "resetList()", to do less redundant work.',
						'0.93: Optimized "suggestListNode()", for faster performance no complete redraw is issued after a new node id opened',
						'0.92: Added some pre-programmed lists. Fixed a bug in the "breadcrum"-path when multiple lists are used.',
						'0.91: Fixed a bug in the handling of fold-out menus. As a by-product a "breadcrum"-path is constructed on start-up, this can be written to a DIV.',
						'0.9: The "booUrlSense"-feature now compares fragmented URLs for greater accuracy.',
						'0.8: Improved automatic node opener so it won\'t mess up the classes for the parent items as much.',
						'0.7: Added support for manualy setting (open/close) node states through it\'s class.',
						'0.6: Moved event-handling from the HTML to the javascript',
						'0.5: Added optional support for mouseover-icons from "image_events.js"',
						'0.4: Combined functionality for dropdowns and foldouts.',
						'0.3: Url sensing, can open nodes related to the document\'s URL.',
						'0.2: Functional prototype (adjust style).',
					  	'0.1: Basic event handling (open/close nodes).'
					  	),
	/*Usage			=*/ new Array(
							'<div id="listmenu0">',
							'	<ul>',
							'		<li class="listmenu0st0">',
							'			<img border="0" alt="" src="/~wmittensrd/images/spacing.gif" align="middle">',
							'			<a href="index.htm?id=200" >item 20</a>',
							'			<span>description 20</span>',
							'			<ul>',
							'				<li class="listmenu0st0">',
							'					<img border="0" alt="" src="/~wmittensrd/images/spacing.gif" align="middle">',
							'					<a href="index.htm?id=210">item 21</a>',
							'					<span>description 21</span>',
							'				</li>',
							'				<li class="listmenu0st0">',
							'					<img border="0" alt="" src="/~wmittensrd/images/spacing.gif" align="middle">',
							'					<a href="index.htm?id=220">item 22</a>',
							'					<span>description 22</span>',
							'				</li>',
							'				<li class="listmenu0st0">',
							'					<img border="0" alt="" src="/~wmittensrd/images/spacing.gif" align="middle">',
							'					<a href="index.htm?id=230">item 23</a>',
							'					<span>description 23</span>',
							'				</li>',
							'			</ul>',
							'		</li>',
							'	</ul>',
							'</div>',
							'<link rel="StyleSheet" href="list_foldout.css" type="text/css">',
							'<script language="javascript" src="list_menu.js"></script>'
					  	)
	)
}else{
// end info


	// constants/configuration
		if(typeof(strListId)=='undefined')			var strListId			= 'listmenu1';	// name of the list's container
		if(typeof(strListPathId)=='undefined')		var strListPathId		= '';		// optional path to write a breadcrumspath too, use '' to disable
		if(typeof(intListMenuType)=='undefined')	var intListMenuType		= 1;			// type of menu: 0=dropdown, 1=foldout
		if(typeof(strListType)=='undefined')		var strListType			= 'UL';			// type of list used valid: UL | OL | DL | TABLE
		if(typeof(strListItem)=='undefined')		var strListItem			= 'LI';			// type of list item used valid: LI | LI | DT,DD | TR,TD
		if(typeof(booSetClassNames)=='undefined')	var booSetClassNames	= (strListType==strListItem) ? false : true ;	// change classnames for decorative purposes
		if(typeof(booSetExclusive)=='undefined')	var booSetExclusive		= false ;		// Close the peers upon opening a new node
		if(typeof(booUrlSense)=='undefined')		var booUrlSense			= false;			// compare fold-out items href with the document URL.
		if(typeof(fltUrlSenseMin)=='undefined')		var fltUrlSenseMin		= 1.0;			// minimum compare score for compared URLs
														var arrUrlSensePath	= new Array();	// branch of nodes with the active url back to the root
		if(typeof(intRootOffset)=='undefined')		var intRootOffset		= 1;			// recursion after which nodes should be hidden
		if(typeof(intListTimer)=='undefined')		var intListTimer		= 1024			// time to wait before setting a list node
														var objListTimer;					// timeout object for cancelations
														var objListTimerTgt;				// cached target object for timeouts
		if(typeof(arrLists)=='undefined')			var arrLists			= new Array(new Array(strListId,intListMenuType,booUrlSense,fltUrlSenseMin));	// index of multiple menu's
		// "imageevents.js" integration (offers caching and fading)
		if(typeof(booUseImageEvents)=='undefined')	var booUseImageEvents	= (typeof(setImgSrcSuffix)=='function') ? true : false ;		// use imageevents.js to manage list icons
		if(typeof(booUseImageCache)=='undefined')	var booUseImageCache	= false;		// pre-cache images
	// primary functions - functionality
		// compares url's and returns a match score
		function compareUrls(strUrlA,strUrlB){
			var intCurScore = 0;
			var intPotScore = 0;
			var intMaxScore = 0;
			var intA,intB;
			// make sure both paths have domains (because MSIE likes to add it to the "href" in the DOM)
			if(strUrlA.indexOf('http://')==-1) strUrlA = document.location.protocol + '//' + document.location.hostname + '/' + strUrlA;
			if(strUrlB.indexOf('http://')==-1) strUrlB = document.location.protocol + '//' + document.location.hostname + '/' + strUrlB;
			// split the urls into manageable strings
			var arrUrlA = strUrlA.split(/[?&\/]/i);
			var arrUrlB = strUrlB.split(/[?&\/]/i);
			// for every string of UrlA
			for(intA=0; intA<arrUrlA.length; intA++){
				// is the string in the substrings of UrlB
				intB = 0; while(intB<arrUrlB.length && arrUrlA[intA]!=arrUrlB[intB]) intB += 1;
				// if a match was found, add length of string A to current score
				if(intB<arrUrlB.length) intCurScore += arrUrlA[intA].length;
				// add length of string A to potential score
				intPotScore += arrUrlA[intA].length;
			}
			// calcultate ma maximum score possible
			intMaxScore = strUrlB.length - arrUrlB.length + 1;
			// return the compare-score
			return intCurScore/intPotScore;
		}
		// change the src-suffix of a list icon
		function setIconClass(objTarget,intState){
			// get the icon object
			var objImg = objTarget.parentNode.getElementsByTagName('IMG');
			if(objImg.length>0){
				// set the image suffix using "imageevents.js" integration
				if(booUseImageEvents){
					setImgSrcSuffix(objImg[0].id,intState);
				// or set the (even) image suffix manually
				}else if(intState%2==0){
					// get the picture source name
					var strImgUrl = objImg[0].src;
					// split the url
					var arrImgUrl		= strImgUrl.split('.');
					var strImgUrlSuffix = '.' + arrImgUrl[arrImgUrl.length-1];
					var strImgUrlPrefix = strImgUrl.substr(0,strImgUrl.length-(strImgUrlSuffix.length)-1);
					var intImgUrlDigit	= parseInt(strImgUrl.substr(strImgUrlPrefix.length,1));
					if(!isNaN(intImgUrlDigit)){
						// construct a new url
						strImgUrl = strImgUrlPrefix + intState + strImgUrlSuffix;
						// give the picture a new source name, if it's not the same as the old one
						if(objImg[0].src != strImgUrl) objImg[0].src = strImgUrl;
					}
				}
			}
		}
		// change the class-suffix of a list node
		function setListClass(objTarget,intOffset,booNoOffset){
			var strLIclass, intLIsuffix;
			// get the class name
			strLIclass		= objTarget.parentNode.className;
	//alert(strLIclass)		
			// is there a classname?
			if(strLIclass!=null && strLIclass!=''){
				// get the class suffix
				intLIsuffix	= parseInt(strLIclass.substr(strLIclass.length-1,1));
				// add the offset to the suffix or take the offset as an absolute value
				intLIsuffix	= (booNoOffset) ? intOffset : intLIsuffix+intOffset;
				// get the class prefix
				strLIclass	= strLIclass.substr(0,strLIclass.length-1);
				// change the target's class
				if(booSetClassNames) objTarget.parentNode.className = strLIclass + intLIsuffix;
				// change the icon's state if changeable icons are found
				setIconClass(objTarget,intLIsuffix);
			}
		}
		// open/close a list node
		function setListNode(objTarget,booNodeState){
			var intLIclass;
			// get the children of the parent node
			var objULs = objTarget.parentNode.getElementsByTagName(strListType);
			// does the parent node have an UL child
			if(objULs.length>0){
				// if no node state if given, toggle
				if(typeof(booNodeState)=='undefined') booNodeState = (objULs[0].style.display=='none' || objULs[0].style.display=='');
				// display or hide it
				objULs[0].style.display = (booNodeState) ? 'block' : 'none';
				// choose the parent class
				intLIclass = (booNodeState) ? 6 : 4 ;
			}else{
				// if no node state assume a value
				if(typeof(booNodeState)=='undefined') booNodeState = false;
				// choose the parent class
				intLIclass = (booNodeState) ? 2 : 0 ;
			}
			// change parent class
			setListClass(objTarget,intLIclass,true);
		}
		// open/close a list node after a delay
		function suggestListNode(objTarget,booNodeState){
			// clear the last running timeout
			clearTimeout(objListTimer);
			// if no node state if given, toggle
			if(typeof(booNodeState)=='undefined'){
				var objNode = objTarget.parentNode.getElementsByTagName(strListType)[0];
				booNodeState = (objNode.style.display=='none' || objNode.style.display=='');
			}
			// set a delayed node change
			if(booNodeState){
				// get the peers to the new list node
				var objTargetPeers = objTarget.parentNode.parentNode.childNodes;
				// for all peers
				for(var intA=0; intA<objTargetPeers.length; intA++){
					if(objTargetPeers[intA].nodeName==strListItem){
						// close the node
						setListNode(objTargetPeers[intA].firstChild,false);
					}
				}
				// open the new list node
				setListNode(objTarget,true);
			}else{
				// find the root Id of the item
				var objRoot = objTarget.parentNode;
				while(objRoot.nodeName==strListType || objRoot.nodeName==strListItem){
					objRoot = objRoot.parentNode;
				}
				var strRoot = objRoot.id;
				// set a timed close request
				objListTimerTgt = objTarget.parentNode;
				objListTimer = setTimeout("resetList(false,'"+strRoot+"',1)",intListTimer);
			}
		}
		// closes a node's peers before opening a new one
		function setListPeers(objTarget,booNodeState){
			// if no node state if given, toggle
			if(typeof(booNodeState)=='undefined'){
				var objNode = objTarget.parentNode.getElementsByTagName(strListType)[0];
				booNodeState = (objNode.style.display=='none' || objNode.style.display=='');
			}
			// get the peers to the new list node
			var objTargetPeers = objTarget.parentNode.parentNode.childNodes;
			// for all peers
			for(var intA=0; intA<objTargetPeers.length; intA++){
				if(objTargetPeers[intA].nodeName==strListItem){
					// close the node
					setListNode(objTargetPeers[intA].firstChild,false);
				}
			}
			// open the new list node
			setListNode(objTarget,booNodeState);
		}
		// opens/closes all list nodes
		function resetList(booNodeState,strNodeId,intMenuType){
			// use the default root Id if none was given
			if(typeof(strNodeId)=='undefined') strNodeId = strListId;
			// use the default menu-type if none was given
			if(typeof(intMenuType)=='undefined') intMenuType = intListMenuType;
			// get all nodes
			var objULs = document.getElementById(strNodeId).getElementsByTagName(strListType);
			// for all nodes (except the root)
			for(var intA=intRootOffset; intA<objULs.length; intA++){
				// set the node to the given state
				objULs[intA].style.display = (booNodeState) ? 'block' : 'none';
			}
			// reset all node styles
			if(objListTimerTgt!=null){
				setListNode(objListTimerTgt.firstChild,false);
				cascadeList(objListTimerTgt,false,intMenuType);
			}
			// highlight the active item root
			if(booUrlSense && arrUrlSensePath.length>0){
				// get the root item of the active item
				objNodeRoot = arrUrlSensePath[arrUrlSensePath.length-1];
				// check if the item has child items
				intNodeState = (objNodeRoot.getElementsByTagName(strListType).length>0) ? 6 : 2 ;
				// if the list id's matches
				if(objNodeRoot.parentNode.parentNode.id==strNodeId) setListClass(objNodeRoot.firstChild,intNodeState,true);
			}
		}
		// cascade back up the hierarchy to open all list nodes
		function cascadeList(objLI,booDisplay,intMenuType){
			// fetch the parent item
			var objParent = objLI.parentNode.parentNode;
			// store the current node in a list
			if(booDisplay) arrUrlSensePath[arrUrlSensePath.length] = objLI;
			// change the class of the LI
			setListNode(objLI.firstChild,booDisplay);
			// recurse if the parent item of this LI is also a LI
			if(objParent.nodeName==strListItem) cascadeList(objParent,booDisplay,intMenuType);
		}
	// secondary function - construction
		// convert the stored path of nodes into a breadcrums trail
		function getListBranch(){
			var arrListBranch = arrUrlSensePath.reverse();
			var strListBranch = ''; //'<a href="/">home</a>&nbsp;&gt;&nbsp;';
			// for every LI in the list branch
			for(var intA=0; intA<arrListBranch.length; intA++){
				// get it's href
				objAs = arrListBranch[intA].getElementsByTagName('A');
				strListUrl = (objAs.length>0) ? objAs[0].getAttribute('href') : '#' ;
				// get it's title
				strListTitle = (objAs.length>0) ? objAs[0].firstChild.nodeValue : '' ;
				// make link
				strListBranch += '<a href="'+strListUrl+'">'+strListTitle+'</a>';
				// add path marker
				strListBranch += (intA<arrUrlSensePath.length-1) ? '&nbsp;&gt;&nbsp;' : '' ;
			}
			// return the breadcrums
			return strListBranch;
		}
		// go through the UL's, add the click events and modify styles where appropriate
		function evalList(objMenuRoot,intMenuType,booSenseUrl,fltSenseUrlMin){
			var strListUrl, strDocUrl, strListClass, intListClass, objIMGs, objAs, objULs, objLIs;
			var arrUrl = new Array();
			// use the default menu Id if none was given
			if(typeof(objMenuId)=='undefined') objMenuRoot = document.getElementById(strListId);
			// use the default menu type if none was given
			if(typeof(intMenuType)=='undefined') intMenuType = intListMenuType;
			// use the default URL sense if none was given
			if(typeof(booUrlSense)=='undefined') booUrlSense = booListSense;
			// get the document's URL
			strDocUrl = document.location.href	// alt: document.location.pathname + document.location.search;
			// get all the LI's in this menu
			objLIs = objMenuRoot.getElementsByTagName(strListItem);
			// for every LI in this menu
			for(var intA=0; intA<objLIs.length; intA++){
				// get the class of this LI
				strListClass = (objLIs[intA].className!=null) ? objLIs[intA].className : '' ;
				intListClass = parseInt(strListClass.substr(strListClass.length-1,1));
				// for all IMG in this LI
				objIMGs = objLIs[intA].getElementsByTagName('IMG');
				if(objIMGs.length>0){
					// set the onclick event
					objIMGs[0].onclick = toggleListNode;
					// give the image an id if it hasn't got one
					if(objIMGs[0].id=='') objIMGs[0].id = 'listmenu' + Math.round(Math.random()*10000) + 'icon' + intA;
					// cache it's states
					if(booUseImageEvents && booUseImageCache) cacheImgSrcSuffix(objIMGs[0].id,0,1,2,3,4,5,6,7);
				}
				// for all A in this LI
				objAs = objLIs[intA].getElementsByTagName('A');
				if(objAs.length>0){
					// get the list item's href
					strListUrl = objAs[0].getAttribute('href');
					// void links are replaced by menu togglers
					if(strListUrl=='javascript:{}' || strListUrl=='#' || strListUrl==''){
						objAs[0].setAttribute('href','javascript:{}');
						objAs[0].onclick = toggleListNode;
					}
					// compare the href to the url
					arrUrl[arrUrl.length] = (booSenseUrl) ? new Array(compareUrls(strListUrl,strDocUrl)*compareUrls(strDocUrl,strListUrl),objLIs[intA]) : 0 ;
					// set the events
					switch(intMenuType){
						case 1 :
							objAs[0].onmouseover = openListNode;
							objAs[0].onmouseout = closeListNode;
							objAs[0].onfocus = openListNode;
							break;
						default : 
							objAs[0].onmouseover = overListNode;
							objAs[0].onmouseout = outListNode;
							objAs[0].onkeypress = keyListNode;
					}
				}else{
					strListUrl = 'none'
				}
				// for all UL in this LI
				objULs = objLIs[intA].getElementsByTagName(strListType);
				if(objULs.length>0){
					// change it's class (to parent)
					setListClass(objLIs[intA].firstChild,4,true);
				}else{
					// change it's class (to child)
					setListClass(objLIs[intA].firstChild,0,true);
				}
				// open the node with an 'openened' class-suffix (2 or 6)
				if(intListClass==6 || intListClass==2) cascadeList(objLIs[intA],true,intMenuType);
			}
			// open the node with the correct url (booUrlSense)
			if(booSenseUrl){
				arrUrlSensePath = new Array();
				arrUrl = arrUrl.sort().reverse();
				// if the most likely url's score is high enough
				if(arrUrl!=""){
					if(arrUrl[0][0]>=fltSenseUrlMin){
						cascadeList(arrUrl[0][1],true,intMenuType);
						if(intMenuType==1) resetList(false,objMenuRoot.id,intMenuType);
					}
				}
			}
		}
	// ternary function - operation 
		// use the keyboard to toggle focused nodes
		function keyListNode(e){
			ascVal = (document.all) ? event.keyCode : e.which ;
			if(ascVal!=0){
				if(intPeerHandling>0){
					setListPeers(this);
				}else{
					setListNode(this);
				}
			}
		}
		// toggle the object's node
		function toggleListNode(){
			if(booSetExclusive){
				setListPeers(this);
			}else{
				setListNode(this);
			}
		}
		// open the object's node
		function openListNode(){
			suggestListNode(this,true);
		}
		// close the object's node
		function closeListNode(){
			suggestListNode(this,false);
		}
		// highlight the list node
		function overListNode(){
			setListClass(this,1);
		}
		// unlight the list node
		function outListNode(){
			setListClass(this,-1);
		}
		// startup sequence
		function startList(){
			// if the browser supports the DOM
			if(typeof(document.getElementById)!='undefined'){
				// for all menu's listed
				for(var intA=0; intA<arrLists.length; intA++){
					// get the menu object
					objMenuId = document.getElementById(arrLists[intA][0]);
					// if the object exists
					if(objMenuId!=null){
						// get the menu type
						intMenuType = arrLists[intA][1];
						// get the URL sense option
						booSenseUrl =  arrLists[intA][2];
						fltSenseUrlMin =  arrLists[intA][3];
						// set all classes to default
						evalList(objMenuId,intMenuType,booSenseUrl,fltSenseUrlMin);
						// fill the optional list path
						if(strListPathId!='' && booSenseUrl && intMenuType==0)  document.getElementById(strListPathId).innerHTML = getListBranch();
					}
				}
			}
		}
	// executed inline
		// browser specific fixes
//		if(navigator.userAgent.indexOf('Gecko')>-1) document.writeln("<style>#listmenu1 ul ul {margin-top : -20px}</style>");
//		if(navigator.userAgent.indexOf('MSIE')>-1 && navigator.userAgent.indexOf('Mac')>-1) document.writeln("<style>#listmenu0 ul li a {line-height : normal; width : auto;}</style>");
		if(navigator.userAgent.indexOf('MSIE 5.0')>-1 && navigator.userAgent.indexOf('Mac')==-1) document.writeln("<style>#listmenu1 ul ul {left:-18px;}#listmenu1 ul ul li {margin : 0px 0px -3px 0px;}</style>");
		// preprogrammed lists
    	arrLists[arrLists.length] =	new Array('listmenu4',0,true,1);
		//arrLists[arrLists.length] =	new Array('gallery0',2,true,1);
		// startup at load
		startList();

}
