//<script>
function ColPagingData()
{
	this.numCurPage = 1;
	this.query = "";
	this.sort = "";
	this.reverse = "false";
	this.nextPage = function(query)
	{
		this.query = query;
		this.sort = "";
		this.reverse = "false";
		this.numCurPage++;
	}
	this.prevPage = function(query)
	{
		this.query = query;
		this.sort = "DESC";
		this.reverse = "true";
		this.numCurPage--;
	}
}

var PagingData =
{
	m_ar: new Array(),
	get: function(collId)
	{
		var ret = this.m_ar[collId];
		if (ret == null)
		{
			ret = this.m_ar[collId] = new ColPagingData();
		}
		return ret;
	}
}

var xmlhttp = XmlHttp.createNew();
var Tree =
{
	onClick: function(oInfo) { }, // overridable
	onShow: function() { },	// overridable

	// Main rendering function. Apply XSL transform to XML data, and put the results in designated <div>.
	show: function(where)
	{
		var div = this.container;
		if (div == null || this.xmlData == null || this.xmlStylesheet == null)
			return;
		var root = this.xmlData.documentElement;
		var s = root.transformNode(this.xmlStylesheet);
		div.innerHTML = s;
		this.root = div;
		this.onShow();
	},
	setContainer     : function(oElem)         { this.container = oElem; },
	setXmlData       : function(xmlData)       { this.xmlData = xmlData; this.show("setXmlData"); },
	setXmlStylesheet : function(xmlStylesheet) { this.xmlStylesheet = xmlStylesheet; this.show("setXmlStylesheet"); },
	
	// Retrieving tree node information.
	// We assume "tree:level" attribute is always present and valid (root has level 0, etc.)
	getLevel: function(elem) { return elem.getAttribute("tree:level"); },
	// Get all node info packed in an object.
	getInfo: function(elem)
	{
		return {
			elem:	elem,
			level:	this.getLevel(elem),
			id:		elem.getAttribute("tree:id"),
			value:	elem.getAttribute("tree:value"),
			link:	elem.getAttribute("tree:link")
		};
	},
	// Get linked list of "info" objects, starting with elem and up to the root.
	getInfoChain: function(elem)
	{
		var ret = this.getInfo(elem);
		for (var info = ret; (elem = this.getParent(elem)) != null; info = info.parent)
			info.parent = this.getInfo(elem);
		info.parent = null;
		return ret;
	},

	// Find nearest ancestor that belongs to the tree (has the "tree:level" attribute)
	findNode: function(elem)
	{ 
		while (elem && this.getLevel(elem) == null) 
		{
			if (elem == this.root)
				return null;
			elem = elem.parentNode;
		}
		return elem;
	},
	getParent: function(elem) { return (this.getLevel(elem) == 0) ? null : this.findNode(elem.parentNode); },
	setActive: function(elem)
	{
		/*if (this.activeNode == elem)
			return false;*/
		if (this.activeNode != null)
			this.activeNode.className = "";
		this.activeNode = elem;
		this.activeNode.className = "active";
		return true;
	},
	insertNode: function(node)
	{
		var id = node.getAttribute("tree:id");
		if (id != null)
			this.nodeMap[id] = node;
		for (node = node.firstChild; node != null; node = node.nextSibling)
			if (node.nodeType == 1)
				this.insertNode(node);
	},
	updateNodeMap: function(node)
	{
		if (this.nodeMap != null)
			this.insertNode(node);
	},
	findNodeById: function(treeID)
	{
		if (this.nodeMap == null) {
			this.nodeMap = new Array();
			this.insertNode(this.root);
		}
		return this.nodeMap[treeID];
	}
}

function toggle(evt)
{
	evt = Compat.getEvent(evt);
	evt.stopPropagation();		// don't bubble this event up the DOM tree.
	toggleNode(Tree.findNode(evt.target));
}

