function MenuNode(id, text, renderHandler, clickHandler, expandHandler, collapseHandler, expanded){
	this.id = id;
	this.text = text;
	this.renderHandler = renderHandler;
	this.clickHandler = clickHandler;
	this.expandHandler = expandHandler;
	this.collapseHandler = collapseHandler;
	this.expanded = expanded;
	this.children = new Array();

	return this;
}
MenuNode.prototype.render = function(visible, depth){
	if (visible == null){
		visible = true;
	}
	
	if (depth == null){
		depth = 0;
	}
	
	var spacer = "";
	for (var i=0;i<depth;i++){
		spacer += "&nbsp;&nbsp;&nbsp;&nbsp;";
	}
	
	var retVal =  "<tr id=\"" + this.id + "\"" + ((visible)?(""):(" style=\"display:none\"")) + "\">" + ((this.renderHandler)?(this.renderHandler(this.id, this.text, (this.children.length>0), this.expanded, depth)):("<td>" + spacer + "<a href=\"JavaScript:window.menuObjectInst.nodeClick('" + this.id + "');void(0);\">" + this.text + "</a></td>")) + "</tr>\n";
	for (var i=0;i<this.children.length;i++){
		retVal += this.children[i].render(visible && this.expanded, depth + 1);
	}
	return retVal;
}

MenuNode.prototype.collapse = function(){
	this.expanded = false;
	for (var i=0;i<this.children.length;i++){
		this.children[i].hide();
	}
	if (this.collapseHandler){
		this.collapseHandler(this.id, this.text, (this.children.length>0));
	}
}

MenuNode.prototype.expand = function(){
	this.expanded = true;
	for (var i=0;i<this.children.length;i++){
		this.children[i].show();
	}
	if (this.expandHandler){
		this.expandHandler(this.id, this.text, (this.children.length>0));
	}
}

MenuNode.prototype.hide = function(){
	for (var i=0;i<this.children.length;i++){
		this.children[i].hide();
	}
	document.getElementById(this.id).style.display = "none";
}

MenuNode.prototype.show = function(){
	document.getElementById(this.id).style.display = "";
	if (this.expanded){
		for (var i=0;i<this.children.length;i++){
			this.children[i].show();
		}
	}
}

function ExpandableMenuObject(border, width, height, cellPadding, cellSpacing){
	window.menuObjectInst = this;
	
	this.width = width;
	this.height = height;
	this.border = border;
	this.cellPadding = cellPadding;
	this.cellSpacing = cellSpacing;

	this.root = new MenuNode();
	this.root.expanded = true;

	return this;
}
ExpandableMenuObject.prototype.addItem = function(parentNode, id, text, renderHandler, clickHandler, expandHandler, collapseHandler, expanded){
	var retVal = new MenuNode(id, text, renderHandler, clickHandler, expandHandler, collapseHandler, expanded);
	
	if (parentNode == null){
		parentNode = this.root;
	}
	
	parentNode.children[parentNode.children.length] = retVal;
	parentNode.children[parentNode.children.length-1].parent = parentNode;
	
	return retVal;
}
ExpandableMenuObject.prototype.render = function(spacer){
	var retVal = "<table" + ((this.border==null)?(""):(" border=\"" + this.border + "\"")) + ((this.width==null)?(""):(" width=\"" + this.width + "\"")) + ((this.height==null)?(""):(" height=\"" + this.height + "\"")) + ((this.cellPadding==null)?(""):(" cellpadding=\"" + this.cellPadding + "\"")) + ((this.cellSpacing==null)?(""):(" cellspacing=\"" + this.cellSpacing + "\"")) + ">";
	for (var i=0;i<this.root.children.length;i++){
		retVal += this.root.children[i].render();
	}
	retVal += "</table>";
	return retVal;
}

ExpandableMenuObject.prototype.getNode = function(id, nodeRef){
	var retVal = null;
	
	if (nodeRef == null){
		nodeRef = this.root;
	}
	
	if (nodeRef.id == id){
		retVal = nodeRef;
	}
	else{
		for (var i=0;i<nodeRef.children.length;i++){
			retVal = this.getNode(id, nodeRef.children[i]);
			if (retVal){
				break;
			}
		}
	}
	
	return retVal;
}

ExpandableMenuObject.prototype.expand = function(id){
	var nodeRef = this.getNode(id);
	if (nodeRef){
		nodeRef.expand();
	}
}

ExpandableMenuObject.prototype.collapse = function(id){
	var nodeRef = this.getNode(id);
	if (nodeRef){
		nodeRef.collapse();
	}
}

ExpandableMenuObject.prototype.nodeClick = function(id){
	var nodeRef = this.getNode(id);
	if (nodeRef){
		if (nodeRef.expanded){
			nodeRef.collapse();
		}
		else{
			nodeRef.expand();
		}
		if (nodeRef.clickHandler){
			nodeRef.clickHandler(nodeRef.id, nodeRef.text, (nodeRef.children.length>0), nodeRef.expanded);
		}
	}
}

ExpandableMenuObject.prototype.traverse = function(userHandler, nodeRef, depth){
	if (nodeRef == null){
		nodeRef = this.root;
		depth = -1;
	}
	else{
		if (userHandler){
			userHandler(nodeRef.id, nodeRef.text, (nodeRef.children.length>0), nodeRef.expanded, depth);
		}
	}
	
	for (var i=0;i<nodeRef.children.length;i++){
		retVal = this.traverse(userHandler, nodeRef.children[i], depth++);
		if (retVal){
			break;
		}
	}
}

ExpandableMenuObject.prototype.showItem = function(id, nodeRef){
	var retVal = null;
	
	if (nodeRef == null){
		nodeRef = this.root;
	}

	if (nodeRef.id == id){
		retVal = nodeRef;
		// Place code here to show the node, and all
		// of its ancestors.
		var objNode = nodeRef;
		while (objNode){
			if (!objNode.expanded){
				objNode.expand();
			}
			
			objNode = objNode.parent;
		}
		document.getElementById(nodeRef.id).scrollIntoView();
	}
	else{
		for (var i=0;i<nodeRef.children.length;i++){
			retVal = this.showItem(id, nodeRef.children[i]);
			if (retVal){
				break;
			}
		}
	}
	
	return retVal;
}

ExpandableMenuObject.prototype.dump = function(nodeRef, boolArr){
	if (nodeRef == null){
		nodeRef = this.root;
		boolArr = new BooleanArray();
	}
	
	boolArr.set(boolArr.getLength(), nodeRef.expanded);
	
	for (var i=0;i<nodeRef.children.length;i++){
		this.dump(nodeRef.children[i], boolArr);
	}
	
	return boolArr.dump();
}

ExpandableMenuObject.prototype.load = function(boolArr, nodeRef, index){
	if (nodeRef == null){
		nodeRef = this.root;
		index = 0;
		boolArr = new BooleanArray(boolArr);
	}
	
	if (index != 0){
		if (boolArr.get(index)){
			nodeRef.expand();
		}
		else{
			nodeRef.collapse();
		}
	}
	
	index = index + 1;
	
	for (var i=0;i<nodeRef.children.length;i++){
		index = this.load(boolArr, nodeRef.children[i], index);
	}
	
	return index;
}


