//Common script functions for TreeView controls

var treeViews = new Array();

function getNode(ownerValue,value)
{
	var node;

	try
	{
		node = eval("treeView" + ownerValue + "_node" + value);
		return node;
	}
	catch(ex)
	{
		return null;
	}
}

//NodeLine element functions
function nodeLine_onClick(ownerValue,value)
{
	var node = getNode(ownerValue,value);
	if (node)
		node.lineOnClick();
}

function nodeLine_onMouseOverOut(ownerValue,value)
{
	var node = getNode(ownerValue,value);
	if (node)
		node.lineOnMouseOverOut();
}

//NodeExpandImage element functions
function nodeExpandImage_onClick(e,ownerValue,value)
{
	if (!e) var e = window.event;

	//toggleExpansion
	var node = getNode(ownerValue,value);
	if (node)
		node.toggleExpansion();

	//cancel event
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
}

//NodeName element functions
function nodeName_onClick(ownerValue,value)
{
	var node = getNode(ownerValue,value);
	if (node)
		node.nameOnClick();
}

function nodeName_onMouseOverOut(ownerValue,value)
{
	var node = getNode(ownerValue,value);
	if (node)
		node.nameOnMouseOverOut();
}


/////////////////////////////////////////////////////////////
// TREE VIEW CLASS //////////////////////////////////////////
/////////////////////////////////////////////////////////////

function TreeView()
{
	//properties
	this.activeNode = null;
	this.container = null;
	this.cssClass = "";
	this.leafView = null;
	this.expandable = true;
	this.expandLevel = -1;
	this.iconSet = new IconSet();
	this.selectedValue = 0;
	this.showImages = false;
	this.value = 0;

	//collection properties
	this.icons = new Array();
	this.nodes = new Array();

	//methods
	this.addNode = treeView_addNode;
	this.findNode = treeView_findNode;
	this.findNodeRecursive = treeView_findNodeRecursive;
	this.initialize = treeView_initialize;
	this.setActiveNode = treeView_setActiveNode;
}

function treeView_addNode(node)
{
	this.nodes[this.nodes.length] = node;
}

//finds a node for the given value
function treeView_findNode(value)
{
	//loop through top level nodes
	for (var i=0; this.nodes && i<this.nodes.length; i++)
	{
		if (this.nodes[i].value == value)
			return this.nodes[i];
		else
		{
			var foundNode = this.findNodeRecursive(this.nodes[i],value);
			if (foundNode)
				return foundNode;
		}
	}
	return null;
}

//finds a node for the given value
function treeView_findNodeRecursive(node,value)
{
	if (node.value == value)
		return node;

	for (var i=0; node.nodes && i<node.nodes.length; i++)
	{
		var foundNode = this.findNodeRecursive(node.nodes[i],value);
		if (foundNode)
			return foundNode;
	}
	return null;
}

//initialize tree view
function treeView_initialize()
{
	//handle initial expansion
	if (this.expandLevel == -1 || this.expandLevel > 0)
		for (var i=0; this.nodes && i<this.nodes.length; i++)
			this.nodes[i].expand(0);

	//select initial node
	if (this.selectedValue > 0)
	{
		var node = getNode(this.value,this.selectedValue);
		if (node)
		{
			node.activate(false)
			node.expand()
		}
		else
		{
			this.selectedValue = 0;
		}
	}
}

function treeView_setActiveNode(node)
{
	if (this.activeNode != node)
	{
		if (this.activeNode)
			this.activeNode.deactivate()

		this.activeNode = node;
	}
}


/////////////////////////////////////////////////////////////
// ICON SET CLASS ///////////////////////////////////////////
/////////////////////////////////////////////////////////////

function IconSet()
{
	//properties
	this.collapseImage = new Image();
	this.expandImage = new Image();
	this.leafImage = new Image();
	this.noExpandImage = new Image();
	this.nodeClosedImage = new Image();
	this.nodeOpenImage = new Image();
	this.path = "";

	//methods
	this.setPath = iconSet_setPath;
}

function iconSet_setPath(path)
{
	this.path = path;

	this.collapseImage.src = path + "Collapse.gif";
	this.expandImage.src = path + "Expand.gif";
	this.leafImage.src = path + "Leaf.gif";
	this.noExpandImage.src = path + "NoExpand.gif";
	this.nodeClosedImage.src = path + "NodeClosed.gif";
	this.nodeOpenImage.src = path + "NodeOpen.gif";
}


/////////////////////////////////////////////////////////////
// TREE VIEW NODE CLASS /////////////////////////////////////
/////////////////////////////////////////////////////////////

function TreeViewLeaf(owner,parent,value,text)
{
}