function getChildren(node, query, sort)
{
	xmlhttp.open("GET", "NetisUtils/srvrutil_getTree.aspx?dbID=" + node.getAttribute("tree:id") + "&children=1&query=" + query + "&sort=" + sort, false);
	xmlhttp.send("");
	var data = xmlhttp.responseXML;
	var treeSize = parseInt(data.documentElement.getAttribute("treeSize"));
	var rootNode = data.selectSingleNode("root/collection");
	if (rootNode == null)
	{
	    rootNode = data.selectSingleNode("collection"); // mozilla is slightly different
	}
	var id = parseInt(rootNode.getAttribute("id"));
	var children = parseInt(rootNode.getAttribute("children"));
	var maxPage = Math.ceil(children/treeSize);
	return { data: data, rootNode: rootNode, id: id, maxPage: maxPage };
}

function toggleNode(node)
{
	// Depending on whether the branch is expanding or collapsing, several things must be changed.
	// For briefness, we pack them all into one neat object.
	var o;
	switch (node.getAttribute("tree:flag")) {
		case "+": o = { displayType: "block", treeFlag: "-", innerHtml: "&ndash;", className: "bulletMinus" }; break;
		case "-": o = { displayType: "none",  treeFlag: "+", innerHtml: "+",      className: "bulletPlus" }; break;
	}
	// ----
	// Note: if o is null here, you probably failed to initialize the "tree:flag" attribute.
	// ----
	node.setAttribute("tree:flag", o.treeFlag);
	var childrenLoaded = false;
	for (var child = node.firstChild; child != null; child = child.nextSibling)
	{
		switch (child.tagName) {
			case "UL":
				if (child.childNodes.length != 0)
					childrenLoaded = true;
				child.style.display = o.displayType;
				break;
			case "SPAN":
				if (child.getAttribute("tree:flag"))
				{
					child.innerHTML = o.innerHtml;
					child.className = o.className;
					child.setAttribute("tree:flag", o.treeFlag);
					break;
				}
		}
	}
	if (childrenLoaded)
		return;
	var id = node.getAttribute("tree:id");
	var o = PagingData.get(id);
	var obj = getChildren(node, o.query, o.sort);
	var root = obj.rootNode;
	node.innerHTML = displayItems(root, obj.data, o.numCurPage, obj.maxPage, (o.reverse == "true"?true:false));
	Tree.updateNodeMap(node);
}

function getNode(evt)
{
	evt = Compat.getEvent(evt);
	evt.stopPropagation();		// don't bubble this event up the DOM tree.
	return Tree.findNode(evt.target);
}

function displayItems(root, data, page, maxPage, reverse)
{
	root.setAttribute("page", page);
	root.setAttribute("pages", maxPage);
	root.setAttribute("expanding", "true");
	if (reverse)
		root.setAttribute("reverse", "true");
	return data.transformNode(Tree.xmlStylesheet);
}

function getNext(nextId, evt)
{
	var node = getNode(evt);
	var query = "CollectionId > " + nextId;
	var obj = getChildren(node, query, "");
	var o = PagingData.get(obj.id);
	o.nextPage(query);
	var root = obj.rootNode;
	node.innerHTML = displayItems(root, obj.data, o.numCurPage, obj.maxPage);	
}

function getPrev(prevId, evt)
{
	var node = getNode(evt);
	var query = "CollectionId < " + prevId;
	var obj = getChildren(node, query, "DESC");
	var o = PagingData.get(obj.id);
	o.prevPage(query);
	var root = obj.rootNode;
	node.innerHTML = displayItems(root, obj.data, o.numCurPage, obj.maxPage, true);				
}

function handleClick(evt)
{
	evt = Compat.getEvent(evt);
	evt.stopPropagation();		// don't bubble this event up the DOM tree.

	if (!Tree.setActive(evt.target))
		return;
	var clickedNode = Tree.findNode(evt.target);
	Tree.onClick(Tree.getInfoChain(clickedNode));
}

function setHover(evt, bSet)
{
	evt = Compat.getEvent(evt);
	var elem = evt.target;
	var currentClass = elem.className;
	if (bSet)
		elem.className = "hover";
	else if (currentClass == "hover")
		elem.className = elem.getAttribute("origClass");

	elem.setAttribute("origClass", currentClass);
}
