
function Menu (target, props) {
	
	this.addListener(this);
	
	if (target == undefined) return;
	
	this.target = (typeof target == "object") ? target : document.getElementById(target);
	
	if (props != undefined) {
		this.properties.evt = (props.evt == undefined) ? this.properties.evt : props.evt;
		this.properties.type = (props.type == undefined) ? this.properties.type : props.type;
		this.properties.autoHide = (props.autoHide == undefined) ? this.properties.autoHide : props.autoHide;
	}
	
	this.evtTarget = (this.userAgent.isIEStrict()) ? "srcElement" : "target";
	
	CSSManager.addClassName(this.target, this.className);
	CSSManager.addClassName(this.target, this.properties.type);
	
	this.onfocus();
	if (this.properties.autoHide) this.autoHide();
	
	var classPointer = this;
	var evtMouse = (this.userAgent.isIEStrict()) ? this.properties.evt : "event";
	
	this.target[this.properties.evt] = function (evtMouse) {
		classPointer.showHide((classPointer.userAgent.isIEStrict()) ? event : evtMouse);
	}
	
}

Class(Menu);
Broadcaster.initialize(Menu.prototype, false);

Menu.prototype.target = new Object();
Menu.prototype.properties = {evt: "onmousedown", type: "", autoHide: true};
Menu.prototype.currFocus = new Object();
Menu.prototype.prevFocus = new Object();
Menu.prototype.evtTarget = new Object();
Menu.prototype.className = "menu-list";
Menu.prototype.userAgent = new UADetector();

Menu.prototype.onShow = new Function;
Menu.prototype.onHide = new Function;

Menu.prototype.show = function (target) {
	
	this.currFocus = target;
	
	CSSManager.removeClassName(target, "hide");
	CSSManager.addClassName(target, "active");
	
	var sibling = Menu.getPreviousSibling(target);
	var alink = new Object();
	
	if (sibling.nodeName.toLowerCase() == "a") {
		alink = sibling;
	} else {
		alink = sibling.getElementsByTagName("a").item(0);
	}
	
	CSSManager.addClassName(alink, "active");
	
	this.broadcastMessage("onShow", this, target);
	
}

Menu.prototype.hide = function (target) {
	
	if (target.nodeName) {
		CSSManager.addClassName(target, "hide");
		CSSManager.removeClassName(target, "active");
		
		var sibling = Menu.getPreviousSibling(target);
		var alink = new Object();
		
		if (sibling.nodeName.toLowerCase() == "a") {
			alink = sibling;
		} else {
			alink = sibling.getElementsByTagName("a").item(0);
		}
		
		CSSManager.removeClassName(alink, "active");
	}
	
	this.broadcastMessage("onHide", this, target);
	
}

Menu.prototype.showHide = function (evt) {
	
	var nodeMatch = new Object();
	nodeMatch.bool = false;
	var node = new Object();
	
	if (evt[this.evtTarget].tagName.toLowerCase() == "a") {
		
		nodeMatch = Menu.hasParentNode(this.target, evt[this.evtTarget], "dt");
		
	} else {
		
		var alink = Menu.hasParentNode(this.target, evt[this.evtTarget], "a");
		
		if (alink.bool) nodeMatch = Menu.hasParentNode(this.target, alink.node, "dt");
		
	}
	
	if (nodeMatch.bool) {
		node = Menu.getNextSibling(nodeMatch.node, 1);
	} else {
		node = Menu.getNextSibling(evt[this.evtTarget], 1);
	}
	
	if (CSSManager.testClassName(node, "hide")) {
		this.hide(this.currFocus);
		this.show(node);
	}
	
}

Menu.prototype.autoHide = function () {
	
	var classPointer = this;
	
	this.target.onmouseout = function (evt) {
		
		var evt = (classPointer.userAgent.isIEStrict()) ? event : evt;
		var currItem = (classPointer.userAgent.isIEStrict()) ? evt.toElement : evt.relatedTarget;
		var children = new Array();
		
		if (currItem == this || currItem == undefined) return;
		
		if (currItem.tagName == null || currItem.tagName.toLowerCase() == "html" || currItem.tagName.toLowerCase() == "body") {
			classPointer.hide(classPointer.currFocus);
		} else {
			children = this.getElementsByTagName( currItem.nodeName);
			for (var items = 0; items < children.length; items++) {
				if (children[items] == currItem) return true;
			}
			
			classPointer.hide(classPointer.currFocus);
		}
		
	}
}

