//--------------------------------------------------------------------
// Javascript-Menu Klasse
//--------------------------------------------------------------------
// An ein statistsches Grundmenu (nur oberste Hierarchie) 
// werden die Untermenupunkte via Javascript angehängt
//
// Parameter:
// containerId:   Id des Containers des statischen Menus, an welches 
//                das JsMenu angedockt wird (z.B. 'divMenuMiddle' 
//                oder 'divTopnav')
// jsMenuId:      Id des Javascript-Menus 
//                (z.B. 'divJsMenu', siehe menuxjs.xsl)
// eventTag:      Tag-Typ des statischen Menus, über welchen das JsMenu 
//                aktiviert werden soll (z.B. 'ul' oder 'td')
// delay:         Einblend-Verzögerung fürs Menu
// offsetX:       Linker Abstand vom Einstiegs-Menupunkt 
// offsetY:       Oberer Abstand vom Einstiegs-Menupunkt
// positioning:   Ausgangselement vom Einstiegs-Menu für absolute Positionierung: 
//                self:     Einstiegsmenupunkt 
//                parent:   1. Elternelement 
//                absolute: 1. absolut positioniertes Elternelement
// autoHideDelay: Ausblendverzögerung
//--------------------------------------------------------------------
function JsMenu(containerId, jsMenuId, eventTag, delay, offsetX, offsetY, positioning, autoHideDelay) {
	var itemIdTemplate = "itemMenuJs{0}_{1}";  // Id-Schablone eines Menupunktes
	var topSearchClass = /\bslidingmenu\b/;  // Suchschema für Klassennamen
	if(!delay) delay = 500;
	if(!offsetX) offsetX = 0;
	if(!offsetY) offsetY = 0;
	if(!autoHideDelay) autoHideDelay = 2000; // muss grösser als delay sein!
	
	// Menu-Objekt via Basisklasse instanzieren
	var jsM = new JsMenuBase(containerId, jsMenuId, eventTag)

	this.getMoverFor = function(node) {return function(e) { jsM.mover(e, node); }; };
	
	this.getMoutFor = function(node) {return function(e) { jsM.mout(e, node); }; };

	// JsMenu-MouseOver-Funktion (wird via Timer verzögert aufgerufen)
	this.mover2 = function(el) {
		// Alle ul-Unterelemente anzeigen
		for (var i = 0; i < el.childNodes.length; i++) {
			var node = el.childNodes[i];
			if (node.nodeName.toLowerCase() == 'ul' && node.style.display != 'block') {
				node.style.display = 'block';
			}
		}
	};
	
	// JsMenu-MouseOut-Funktion (wird via Timer verzögert aufgerufen)
	this.mout2 = function(el) {
		// ul-Hauptelement verstecken
		if (el.nodeName.toLowerCase() == 'ul') {
			el.style.display = 'none';
		}
		// Alle ul-Unterelemente verstecken
		for (var i = 0; i < el.childNodes.length; i++) {
			var node = el.childNodes[i];
			if (node.nodeName.toLowerCase() == 'ul' && node.style.display != 'none') {
				node.style.display = 'none';
			}
		}
	};
	
	// Statistisches Menu MouseOver-Funktion (wird via Timer verzögert aufgerufen)
	this.mnuMover2 = function(el) {
		var mnu = getMnuItem(el)

		if(!mnu) return;

		if(mnu && mnu.style.display != 'block')	{
			mnu.style.position = 'absolute';
			switch(positioning) {
				case 'absolute':
					var position = getPosition(el);
					mnu.style.left = position[0] + offsetX + 'px';
					mnu.style.top = position[1] + offsetY + 'px';
					break;
				case 'parent':
					mnu.style.top = el.parentNode.offsetTop + offsetY + 'px';
					if(navigator.userAgent.toLowerCase().indexOf('safari')!=-1)
					{
						var version = navigator.appVersion.match(/Safari\/([0-9]*)./);
						if(version.length > 0 && version[1] <= '420')
						{
							// bei Safari Version < 3 fuer offsetTop nicht Parent- sondern aktuellen Node nehmen!!!
							mnu.style.top = el.offsetTop + offsetY + 'px';
						}
					}
					else
					{
						mnu.style.top = el.parentNode.offsetTop + offsetY + 'px';
					}
					mnu.style.left = el.parentNode.offsetLeft + offsetX + 'px';
					break;
				default:
					mnu.style.left = el.offsetLeft + offsetX + 'px';
					mnu.style.top = el.offsetTop + offsetY + 'px';
					break;
			}
			mnu.style.display = 'block';
		}
	};
	
	// Statistisches Menu MouseOut-Funktion (wird via Timer verzögert aufgerufen)
	this.mnuMout2 = function(el) {
		var mnu = getMnuItem(el)
		if(mnu && mnu.style.display != 'none')	{
			mnu.style.display = "none";
		}
	};
	
	this.getMnuMoverFor = function(node) {
		return function(e) { jsM.mnuMover(e, node); };
	};

	this.getMnuMoutFor = function(node) {
		return function(e) { jsM.mnuMout(e, node); };
	};

	function hideAllMnu(withoutEle) {
		var menu = document.getElementById(jsMenuId);
		var uls = menu.getElementsByTagName('ul');
		for (var u = 0; u < uls.length; u++) {
			if (uls[u].className.search(topSearchClass) == -1) continue;
			var ul = uls[u];
			if(withoutEle && ul.id != withoutEle.id || !withoutEle)
			{
				if(ul.style.display != 'none') ul.style.display = 'none';
			}
		}	
	}	
		
	// Ermöglichung des Zugriffs auf die aktuelle JsMenu-Klasse aus der Basisklasse heraus
	jsM.superClass = this;

	this.init = function() {
		jsM.baseInit();
	}

	// liefert zum aktuellen statischen Menupunkt das JsMenu-Einstiegselement
	function getMnuItem(mnuEl) {
		// Id-Zahl des aktuellen eventTags bestimmen
		var idMatches = mnuEl.id.match(/\d+/g);
		if(idMatches) {
			// Ev. sichtbares Javascipt-Menu ausblenden
			// Javascript-Menu für diese Id anzeigen
			var mnuId = itemIdTemplate
			if(idMatches.length > 1) {
				mnuId = mnuId.replace('{0}', idMatches[0]) // Menu-Nummer
				mnuId = mnuId.replace('{1}', idMatches[1]) // Item-Nummer
			} else {
				mnuId = mnuId.replace('{0}', '') // Menu-Nummer
				mnuId = mnuId.replace('{1}', idMatches[0]) // Item-Nummer
			}
			return document.getElementById(mnuId);
		}
		return null;
	}
	

	// Liefert die absolute x,y-Position eines Elements
	function getPosition(node) {
		var posX = posY = 0;
		if(node.offsetParent) {		
			posX = node.offsetLeft;
			posY = node.offsetTop;
			while(node = node.offsetParent) {
//				if(node.style.position == "absolute") break;
				posX += node.offsetLeft;
				posY += node.offsetTop;
			}
		}
		return [posX, posY]
	}
	

	//--------------------------------------------------------------------
	// Basisklasse für JsMenu
	// Liefert Grundfunktionalität auf welcher die JsMenu-Klasse aufbaut
	// Struktur ist notwendig, wegen der verschachtelten Aufrufe von
	// Klassen-Methoden innerhalb von Klassen-Methoden
	//--------------------------------------------------------------------
	function JsMenuBase(containerId, jsMenuId, eventTag) {
		this.containerId = containerId;
		this.eventTag = eventTag;
		this.jsMenuId = jsMenuId;

		// JsMenu-MouseOver
		this.mover = function(e, targetElement) {
			var el = window.event ? targetElement : e ? e.currentTarget : null;
			if (!el) return;
			clearTimeout(el.outTimeout);
			el.overTimeout = setTimeout(function() { jsM.superClass.mover2(el); }, 300);

			// Autom. Ausblenden deaktivieren
			var menu = document.getElementById(containerId);
			var mnuItems = menu.getElementsByTagName(eventTag);
			for (var i = 0; i < mnuItems.length; i++) {
				var node = mnuItems[i];	
				if (node.nodeName.toLowerCase() == eventTag) {
					clearTimeout(node.mnuOutTimeout);
				}
			}
			
		};

		// JsMenu-MouseOut
		this.mout = function(e, targetElement) {
			var el = window.event ? targetElement : e ? e.currentTarget : null;
			if (!el) return;
			el.outTimeout = setTimeout(function() { jsM.superClass.mout2(el); }, 300);
		};

		// Statisches Menu MouseOver: Javascript-Menu anzeigen 
		this.mnuMover = function(e, targetElement) {
			var el = window.event ? targetElement : e ? e.currentTarget : null;
			if (!el) return;
			clearTimeout(el.mnuOutTimeout);

			// ev. bereits ausgelöste andere Menuanzeige-Events wieder löschen
			var menu = document.getElementById(containerId);
			var mnuItems = menu.getElementsByTagName(eventTag);
			for (var i = 0; i < mnuItems.length; i++) {
				var node = mnuItems[i];	
				if (node.nodeName.toLowerCase() == eventTag && node.id.search(/forMenuJs/) != -1) {
					if(el.id.match(/\d+/g) != node.id.match(/\d+/g)) {
						clearTimeout(node.mnuOverTimeout);
					}
				}
			}

			// Verzögertes Einblenden des Menus
			el.mnuOverTimeout = setTimeout(function() { jsM.superClass.mnuMover2(el); }, delay);
		};
	
		// Statisches Menu MouseOut: Javascript-Menu ausblenden 
		this.mnuMout = function(e, targetElement) {
			var el = window.event ? targetElement : e ? e.currentTarget : null;
			if (!el) return;
			// ev. bereits ausgelöstes Menuanzeige-Event wieder löschen
			clearTimeout(el.mnuOverTimeout);
			// Vollständiges Ausblenden des Menus			
			el.mnuOutTimeout = setTimeout(function() { jsM.superClass.mnuMout2(el); }, autoHideDelay);
		};

		// Initialisierung: Fügt die Events an die entsprechenden Elemente
		this.baseInit = function() {
			// Eventhandler für Javascript-Menu definieren
			var menu = document.getElementById(this.jsMenuId);
			if (!menu) return;
			var uls = menu.getElementsByTagName('ul');
			if (!uls) return;
			for (var u = 0; u < uls.length; u++) {
				var node = uls[u]
				if (node.className.search(topSearchClass) == -1) continue;
				node.style.display = 'none';
				addEvent(node, 'mouseover', this.superClass.getMoverFor(node), false);
				addEvent(node, 'mouseout', this.superClass.getMoutFor(node), false);
				// Untermenu ebenfalls beachten
				var lis = node.getElementsByTagName('li');
				for (var i = 0; i < lis.length; i++) {
					var node = lis[i];
					if (node.nodeName.toLowerCase() == 'li' &&
						node.getElementsByTagName('ul').length > 0) {          
						addEvent(node, 'mouseover', this.superClass.getMoverFor(node), false);
						addEvent(node, 'mouseout', this.superClass.getMoutFor(node), false);
						node.getElementsByTagName('a')[0].className += ' subheader';
					}
				}
			}  
			
			// Eventhandler für statisches Menu definieren
			// bei jedem 'eventTag'-mouseover wird das entsprechende
			// Javascript-Menu eingeblendet
			var menu = document.getElementById(containerId);
			var mnuItems = menu.getElementsByTagName(eventTag);
			for (var i = 0; i < mnuItems.length; i++) {
				var node = mnuItems[i];	
				if (node.nodeName.toLowerCase() == eventTag && node.id.search(/forMenuJs/) != -1) {
					// Bei aufgeklapptem Menu keine Event-Anbingung 
					if (node.getElementsByTagName(eventTag).length == 0)
					{
						addEvent(node, 'mouseover', this.superClass.getMnuMoverFor(node), false);
						addEvent(node, 'mouseout', this.superClass.getMnuMoutFor(node), false);
					}
				}
			}
		}
	}

}


