/************************************************************************************************************************
* jonathan a. griffioen 
* Dynamic menu script
*************************************************************************************************************************
* Generally used functionality:
************************************************************************************************************************/

Array.prototype.find = function (element) {
// Finds a record in an array (needle in a haystack).
	for (var keys in this) {
		if (this[keys] == element) {
			return keys;
			break;
		}  
	}
	return false;
};

//  Browser detection
var chkAgent1 = navigator.userAgent;
   var IE = chkAgent1.search(/MSIE/i);

if(IE < 0) {

	IE = false;
}


/************************************************************************************************************************
* Instance prototype:
*************************************************************************************************************************
* To enable the script to be used multiple times on one page, this prototype has been created so that the generated
* menu can link  back to its own object.
************************************************************************************************************************/

DMInstance = function() {
//	The prototype.
	this.DMinstance				= new Array();
	
	this.ObjCurrentItem			= '';

	this.class_menuCat			= "menuCat";
	this.class_subLink			= "subLink";
	this.class_menuBranch		= "menuBranch";
	this.class_topMenuBranch	= "topMenuBranch";
	this.class_active			= "dmActive";
}

DMInstance.prototype.newDM = function(DMID) {

//	The Menu creator, this function is called to create a new menu:
//	Example: newMenu = dMInstance.newDM('divElement');
	this.DMinstance[DMID] =  new DynamicMenu(DMID);
	this.DMinstance[DMID].discoverMenuNodes('');

	this.activeLinkId	  = '';

	return this.DMinstance[DMID];
}

DMInstance.prototype.fetchDM = function(DMID) {
//	Returns a menuinstance by id.

	return this.DMinstance[DMID];
}


DMInstance.prototype.currentDM = function(currentObj) {
	
	currentDivId = currentObj.id;
	
	while(!this.fetchDM(currentDivId)) {

		currentObj = currentObj.parentNode;
//alert(currentObj);
		if(currentObj.id) {
			currentDivId = currentObj.id
		}
	}
	
	currentDivId = currentObj.id;
	currentObj   = null;
	
	return currentDivId;
}


DMInstance.prototype.setActiveElement = function(DMID, elementId) {
// Funcion that sets/unsets the classname of a subelement after it has been clicked.
	if(this.activeLinkId != '') {

		objLastElementId 			= document.getElementById(this.activeLinkId);
		objLastElementId.className  = this.class_subLink;
	}

	objElementId 					= document.getElementById(elementId);
	objElementId.className 			= this.class_subLink + " " + this.class_active;
	this.activeLinkId 				= elementId;

	objElementId 					= null;
	objLastElementId 				= null


}
if(typeof( window['dMInstance'] ) == "undefined" ) {
	dMInstance = new DMInstance;
}
/************************************************************************************************************************
* Functionality prototype:
*************************************************************************************************************************
* The main part of the script.
************************************************************************************************************************/

function DynamicMenu(divId) {
//	The main prototype.
	this.arrMenuItems 			= new Array();
	this.arrMenuCategories		= new Array();
	this.menuItemIndex 			= 0;
	this.divId					= divId;
	this.objCount				= 0;
	this.activeLink				= false;

	this.class_menuCat			= "menuCat";
	this.class_subLink			= "subLink";
	this.class_menuBranch		= "menuBranch";
	this.class_topMenuBranch	= "topMenuBranch";
	this.class_click			= "dm_click";

}

DynamicMenu.prototype.discoverMenuNodes = function(objStartNode) {
//	This function browses recursively through the menu, sets classes, id's, and attaches events.
	if(objStartNode == '') {

		objStartNode = document.getElementById(this.divId);
	}

	var childNodes 		 = objStartNode.childNodes;
	var lengthChildNodes = childNodes.length;
	var activeObj		 = '';
	
    for (var i=0; i < lengthChildNodes; i++) {

		var currentObj = childNodes[i];

		switch(currentObj.nodeName.toLowerCase()) {

			case 'a':
				// attachevent
				this.objCount++;
				currentObj.id = this.divId + this.objCount;
	    		currentObj.divId = this.divId;
				this.attachNodeEvent(currentObj);

				if(currentObj.className == 'show') {					
					activeObj = currentObj;
				}
				
				if(currentObj.parentNode.parentNode.parentNode.nodeName=="DIV") {

					currentObj.className = this.class_menuCat;
					this.arrMenuCategories[this.arrMenuCategories.length] = currentObj;
				}
				else
				{
					currentObj.className = this.class_subLink;
				}

				break;
			case 'ul':
				// explore, attach id, attach class
				currentObj.id = this.class_menuBranch +'_' + this.divId + this.objCount;
				if(this.objCount > 0)
				{
					currentObj.className = this.class_menuBranch + ' hide';
					this.arrMenuItems[this.arrMenuItems.length] = currentObj;
				}
				else
				{
					currentObj.className = this.class_topMenuBranch;
				}
			case 'li':
				// explore
				this.discoverMenuNodes(currentObj);
				break;
		}
	}

	if(activeObj != '') {
		this.expandBranch(activeObj);
		activeObj	 = null;		
	}
	
	objStartNode = null;
	currentObj   = null;
}