Menu.prototype.onfocus = function (evt) {
	
	//if (this.properties.evt != "onmouseover") return;
	
	var classPointer = this;
	
	if (this.userAgent.isIEStrict()) {
		this.target.onfocusin = function (onfocusin) {
			
			var evt = event;
			var currItem = evt.srcElement;
			
			var target = Menu.parentNodeWithAttributeValue(classPointer.target, currItem, "className", "hide");
			
			if (target.bool) {
				classPointer.hide(classPointer.currFocus);
				classPointer.show(target.node);
			} else {
				classPointer.showHide(evt);
			}
			
			//classPointer.showHide(event);
		}
		
		this.target.onfocusout = function (onfocusout) {
				
			var evt = event;
			var currItem = evt.toElement;
			var children = new Array();
			
			if (currItem == this) return;
			
			if (currItem == null || currItem.tagName == null || currItem.tagName.toLowerCase() == "html" || currItem.tagName.toLowerCase() == "body") {
				classPointer.hide(classPointer.currFocus);
			} else {
				children = this.getElementsByTagName( currItem.nodeName);
				for (var items = 0; items < children.length; items++) {
					if (children[items] == currItem) return true;
				}
				
				classPointer.hide(classPointer.currFocus);
			}
			
		}
	} else {
		this.target.onfocus = function (evt) {
			
			var currItem = evt.explicitOriginalTarget;
			
			var target = Menu.parentNodeWithAttributeValue(classPointer.target, currItem, "className", "hide");
			if (target.bool) {
				classPointer.hide(classPointer.currFocus);
				classPointer.show(target.node);
			} else {
				classPointer.showHide(evt);
			}
			
		}
		this.target.onblur = function (evt) {
			
			var currItem = evt.explicitOriginalTarget;
			var children = new Array();
			
			if (currItem == this) return;
			
			if (currItem == null || currItem.tagName == null || currItem == evt.target || currItem.tagName.toLowerCase() == "html" || currItem.tagName.toLowerCase() == "body") {
				classPointer.hide(classPointer.currFocus);
			} else {
				children = this.getElementsByTagName( currItem.nodeName);
				for (var items = 0; items < children.length; items++) {
					if (children[items] == currItem) return true;
				}
				
				classPointer.hide(classPointer.currFocus);
			}
			
		}
	}
	
}

Menu.hasParentNode = function (root, target, name) {
	
	var node = target;
	var result = new Object();
	result.bool = false;
	
	while (node.parentNode != undefined && node.parentNode != root) {
		node = node.parentNode;
		if (node.nodeType == 1 && node.tagName.toLowerCase() == name) {
			result.bool = true;
			break;
		}
	}
	
	result.node = node;
	
	return result;
	
}

Menu.parentNodeWithAttributeValue = function (root, target, name, value) {
	
	var node = target;
	var result = new Object();
	result.bool = false;
	
	while (node.parentNode != undefined && node.parentNode != root) {
		node = node.parentNode;
		if (node.nodeType == 1) {
			if ((name == "className" && CSSManager.testClassName(node, value)) || node[name] == value) {
				result.bool = true;
				break;
			}
		}
	}
	
	result.node = node;
	
	return result;
	
}

Menu.getNextSibling = function (target, type) {
	
	var node = target;
	var nodeType = (type == undefined) ? 1 : type;
	
	while (node.nextSibling != undefined) {
		node = node.nextSibling;
		if (node.nodeType == nodeType) break;
	}
	
	return node;
	
}

Menu.getPreviousSibling = function (target, type) {
	
	var node = target;
	var nodeType = (type == undefined) ? 1 : type;
	
	while (node.previousSibling != undefined) {
		node = node.previousSibling;
		if (node.nodeType == nodeType) break;
	}
	
	return node;
	
}
