/*
	Main Menu
	
	used to open and close menu items.
	all sub-menus are closed on startup.
	
	id of menu-container must be "nav".
	className: hasActiveSub, hasSub and liselected must be set on li Elements.
	
	--> attributes
	--> helper class
	--> methods
	--> konstruktor

*/

function WL_MainMenu()
{
	/**
	 * id of main menu
	 */
	this.rootElement = "nav";
	
	/**
	 * Element der aktuellen Auswahl
	 */
	this.sel = null;
	
	/**
	 * contains all menu items (Instances of inner helper classs mmItem := {'level':'','hasSub':'HtmlUlElement','element':'HtmlLiElement'}) 
	 */
	this.parents = new Object();
	
	/**
	 * some private statics:
	 */
	this.ROOT = "ROOT";
	this.NO_SUB = "NO_SUB";
	
	/**
	 * innner helper class 
	 * @param parent: id of the parent element ( or this.ROOT)
	 * @param ulDomElement: ul-dom element of submenu ( or this.NO_SUB)
	 * @param liDomElement: li-dom element of this menu item
	 */
	function mmItem(parent, ulDomElement, liDomElement)
	{
		this.level = parent;          // ROOT or id of parent
		this.element = liDomElement;  // li-dom-element of menu item
		this.hasSub = ulDomElement;   // this.NO_SUB or the ul-dom-element of the sub
	}
	

	/**
	 * use force = true to set className hasActiveSub
	 */
	this.togglePicClassName = function(element, force)
	{
		//var tt = element.className;
		var s = element.className.split(/\s+/);
		for(var p=0;p<s.length;p++)
    	{
			if(force!=true)
			{
				if(s[p]== "hasActiveSub")
	    		{
	    			s.splice(p,1);
	    			element.className = s.join(' ')+" hasSub";
	    			//alert("from hasActiveSub to hasSub:\n before: "+tt+"\n after:"+element.className);
	    			break;
	    		}
			}
			if(s[p]== "hasSub")
			{
	    		s.splice(p,1);
    			element.className = s.join(' ')+" hasActiveSub";
    			//alert("from hasSub to hasActiveSub:\n before: "+tt+"\n after:"+element.className);
    			break;
			}
    	}
	}
	
	/**
	 *  open sub menu of item with id == id 
	 * @param id of the element
	 */	
	this.openItem = function(id)
	{
    	this.parents[id].hasSub.style.display = 'block';
    	// alert("open sub: "+id);
    	return;
	}
	
	
	/**
	 * Ein und ausblenden des aktuellen submenues
	 */
	this.toogleItem = function(id)
	{
		try{
			if(this.parents[id].hasSub != this.NO_SUB)
			{
				if(this.parents[id].hasSub.style.display == 'none')
		    	{
		    		this.parents[id].hasSub.style.display = 'block'
		    	}
		    	else
		    	{
		    		this.parents[id].hasSub.style.display = 'none'
		    	}
			}
		}
		catch(E)
		{
			alert("error to toggle element with id: "+id+" error: "+E)
		}
    	// alert("toogle sub: "+id+" to "+this.parents[id].hasSub.style.display);
    	return;
	}

	this.toogleClassName = function(id)
	{
    	return;
	}
	
	/**
	 * closes the root-item of this item
	 * @param id of the element
	 * @param abortLevel wenn beide items im selben Unterbaum hängen, abbruch auf der ebene des zu öffnenden Items 
	 */
	this.closeRootOfItem = function(id, abortLevel)
	{
		var t = id;
    	//goto root (first level item)
    	while(this.parents[t].level != this.ROOT ) 
		{
    		if(abortLevel == this.parents[t].level)
    		{
    			if(this.parents[t].hasSub != this.NO_SUB)  // eigentlich unnoetig?
    			{
    				this.parents[t].hasSub.style.display = 'none';
    				this.togglePicClassName(this.parents[t].element);
    				//this.removeActiveClassName(this.parents[t].element);
    				//alert("close root element "+this.parents[t].element.id+" of "+id+" aborted at: "+this.parents[t].level);
    				return;
    			}
    		}
    		t = this.parents[t].level;
		}
    	this.parents[t].hasSub.style.display = 'none';
    	this.togglePicClassName(this.parents[t].element);
    	//this.removeActiveClassName(this.parents[t].element);
    	// alert("close root element "+this.parents[t].element.id+" of "+id);
    	return;
	}
	
	/**
	 * is id2 parent of id1 (checks up to the root)
	 * @param id1
	 * @param id2
	 * @param parents
	 * @return
	 */
	this.isParentOf = function(id1, id2)
	{
		var t= id1;
		while(this.parents[t].level != this.ROOT ) // ist das hier roobust genug?
		{
			if(this.parents[t].element.id == id2)
			{
				return true;
			}
			t = this.parents[t].level;
		}
		if(this.parents[t].element.id == id2)  // DAS HIER GEHT BESSER !?!?! also ohne dieses if 
		{
			return true;
		}
		return false;
	}

	
	/**
	 * --> fill "parents"
	 * --> uses skip temporary
	 * @param list: li-elements to add
	 * @param level: id of the current parent
	 * @param skip: helper instances, to check an item only once
	 */
	this.initMenuItems = function(list, level, skip)
	{
		var i,e;
		for(i=0;i<list.length;i++)
		{
			if(list[i].id && list[i].id != undefined)
			{ 
				if(skip[list[i].id] == "done")
				{
					continue;
				}
				else if( (e = this.hasSubmenus(list[i]))!= this.NO_SUB)
				{
					this.parents[list[i].id] = new mmItem(level, e, list[i]);
					skip[list[i].id] = "done";
					this.initMenuItems(list[i].getElementsByTagName("li"), list[i].id, skip)
				}
				else
				{
					this.parents[list[i].id] = new mmItem(level, e, list[i]);
					skip[list[i].id] = "done";
				} 
			}
		}
	}
	

	/**
	 * check whether a submenu exist: 
	 * return element.getElementsByTagName("ul")[0] if sub exists 
	 * or this.NO_SUB, if not
	 * 
	 * stopPropagation of the ul Element 
	 * 
	 * Annahme: das erste ul-elemt ist dass richtige !!! 
	 */
	this.hasSubmenus = function(element)
	{
		var l = element.getElementsByTagName("ul");
		if(l && l != undefined && l.length>0)
		{
			return l[0];
		}
		return this.NO_SUB;
	}
	
	/**
	 * debug-method print all menu item id, including assigned parents, sub and dom-element of itself
	 */
	this.showParents = function()
	{
		var s = "";
		for (var key in this.parents)
		{
		    s += key+": "+this.parents[key].level
		    	+" hasSub:"+ (this.parents[key].hasSub != this.NO_SUB) 
		    	+" element:"+this.parents[key].element.id+"\n";
		}
		alert(s);
	}
	
	/**
	 * Name ist Programm
	 */
	this.deactivatePropagationOfA = function(element)
	{
		var i,event, list = element.getElementsByTagName("a");
		for(i=0;i<list.length;i++)
		{
			//if(list[i].hash && list[i].hash.substring(0,1)!= '#')  // Macht das hier überhaupt noch Sinn ? FIXME:
			{
				
				list[i].onclick = function(evt)
				{
					event = window.event || evt;
					if(event!=null)
					{
						 if (event && event.stopPropagation) //if stopPropagation method supported
						 {
							 event.stopPropagation();
							 event.preventDefault();
						 }
						 else 
						 {
							  event.cancelBubble = true;
							  event.returnValue = false;  // ok??? ie
	
						 }
					}
				}
			}
		}
	}

	/**
	 *  Link vom ersten a-Tag wird bei Click auf li geladen...
	 */
	this.loadPage = function(element)
	{
		var list = element.getElementsByTagName("a");
		if(list.length>0 && list[0].href)
		{
			//alert(list[0].href+" "+list[0].target);
			if(list[0].target && "_blank" == list[0].target)
			{
				window.open(list[0].href);
			}
			else
			{
				window.location.href = list[0].href;
			}
		}
	}

	this.handleSelectedElement = function(element)
	{
		try
		{
			// close the root of the current selection, when this.id is parent of selected
			if(element.mm.isParentOf(element.mm.sel.id, element.id))
			{
				//schliese untermenu, da selected unterhalb liegt;
				element.mm.toogleItem(element.id);
				element.mm.togglePicClassName(element.mm.parents[element.id].element);
				element.mm.sel = element;
				//document.getElementById("debug_mm").innerHTML = "mm.sel case 1: "+element.mm.sel.id;  // add debug_mm to frame.jsp to debug
				//alert("test1");
				return true;
	
			}
			else if(element.mm.parents[element.id].level == element.mm.parents[element.mm.sel.id].level)
			{
				// schliese nur selected, da beide auf der selben Ebene sind (nicht bis root schließen) und fahre for (also oeffne angeklicktes)
				element.mm.toogleItem(element.mm.sel.id);
				element.mm.togglePicClassName(element.mm.parents[element.mm.sel.id].element);
				//alert("case 2");
			}
			//else if(element.mm.isParentOf(element.mm.sel.id, element.id)){
			//	alert("do something?")
			//}
			else if(!element.mm.isParentOf(element.id, element.mm.sel.id)) 
			{
				// selected liegt nicht(!) oberhalb von alktuellen, also irgendwo anders: schließe selected
				// schliesse root von selected, da selected ausserhalb liegt
				element.mm.closeRootOfItem(element.mm.sel.id, element.mm.parents[element.id].level);   ///loest tooglePicClassName aus
				//alert("case 3");
			}
		}
		catch(E)
		{
			alert("error handling selected: element:"+element.id+" "+E);
		}
			return false;
			
	}
	
	
	/**
	 * stop propagation
	 */
	this.stopPropagation = function(evt)
	{
		var event = window.event || evt;
		if(event!=null)
		{
			 if (event && event.stopPropagation) //if stopPropagation method supported
			 {
				 event.stopPropagation();
			 }
			 else 
			 {
				  event.cancelBubble = true;
			 }
		}
	}
	
	
	/*
	 * Konstuktor
	 */
	try
	{
		// get all the elements (in nav) that have id as content
		// Ebenen werden hier ignoriert!
		var skip = new Object();  // helper, to hold ids of already checkked elements, to ignore them 
		this.initMenuItems(document.getElementById(this.rootElement).getElementsByTagName("li"), this.ROOT, skip);
		//this.showParents(); // debug
		for (var id in this.parents)
		{
			// reference to  this menu instance
			this.parents[id].element.mm = this;  // referenz auf mm (this) setzen

			// all items with sub-menus...
			if(this.parents[id].hasSub != this.NO_SUB)
			{
				//if(this.parents[id].element.className == null || this.parents[id].element.className.indexOf("hasActiveSub")<0)
				if(this.parents[id].element.className != null && this.parents[id].element.className.indexOf("hasSub")>=0)
				{
					// close all subs on startup (if there is no active className)
					this.parents[id].hasSub.style.display = 'none';
				}
				
				// set onclick handler
				this.parents[id].element.onclick = function(evt)
				{
					if (!evt) var evt = window.event;
					var tg = (window.event) ? evt.srcElement : evt.target;
					//if(tg.nodeName && tg.nodeName.toUpperCase() == 'A')
					//{
					//	return; 
					//}
					if(tg.nodeName && tg.nodeName.toUpperCase() == 'SPAN')  // Inner Link: Foren ungelesenen Zähler; ignore it...
					{
						return; // Abbruch
					}
					
					// Achtung: Hier sind wir im listElement, 
					// also gilt this.mm == main menu instance == this
					this.mm.stopPropagation(evt);
					//this.mm.deactivatePropagationOfA(this.mm.parents[this.id].element);

					if(this.mm.sel == this)
					{
						// just close sub of current selection
						this.mm.toogleItem(this.id);
						this.mm.togglePicClassName(this.mm.parents[this.id].element);

						this.mm.sel = this;
						//document.getElementById("debug_mm").innerHTML = "mm.sel case 0: "+this.mm.sel.id;  // add debug_mm to frame.jsp to debug
						//alert("test0 this.id:"+this.id+"  sel.id:"+this.mm.sel.id);
						return;
					}
					
					if(this.mm.sel!=null)
					{
						if(this.mm.handleSelectedElement(this))  //mm.sel is set inside here, if abort...
						{
							return ;
						}
					}
					// oeffne angeklicktes element
					this.mm.openItem(this.id);
					this.mm.togglePicClassName(this.mm.parents[this.id].element, true); // set this this.id pic to open
					this.mm.sel = this;
					//alert("test4");
					//document.getElementById("debug_mm").innerHTML = "mm.sel case 4: "+this.mm.sel.id;  // add debug_mm to frame.jsp to debug
					
					return;
				}// ende onclick
				
				// bei Klicks auf a-tags keine "Menueaktion" ausloesen ... wirkt wie unkoordiniertes auf und zuklappen
				// Hinweis: hier wird onclick event der a-tags ueberschrieben !?!
				//this.deactivatePropagationOfA(this.parents[id].element);
				// --> war doch nicht gut, da sich Untermenue nicht aufgeklappt hat, wenn es nicht mit Seite verlinkt ist.
			} 
			else // einzelne Menüpunkte
			{
				this.parents[id].element.onclick = function(evt)
				{
					this.mm.deactivatePropagationOfA(this.mm.parents[id].element);
					this.mm.stopPropagation(evt); // unnoetiges Menueverhalten vermeiden
					
					if (!evt) var evt = window.event;
					var tg = (window.event) ? evt.srcElement : evt.target;
					if(tg.nodeName && tg.nodeName.toUpperCase() == 'A')
					{
						return;  // Abbruch
					}
					if(tg.nodeName && tg.nodeName.toUpperCase() == 'SPAN')  // Inner Link: Foren ungelesenen Zähler
					{
						return;  // Abbruch
					}
					
					// das hier ist wohl hinfaellig wg. loadPage(this)
					//if(this.mm.sel!=null)
					//{
					//	this.mm.handleSelectedElement(this);
					//}
					//this.mm.sel = this;
					//document.getElementById("debug_mm").innerHTML = "Blatt mm.sel: "+this.mm.sel.id;  // add debug_mm to frame.jsp to debug
					
					this.mm.loadPage(this);
					
				}
			}
			
			// vorselektieren
			if(this.parents[id].element.className.match(/liselected+/)!=undefined)
			{
				this.sel=this.parents[id].element;
				//document.getElementById("debug_mm").innerHTML = "init: mm.sel: "+this.sel.id;  // add debug_mm to frame.jsp to debug
			}
		}

		// alert(this.sel==null? "null" : this.sel.id);
		// test
		// alert(
		//		this.isParentOf("mmInformation-header", "mmFoyer-header")+"\n"
		//		+this.isParentOf("mmFoyer-header","mmInformation-header")+"\n"
		//		+this.isParentOf("mmFoyer22-header", "mmFoyer-header")+"\n"
		//		+this.isParentOf( "mmFoyer-header", "mmFoyer22-header")+"\n"
		// );
	}
	catch(e)
	{ 
		alert("error while initialization the main menu: "+e);
	}
}

