(function (window, undefined) {
	var popupTimeout = {};			// Hide-Timeouts für Hauptmenüs
	var popupSubMenuDir = 1;		// direction: 1 = right; -1 = left
	var popupSafari = (document.childNodes) && (!document.all) && (!navigator.taintEnabled) && (!navigator.accentColorName);

	// Node-Objekt-Erweiterung um die Funktion contains()
	// Ist für IsMouseEnter/IsMouseLeave notwendig
	if (window.Node && Node.prototype && !Node.prototype.contains) {
		Node.prototype.contains = function(arg) {
			return !!(this.compareDocumentPosition(arg) & 16);
		}
	}

	// Initialisierungsfunktion wird im Body-onload geladen
	addEvent(window, "load", popupInitialize);

	function popupInitialize() {
		// Menü-Handling generieren
		var lists = document.getElementsByTagName("UL");
		for (var i = 0; i < lists.length; i++) {
			if (lists[i].className == "popupMenu") {
				lists[i].className = "popupMenuClass";

				if (popupSafari) { lists[i].style.position = "absolute"; }

				// Formatierungs-Klassen für Menü-Einträge setzen
				var listItems = lists[i].getElementsByTagName("LI");
				for (var j = 0; j < listItems.length; j++) {
					// Untermenü vorhanden?
					if (listItems[j].getElementsByTagName("UL").length > 0) {
						listItems[j].className = "popupMenuItemExpandableClass";
						addEvent(listItems[j], "mouseover", function (e) { if (IsMouseEnter(this, e)) { hoverIt(this); showSubMenu(this); } }, false);
						addEvent(listItems[j], "mouseout", function (e) { if (IsMouseLeave(this, e)) { unhoverIt(this); hideSubMenu(this); } }, false);
						listItems[j].getElementsByTagName("UL")[0].style.left = "0px";
					} else {
						addEvent(listItems[j], "mouseover", function (e) { if (IsMouseEnter(this, e)) { hoverIt(this); } }, false);
						addEvent(listItems[j], "mouseout", function (e) { if (IsMouseLeave(this, e)) { unhoverIt(this); } }, false);
						listItems[j].className = "popupMenuItemClass";
					}
				}

				// Hintergrund-Grafik für Hauptmenü setzen
				var pos = getAbsPos(lists[i]);

				var node = lists[i].firstChild, listOffsetHeight = 0;
				while (node != null) {
					if (node.nodeName.toUpperCase() == 'LI') {
						listOffsetHeight++;
					}
					node = node.nextSibling;
				}
				listOffsetHeight *= popupConfig["content"]["itemHeight"];

				var bgElem = createMenu(
					-popupConfig["content"]["leftBorder"],
					-popupConfig["content"]["topBorder"],
					lists[i].offsetWidth + popupConfig["content"]["leftBorder"] + popupConfig["content"]["rightBorder"],
					listOffsetHeight + popupConfig["content"]["topBorder"] + popupConfig["content"]["bottomBorder"],
					true
				);

				bgElem.style.zIndex = 10000 + (pos.level * 3);
				lists[i].style.zIndex = 10001 + (pos.level * 3);
				var listItems2 = lists[i].getElementsByTagName("LI");
				for (var k = 0; k < listItems2.length; k++) {
					listItems2[k].style.zIndex = 10002 + (pos.level * 3);
				}

				lists[i].insertBefore(bgElem, lists[i].firstChild);

				// Hintergrund-Grafiken für Untermenüs setzen
				var subLists = lists[i].getElementsByTagName("UL");
				for (var j = 0; j < subLists.length; j++) {
					if (popupSafari) { subLists[j].style.position = "absolute"; }
					subLists[j].style.display = "block";

					var pos = getAbsPos(subLists[j]);

					var node = subLists[j].firstChild, listOffsetHeight = 0;
					while (node != null) {
						if (node.nodeName.toUpperCase() == 'LI') {
							listOffsetHeight++;
						}
						node = node.nextSibling;
					}
					listOffsetHeight *= popupConfig["content"]["itemHeight"];

					var bgElem = createMenu(
						-popupConfig["content"]["leftBorder"],
						-popupConfig["content"]["topBorder"],
						subLists[j].offsetWidth + popupConfig["content"]["leftBorder"] + popupConfig["content"]["rightBorder"],
						listOffsetHeight + popupConfig["content"]["topBorder"] + popupConfig["content"]["bottomBorder"],
						false
					);

					bgElem.style.zIndex = 10000 + (pos.level * 3);
					subLists[j].style.zIndex = 10001 + (pos.level * 3);
					var listItems2 = subLists[j].getElementsByTagName("LI");
					for (var k = 0; k < listItems2.length; k++) {
						listItems2[k].style.zIndex = 10002 + (pos.level * 3);
					}

					subLists[j].insertBefore(bgElem, subLists[j].firstChild);
				}

				// Zusammenklappen beim Klick
				var links = lists[i].getElementsByTagName("A");
				for (var j = 0; j < links.length; j++) {
					addEvent(links[j], "click", function (e) { hideAll(this); }, false);
				}
			}
		}
	}

	function createMenu(left, top, width, height, bMainMenu) {
		var menu = document.createElement("DIV");
		var menuStyle = menu.style;

		menuStyle.position = "absolute";
		menuStyle.left = left + "px";
		menuStyle.top = top + "px";
		menuStyle.width = width + "px";
		menuStyle.height = height + "px";

		menu.appendChild(
			createMenuElem(width, height, "left bottom", bMainMenu).appendChild(
				createMenuElem(width, height, "right bottom", bMainMenu).appendChild(
					createMenuElem(width, height, "right top", bMainMenu).appendChild(
						createMenuElem(width, height, "left top", bMainMenu).appendChild(
							createMenuElem(width, height, "hover left", bMainMenu).appendChild(
								createMenuElem(width, height, "hover right", bMainMenu)
							).parentNode
						).parentNode
					).parentNode
				).parentNode
			).parentNode
		);
		
		return menu;
	}

	function createMenuElem(width, height, backgroundAlign, bMainMenu) {
		var elem = document.createElement("DIV");
		var elemStyle = elem.style;

		elemStyle.position = "absolute";
		elemStyle.backgroundRepeat = "no-repeat";

		switch (backgroundAlign) {
			case "left bottom":
				elemStyle.backgroundPosition = backgroundAlign;
				elemStyle.width = popupConfig["background"]["leftBorder"] + "px";
				elemStyle.height = (height - popupConfig["background"]["topBorder"] < 1 ? 1 : height - popupConfig["background"]["topBorder"]) + "px";
				elemStyle.marginLeft = "0px";
				elemStyle.marginTop = popupConfig["background"]["topBorder"] + "px";
				break;

			case "right bottom":
				elemStyle.backgroundPosition = backgroundAlign;
				elemStyle.width = (width - popupConfig["background"]["leftBorder"] < 1 ? 1 : width - popupConfig["background"]["leftBorder"]) + "px";
				elemStyle.height = (height - popupConfig["background"]["topBorder"] < 1 ? 1 : height - popupConfig["background"]["topBorder"]) + "px";
				elemStyle.marginLeft = popupConfig["background"]["leftBorder"] + "px";
				elemStyle.marginTop = "0px";
				break;

			case "right top":
				elemStyle.backgroundPosition = backgroundAlign;
				elemStyle.width = (width - popupConfig["background"]["leftBorder"] < 1 ? 1 : width - popupConfig["background"]["leftBorder"]) + "px";
				elemStyle.height = popupConfig["background"]["topBorder"] + "px";
				elemStyle.marginLeft = "0px";
				elemStyle.marginTop = -popupConfig["background"]["topBorder"] + "px";
				break;

			case "left top":
				elemStyle.backgroundPosition = backgroundAlign;
				elemStyle.width = popupConfig["background"]["leftBorder"] + "px";
				elemStyle.height = popupConfig["background"]["topBorder"] + "px";
				elemStyle.marginLeft = -popupConfig["background"]["leftBorder"] + "px";
				elemStyle.marginTop = "0px";
				break;

			case "hover left":
				elem.className = "popupMenuItemHoverBackgroundClass";
				elemStyle.backgroundPosition = "left " + -popupConfig["background"]["topBorder"] + "px";
				elemStyle.width = popupConfig["background"]["leftBorder"] + "px";
				elemStyle.height = popupConfig["hover"]["height"] + "px";
				elemStyle.marginLeft = "0px";
				elemStyle.marginTop = popupConfig["content"]["topBorder"] + "px";
				elemStyle.visibility = "hidden";
				break;

			case "hover right":
				elemStyle.backgroundPosition = "right " + -popupConfig["background"]["topBorder"] + "px";
				elemStyle.width = (width - popupConfig["background"]["leftBorder"] < 1 ? 1 : width - popupConfig["background"]["leftBorder"]) + "px";
				elemStyle.height = popupConfig["hover"]["height"] + "px";
				elemStyle.marginLeft = popupConfig["background"]["leftBorder"] + "px";
				elemStyle.marginTop = "0px";
				break;
		}

		if (popupConfig["background"]["source_ie6"] != undefined && navigator.platform == "Win32" && navigator.appName == "Microsoft Internet Explorer" && typeof document.body.style.filter == "string" && !window.XMLHttpRequest) {
			elemStyle.backgroundImage = 'url("' + (bMainMenu || !popupConfig["background"]["source_sub_ie6"] ? popupConfig["background"]["source_ie6"] : popupConfig["background"]["source_sub_ie6"]) + '")';
		} else {
			elemStyle.backgroundImage = 'url("' + (bMainMenu || !popupConfig["background"]["source_sub"] ? popupConfig["background"]["source"] : popupConfig["background"]["source_sub"]) + '")';
		}

		return elem;
	}

	/*
		Ermittelt die absolute Position eines Elements.
		elem gibt dabei das Element an.
		
	*/
	function getAbsPos(elem) {
		var pos = { x:0, y:0, level:0 };
		while (elem != null && typeof(elem.offsetLeft) !== 'undefined' && typeof(elem.offsetTop) !== 'undefined')
		{
			pos.x += elem.offsetLeft;
			pos.y += elem.offsetTop;
			pos.level++;
			elem = elem.offsetParent;
		}
		return pos;
	}

	/*
		Setzt bei Sub-Menü-Einträgen das Position-Style.
		Diese Funktion ist notwendig, da Firefox 2 extreme Geschwindigkeitseinbrüche hat,
		wenn man Position:Absolute über CSS setzt und dann auf die Elemente per JavaScript zugreift.
		Durch diese Funktion wird Position:Absolute nur für die Sub-Menüs gesetzt, für die es aktuell
		wirklich benötigt wird.
		In Safari muss Position:Absolute schon bei der Initialisierung gesetzt werden, weil es sonst
		Darstellungsfehler gibt, deshalb wird die Funktion hier entsprechend nicht ausgeführt.
	*/
	function setChildPositionStyle(parent, value) {
		if (popupSafari) { return; }

		var node = parent.firstChild;
		while (node != null) {
			if (node.nodeName.toUpperCase() == "LI") {
				var subNode = node.firstChild;
				while (subNode != null) {
					if (subNode.nodeName.toUpperCase() == "UL") {
						subNode.style.position = value || "static";
					}
					subNode = subNode.nextSibling;
				}
			}
			node = node.nextSibling;
		}
	}

	/*
		Blendet ein Popup-Menü ein.
		elem gibt das Element an, dass den Menüaufruf enthält (idr. this).
		menuId ist ein optionaler Parameter der die ID des PopupMenu-UL-Elements enthält;
	*/
	window['showPopupMenu'] = function (elem, menuId) {
		var setPos = (menuId != undefined);
		var menuId = menuId || elem.id;

		if (!document.getElementById(menuId)) { return; }
		if (document.getElementById(menuId).className == "popupMenu") { popupInitialize(); }

		if (popupTimeout[menuId] != null && typeof popupTimeout[menuId] != 'undefined') {
			clearTimeout(popupTimeout[menuId]);
		}
		popupTimeout[menuId] = null;

		if (setPos) {
			var popupMenu = document.getElementById(menuId);
			popupSubMenuDir = 1;
			setChildPositionStyle(popupMenu, "absolute");
			var pos = getAbsPos(elem);
			popupMenu.style.left = (pos.x + popupConfig["mainmenu"]["left"]) + "px";
			var oH = (typeof(elem.offsetHeight) !== 'undefined' ? elem.offsetHeight : 0);
			popupMenu.style.top = (pos.y + oH + popupConfig["mainmenu"]["top"] + popupConfig["background"]["topBorder"]) + "px";

			var node = popupMenu.firstChild;
			while (node != null) {
				if (node.nodeName.toUpperCase() == 'LI') {
					node.style.height = popupConfig["content"]["itemHeight"] + 'px';
					node.style.lineHeight = popupConfig["content"]["itemHeight"] + 'px';
				}
				node = node.nextSibling;
			}

			popupMenu.style.visibility = "visible";
		}
	}

	/*
		Blendet ein Popup-Menü aus.
		interval ist ein optionaler Parameter der festlegt nach wieviel Millisekunden das
		Menü ausgeblendet werden soll; Default ist 150.
	*/
	window['hidePopupMenu'] = function (menuId, interval)
	{
		if (interval == 0) {
			if (typeof menuId != 'undefined') {
				var popupMenu = document.getElementById(menuId);
				popupTimeout[menuId] = null;
				if (popupMenu) {
					popupMenu.style.visibility = "hidden";

					var node = popupMenu.firstChild;
					while (node != null) {
						if (node.nodeName.toUpperCase() == 'LI') {
							node.style.height = '2px';
							node.style.lineHeight = '2px';
						}
						node = node.nextSibling;
					}
				}
				popupMenu = null;
			}
		} else {
			popupTimeout[menuId] = setTimeout((function (menuId) { return function () {
				hidePopupMenu(menuId, 0);
			}})(menuId), interval || 150);
		}
	}

	/*
		Ermittelt den x-Offset gegenüber den übergeordneten Menü.
		node gibt das UL-Element des Untermenüs an.
	*/
	function getNewSubMenuPos(node) {
		if (popupSubMenuDir == 1) {
			// Untermenü auf rechter Seite anzeigen
			return (node.offsetParent.offsetWidth + popupConfig["submenu"]["leftAlign"]);
		} else {
			// Untermenü auf linker Seite anzeigen
			return -(node.offsetWidth + popupConfig["submenu"]["rightAlign"]);
		}
	}

	/*
		Blendet ein Untermenü ein.
		parent gibt das übergeordnete LI-Element an.
	*/
	function showSubMenu(parent) {
		var node = parent.firstChild;
		while (node != null) {
			if (node.nodeName.toUpperCase() == "UL") {
				node.style.left = "0px";
				setChildPositionStyle(node, "absolute");
				var newSubMenuPos = getNewSubMenuPos(node);
				var pos = getAbsPos(node);
				if ((pos.x + newSubMenuPos + node.offsetWidth) > getViewportWidth()) {
					popupSubMenuDir = -1;
					newSubMenuPos = getNewSubMenuPos(node);
				} else if ((pos.x + newSubMenuPos) < 0) {
					popupSubMenuDir = 1;
					newSubMenuPos = getNewSubMenuPos(node);
				}
				node.style.left = newSubMenuPos + "px";
				node.style.marginTop = (popupConfig["submenu"]["top"] - popupConfig["content"]["itemHeight"]) + "px";
				node.offsetParent.style.zIndex *= 2;

				var subNode = node.firstChild;
				while (subNode != null) {
					if (subNode.nodeName.toUpperCase() == 'LI') {
						subNode.style.height = popupConfig["content"]["itemHeight"] + 'px';
						subNode.style.lineHeight = popupConfig["content"]["itemHeight"] + 'px';
					}
					subNode = subNode.nextSibling;
				}

				node.style.visibility = "visible";
			}
			node = node.nextSibling;
		}
	}

	/*
		Blendet einen Untermenü aus.
		parent gibt das übergeordnete LI-Element an.
		
	*/
	function hideSubMenu(parent) {
		var node = parent.firstChild;
		while (node != null) {
			if (node.nodeName.toUpperCase() == "UL") {
				node.style.left = "0px";
				if (node.offsetParent.parentNode.className != 'popupMenuClass') {
					node.offsetParent.style.zIndex /= 2;
				}
				node.style.visibility = "hidden";
				setChildPositionStyle(node);

				var subNode = node.firstChild;
				while (subNode != null) {
					if (subNode.nodeName.toUpperCase() == 'LI') {
						subNode.style.height = '2px';
						subNode.style.lineHeight = '2px';
					}
					subNode = subNode.nextSibling;
				}
			}
			node = node.nextSibling;
		}
	}

	/*
		Verschiebt das Hover-Element über den aktiven Menü-Eintrag
		elem gibt den List-Item an, über dem sich die Maus befindet
	*/
	function hoverIt(elem) {
		subElems = elem.offsetParent.getElementsByTagName("DIV");
		for (var i = 0; i < subElems.length; i++) {
			if (subElems[i].className == "popupMenuItemHoverBackgroundClass") {
				subElems[i].style.marginTop = (elem.offsetTop + popupConfig["content"]["topBorder"] + popupConfig["hover"]["topBorder"]) + "px";
				subElems[i].style.visibility = "visible";
				break;
			}
		}

		if (elem.className == "popupMenuItemClass") {
			elem.className = "popupMenuItemHoverClass";
		} else if (elem.className == "popupMenuItemExpandableClass") {
			elem.className = "popupMenuItemHoverExpandableClass";
		}
	}

	/*
		Blendet das Hover-Element aus
		elem gibt den List-Item an, über dem sich die Maus befand
	*/
	function unhoverIt(elem)
	{
		subElems = elem.offsetParent.getElementsByTagName("DIV");
		for (var i = 0; i < subElems.length; i++) {
			if (subElems[i].className == "popupMenuItemHoverBackgroundClass") {
				subElems[i].style.visibility = "hidden";
				break;
			}
		}

		if (elem.className == "popupMenuItemHoverClass") {
			elem.className = "popupMenuItemClass";
		} else if (elem.className == "popupMenuItemHoverExpandableClass") {
			elem.className = "popupMenuItemExpandableClass";
		}
	}

	/*
		Blendet alle Menü-Ebenen aus - dies ist beim click-Event auf einen Menüeintrag notwendig,
		da sonst beim Rücksprung auf die Seite (über den Browser-Back-Button) das Menü noch teilweise angezeigt wird.
	*/
	function hideAll(elem) {
		var node = elem.parentNode;
		while (node != null) {
			if (node.nodeName.toUpperCase() == "LI") {
				unhoverIt(node);
				hideSubMenu(node);
			}

			node = node.parentNode;
		}

		hidePopupMenu(undefined, 0);
	}

	/*
		John Resigs "Flexible Javascript Events"
		http://ejohn.org/projects/flexible-javascript-events/
	*/
	function addEvent(obj, type, fn) {
		if (obj.attachEvent) {
			var rnd = parseInt(Math.random() * 0xffffffff, 16).toString() + parseInt(Math.random() * 0xffffffff, 16).toString() + parseInt(Math.random() * 0xffffffff, 16).toString() + parseInt(Math.random() * 0xffffffff, 16).toString();
			obj['e' + type + fn + rnd] = fn;
			obj[type + fn + rnd] = function() { obj['e' + type + fn + rnd](window.event); }
			obj.attachEvent('on' + type, obj[type + fn + rnd]);
		} else {
			obj.addEventListener(type, fn, false);
		}
	}

	/*
		Überprüft ob der Mauszeiger ein Element betreten hat.
		Dieser Aufruf sollte im mouseover-Event erfolgen.
		Da Elemente auch beim Wechsel von Child zu Parent-Element, oder innerhalb von Child-Elementen einen Event auslösen ist diese Funktion wichtig,
		um sicherzustellen, dass Aktionen wirklich nur beim Betreten ausgeführt werden.
		elem gibt dabei das Element an; e das Event-Objekt

		Beispiel:
			if (IsMouseEnter(this, e)) ...
	*/
	function IsMouseEnter(elem, e) {
		e = e || window.event;
		var target = e.target || e.srcElement;
		var fromElement = e.relatedTarget || e.fromElement || false;

		try {
			if (fromElement === false) { return true; }
			if (elem.contains(fromElement) || fromElement === elem) {
				return false;
			} else {
				return true;
			}
		} catch (e) {
			return true;
		}
	}

	/*
		Überprüft ob der Mauszeiger ein Element verlassen hat.
		Dieser Aufruf sollte im mouseout-Event erfolgen.
		Da Elemente auch beim Wechsel von Child zu Parent-Element, oder innerhalb von Child-Elementen einen Event auslösen ist diese Funktion wichtig,
		um sicherzustellen, dass Aktionen wirklich nur beim Verlassen des eigentlichen Elements ausgeführt werden.
		elem gibt dabei das Element an; e das Event-Objekt

		Beispiel:
			if (IsMouseLeave(this, e)) ...
	*/
	function IsMouseLeave(elem, e) {
		e = e || window.event;
		var target = e.target || e.srcElement;
		var toElement = e.relatedTarget || e.toElement || false;

		try {
			if (toElement === false) { return true; }
			if (elem.contains(toElement) || toElement === elem) {
				return false;
			} else {
				return true;
			}
		} catch (e) {
			return true;
		}
	}

	/*
		Gibt die Breite des sichtbaren Seiten-Bereichs zurücks
	*/
	function getViewportWidth() {
		if (window.innerWidth) {
			return window.innerWidth;
		} else if (document.documentElement && document.documentElement.clientWidth) {
			return document.documentElement.clientWidth;
		} else if (document.body) {
			return document.body.clientWidth;
		} else {
			return 0;
		}
	}
})(window);