function TreeViewNode(owner,parent,value,text)
{
	//properties
	this.expanded = false;
	this.hasLeafs = false;
	this.hasNodes = false;
	this.owner = owner;
	this.parent = parent;
	this.text = text;
	this.value = value;

	//collections
	this.leafs = new Array();
	this.nodes = new Array();

	//dhtml references
	this.containerEl = null;
	this.contentEl = null;
	this.expandImage = null;
	this.inputEl = null;
	this.nameEl = null;
	this.nodeImage = null;
	this.nodeLineEl = null;

	//add to parent/owner
	if (parent)
		parent.addNode(this);
	else
		owner.addNode(this);

	//methods
	this.activate = treeViewNode_activate;
	this.addLeaf = treeViewNode_addLeaf;
	this.addNode = treeViewNode_addNode;
	this.collapse = treeViewNode_collapse;
	this.expand = treeViewNode_expand;
	this.deactivate = treeViewNode_deactivate;
	this.initialize = treeViewNode_initialize;
	this.toggleExpansion = treeViewNode_toggleExpansion;

	//event handlers
	this.lineOnClick = treeViewNode_lineOnClick;
	this.lineOnMouseOverOut = treeViewNode_lineOnMouseOverOut;
	this.nameOnClick = treeViewNode_nameOnClick;
	this.nameOnMouseOverOut = treeViewNode_nameOnMouseOverOut;

	//finally, initialize this node
	this.initialize();
}

function treeViewNode_activate(hover)
{
	if (this.owner.activeNode != this)
	{
		//set active node
		this.owner.setActiveNode(this);

		//change style for node
		this.nameEl.className = hover ? "NodeNameSelectedHover" : "NodeNameSelected";
		if (this.owner.showImages)
			this.nodeImage.src = this.owner.iconSet.nodeOpenImage.src;

		//attempt to show leafs in leaf viewer
		if (this.owner.leafView)
			eval("leafView" + this.owner.leafView.ordinal + "_group" + this.value).activate();
	}
}

function treeViewNode_addLeaf(leaf)
{
	this.leafs[this.leafs.length] = leaf;
	this.hasLeafs = true;
}

function treeViewNode_addNode(node)
{
	this.nodes[this.nodes.length] = node;
	this.hasNodes = true;
}

function treeViewNode_collapse()
{
	if (this.owner.expandable)
	{
		this.expanded = false;
		if (this.contentEl)
			this.contentEl.style.display = "none";
		this.expandImage.src = this.hasNodes ? this.owner.iconSet.expandImage.src : this.owner.iconSet.noExpandImage.src;
	}
}

function treeViewNode_deactivate()
{
	this.nameEl.className = "NodeName";
	if (this.owner.showImages)
		this.nodeImage.src = this.owner.iconSet.nodeClosedImage.src;
}

function treeViewNode_expand(level)
{
	if (this.owner.expandable || level != null)
	{
		//ensure all parents are expanded
		if (this.parent)
			this.parent.expand();

		this.expanded = true;
		if (this.contentEl)
			this.contentEl.style.display = "block";
		if (this.owner.expandable)
			this.expandImage.src = this.hasNodes ? this.owner.iconSet.collapseImage.src : this.owner.iconSet.noExpandImage.src;

		//expand any necessary child nodes (but only if a level was given)
		if (level != null)
		{
			if (this.owner.expandLevel == -1 || level < this.owner.expandLevel - 1)
			{
				level += 1;
				for (var i=0; this.nodes && i<this.nodes.length; i++)
				{
					if (this.nodes[i].expand)
						this.nodes[i].expand(level);
				}
			}
		}
	}
}

function treeViewNode_initialize()
{
	this.contentEl = document.getElementById("NodeContent" + this.value);
	this.expandImage = document.getElementById("NodeExpandImage" + this.value);
	this.nameEl = document.getElementById("NodeName" + this.value);
	this.nodeImage = document.getElementById("NodeImage" + this.value);
}

function treeViewNode_lineOnClick()
{
	this.expand();
}

function treeViewNode_lineOnMouseOverOut()
{
	if (this.nodeLineEl)
	{
		switch (this.nodeLineEl.className)
		{
			case "NodeLine": this.nodeLineEl.className = "NodeLineHover"; break;
			case "NodeLineHover": this.nodeLineEl.className = "NodeLine"; break;
			case "NodeLineSelected": this.nodeLineEl.className = "NodeLineSelectedHover"; break;
			case "NodeLineSelectedHover": this.nodeLineEl.className = "NodeLineSelected"; break;
		}
	}
}

function treeViewNode_nameOnClick()
{
	this.activate(true);
	this.expand();
}

function treeViewNode_nameOnMouseOverOut()
{
	if (this.nameEl)
	{
		switch (this.nameEl.className)
		{
			case "NodeName": this.nameEl.className = "NodeNameHover"; break;
			case "NodeNameHover": this.nameEl.className = "NodeName"; break;
			case "NodeNameSelected": this.nameEl.className = "NodeNameSelectedHover"; break;
			case "NodeNameSelectedHover": this.nameEl.className = "NodeNameSelected"; break;
		}
	}
}

function treeViewNode_toggleExpansion()
{
	if (this.expanded)
		this.collapse();
	else
		this.expand();
}