DynamicMenu.prototype.expandBranch = function(currentObj) {
//	This function expands a whole 'node tree' in the menu to the point of a given object.
	while(currentObj.parentNode.parentNode.nodeName!="DIV") {
		oldClassName  = currentObj.className;
		currentObj.className = oldClassName.replace(' hide', ' show');
		currentObj = currentObj.parentNode;
	}
	
	if(currentObj.getElementsByTagName('a').length) {
		currentObj.getElementsByTagName('a')[0].className  = this.class_menuCat +" "+this.class_click;
	}
		
	currentObj   = null;
}

DynamicMenu.prototype.collapseExpandAll = function(CEAction) {
//	Collapses/Expands the whole menu.
	if(CEAction == 'expand') {
		$newClassTag = ' show';
		$oldClassTag = ' hide';
	} else {
		$newClassTag = ' hide';		
		$oldClassTag = ' show';
	}
	
	var numberOfSubnodes = this.arrMenuItems.length;
	
	for(i=0; i < numberOfSubnodes; i++) {
		currentObj = this.arrMenuItems[i];
		currentObj.className = currentObj.className.replace($oldClassTag, $newClassTag);		
	}
	
	var numberOfCategories = this.arrMenuCategories.length;
	
	for(i=0; i < numberOfCategories; i++) {
		currentObj = this.arrMenuCategories[i];

		if(CEAction == 'expand') {
	
			currentObj.className = this.class_menuCat +" "+this.class_click;
		}
		else {
	
			currentObj.className = this.class_menuCat;
		}
	}
	currentObj	  = null;
}

DynamicMenu.prototype.collapseBranches = function(objBranch) {
//	Collapses all branches.

	$newClassTag = ' hide';		
	$oldClassTag = ' show';

	if(!objBranch) {
		
		return false;
	}
	
	var numberOfCategories = objBranch.parentNode.parentNode.childNodes.length;
	
	for(i=0; i < numberOfCategories; i++) {

		currentObj 		= objBranch.parentNode.parentNode.childNodes[i];
		currentMenuObj	= document.getElementById('menuBranch_'+currentObj.id);		
				
		if(currentObj.nodeName.toLowerCase() == 'li') {

			i2 = 0;
			
			nrOfChildNodes = currentObj.childNodes.length;
			tagetAnchorObj = false;
			
			while(i2 < nrOfChildNodes && !tagetAnchorObj) {
				
				if(currentObj.childNodes[i2].nodeName.toLowerCase() == 'a')
				{
					
					tagetAnchorObj = currentObj.childNodes[i2];
				}
				i2++;	
			}
			
			if(!tagetAnchorObj){
				
				return false;
			}

			targetMenuObj					= document.getElementById('menuBranch_'+tagetAnchorObj.id);		

			tagetAnchorObj.className 		= tagetAnchorObj.className.replace(' '+this.class_click, '');
	
			if(targetMenuObj) {
				
				targetMenuObj.className  	= targetMenuObj.className.replace($oldClassTag, $newClassTag);			
			}
			
		}
	}
	
	currentObj	   = null;
	currentMenuObj = null;
}

DynamicMenu.prototype.attachNodeEvent = function(objNode) {
//	The attachevent function
	if (IE) {
	//  If Internet Explorer.
		objNode.attachEvent( "onclick", toggleInvis);
	} else {
    //  If Gecko.
		objNode.addEventListener( "click",toggleInvis, false);
	}

	objNode = null;
}

function toggleInvis(evt) {

	this.class_menuCat			= "menuCat";
	this.class_subLink			= "subLink";
	this.class_menuBranch		= "menuBranch";
	this.class_topMenuBranch	= "topMenuBranch";
	this.class_click			= "dm_click";

//	The onClick event of every anchor in the menu. 
//	This hides/shows the subtree of a menuitem and sets apropriate classes.
	if(IE) {
	  var objTarget = event.srcElement;
	} else {
	  var objTarget = evt.currentTarget;
	}

	dmCurrent = dMInstance.currentDM(objTarget);
	dMObj     = dMInstance.fetchDM(dmCurrent);
	objBranch = document.getElementById(this.class_menuBranch + '_' + objTarget.id);
	
	if(objTarget.className == this.class_menuCat) {

	 	dMObj.collapseBranches(objTarget);
		
		objTarget.className = this.class_menuCat +" "+this.class_click;
	}
	else if(objTarget.className == this.class_menuCat +" "+this.class_click) {

		objTarget.className = this.class_menuCat;
	}
	else {

		dMInstance.setActiveElement(objTarget.divId, objTarget.id);
	}

	if(!objBranch) {

		return false;
	}

	oldClassName = objBranch.className;

	if(objBranch.className == this.class_menuBranch + " hide") {

  		dMObj.collapseBranches(objBranch);
  		dMObj.expandBranch(objBranch);	

		this.ObjCurrentItem	 = objBranch;

		objBranch.className = oldClassName.replace(' hide', ' show');
	}
	
	objBranch    = null;
	objTarget    = null;
	oldClassName = null;
	dMObj		 = null;
}

// END OF FILE

