/* Copyright © 2002 Jean-Claude Manoli [jc@manoli.net]
 *
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the author(s) be held liable for any damages arising from
 * the use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 * 
 *   1. The origin of this software must not be misrepresented; you must not
 *      claim that you wrote the original software. If you use this software
 *      in a product, an acknowledgment in the product documentation would be
 *      appreciated but is not required.
 * 
 *   2. Altered source versions must be plainly marked as such, and must not
 *      be misrepresented as being the original software.
 * 
 *   3. This notice may not be removed or altered from any source distribution.
 * 
 *   Feb 7/2004 Code Modified by Jose Walker - jwalker@coextant.de
 *   a little bug was preventing the sync toc of working properly in 
 *   Mozilla based browsers, function modified findHref
 *
 *   2005-2006: Several functions added and some functions patched.
 */ 

var treeSelected = null; //last treeNode clicked

function die() {
	return false;
}

function touchAllNodes(oldClass, newClass) {
	var root=document.getElementById("treeRoot");
	if (root!=null) {
	  var divs=root.getElementsByTagName("div");
	  for (var i=0, l=divs.length; i<l; i++) {
	    var div=divs[i];
	    if (div.className==oldClass)
				div.className=newClass;
		}
	}
}

function touchAllImages(oldSrc, newSrc) {
	var root=document.getElementById("treeRoot");
	if (root!=null) {
	  var imgs=root.getElementsByTagName("img");
	  for (var i=0, l=imgs.length; i<l; i++) {
	    var img=imgs[i];
	    if (img.className=="treeNoLinkImage" || img.className=="treeLinkImage") {
				if (img.src==oldSrc)
					img.src=newSrc;
			}
		}
	}
}

function expandAll() {
	touchAllNodes("treeSubnodesHidden", "treeSubnodes");
	touchAllImages(imgPlus.src, imgMinus.src);
}

function collapseAll() {
	touchAllNodes("treeSubnodes", "treeSubnodesHidden");
	touchAllImages(imgMinus.src, imgPlus.src);
}

function initToc() {
	var root=document.getElementById("treeRoot");
	if (root!=null) {
		var anchors=root.getElementsByTagName("a");
		for (var i=0, l=anchors.length; i<l; i++) {
			var anchor=anchors[i];
			if (anchor.title=="")
				anchor.title=anchor.innerText;
			if (anchor.href=="") {
				anchor.target="";
				anchor.href="javascript:void(0);";
			}
		}
	}
}

function moveNext() {
	if (treeSelected==null) {
		var root=document.getElementById("treeRoot");
		if (root!=null) {
			var children=root.childNodes;
			if (children!=null) {
				for (var i=0, l=children.length; i<l; i++) {
					var child=root.childNodes[i];
					if (child.className=="treeNode") {
						selectAndShowNode(child);
						var anchor=child.getElementsByTagName("a")(0);
						if (anchor.target!="") {
							if (top.section)
								top.section.frames(anchor.target).location=anchor.href;
							else
								top.frames(anchor.target).location=anchor.href;
						}
						break;
					}
				}
			}
		}
	}
	else {
		var next=getNext(treeSelected);
		if (next!=null) {
			selectAndShowNode(next);
			var anchor=next.getElementsByTagName("a")(0);
			if (anchor.target!="")
				if (top.section)
					top.section.frames(anchor.target).location=anchor.href;
				else
					top.frames(anchor.target).location=anchor.href;
		}
	}
}

function getNext(el) {
	if (el==null || el.id=="treeRoot") return null;
	
	var next=el.firstChild;
	while (next!=null && next.nodeName!="DIV")
		next=next.nextSibling;
	if (next==null) {
		next=el.nextSibling;
		while (next!=null && next.nodeName!="DIV")
			next=next.nextSibling;
		if (next==null) {
			var parent=el.parentNode;
			while (parent!=null && parent.id!="treeRoot" && parent.nextSibling==null)
				parent=parent.parentNode;
			if (parent==null || parent.id=="treeRoot")
				return null;
			var sibling=parent.nextSibling;
			if (sibling.className=="treeNode")
				return sibling;
			else
				return getNext(sibling);
		}
	}
	if (next.className=="treeNode")
		return next;
	else
		return getNext(next);
}

function movePrevious() {
	if (treeSelected==null) {
		var root=document.getElementById("treeRoot");
		if (root!=null) {
			var children=root.childNodes;
			if (children!=null) {
				for (var i=0, l=children.length; i<l; i++) {
					var child=root.childNodes[i];
					if (child.className=="treeNode") {
						var last=getLast(child);
						if (last!=null) {
							selectAndShowNode(last);
							var anchor=last.getElementsByTagName("a")(0);
							if (anchor.target!="") {
								if (top.section)
									top.section.frames(anchor.target).location=anchor.href;
								else
									top.frames(anchor.target).location=anchor.href;
							}
							break;
						}
					}
				}
			}
		}
	}
	else {
		var previous=getPrevious(findNode(treeSelected));
		if (previous!=null) {
			selectAndShowNode(previous);
			var anchor=previous.getElementsByTagName("a")(0);
			if (anchor.target!="") {
				if (top.section)
					top.section.frames(anchor.target).location=anchor.href;
				else
					top.frames(anchor.target).location=anchor.href;
			}
		}
	}
}

function getPrevious(el) {
	if (el==null) return null;
	var previous=el.previousSibling;
	if (previous==null) {
		previous=el.parentNode;
		while (previous!=null && parent.id!="treeRoot" && previous.className!="treeNode")
			previous=previous.parentNode;
		if (previous==null || parent.id=="treeRoot")
			return null;
		else
			return previous;
	}
	else {
		// Dig in
		return getLast(previous);
	}
}

function getLast(el) {
	var subnodes=el.firstChild;
	while (subnodes!=null && subnodes.nodeName!="DIV")
		subnodes=subnodes.nextSibling;
	if (subnodes==null || (subnodes.className!="treeSubnodesHidden" && subnodes.className!="treeSubnodes"))
		return el;
	if (subnodes.hasChildNodes())
		return getLast(subnodes.lastChild);
	else
		return e1;
}

function findNode(el) {
	// Takes element and determines if it is a treeNode.
	// If not, seeks a treeNode in its parents.
	while (el!=null) {
		if (el.className=="treeNode") {
			break;
		}
		else {
			el=el.parentNode;
		}
	}
	return el;
}

function clickAnchor(el) {
	// Handles click on a TOC link
	expandNode(el.parentNode);
	selectNode(el.parentNode);
	el.blur();
}

function selectNode(el) {
	// Un-selects currently selected node, if any, and selects the specified node
	if (treeSelected!=null) {
		setSubNodeClass(treeSelected, 'A', 'treeUnselected');
	}
	setSubNodeClass(el, 'A', 'treeSelected');
	treeSelected=el;
}

function setSubNodeClass(el, nodeName, className) {
	// Sets the specified class name on el's first child that is a nodeName element
	var child;
	for (var i=0; i<el.childNodes.length; i++) {
		child=el.childNodes[i];
		if (child.nodeName==nodeName) {
			child.className=className;
			break;
		}
	}
}

function expandCollapse(el) {
	// If source treeNode has child nodes, expand or collapse view of treeNode
	if (el==null) return;	// Do nothing if it isn't a treeNode
		
	var child;
	var imgEl;
	for (var i=0; i < el.childNodes.length; i++) {
		child=el.childNodes[i];
		if (child.src) {
			imgEl=child;
		}
		else if (child.className=="treeSubnodesHidden") {
			child.className="treeSubnodes";
			imgEl.src=imgMinus.src;
			break;
		}
		else if (child.className=="treeSubnodes") {
			child.className="treeSubnodesHidden";
			imgEl.src=imgPlus.src;
			break;
		}
	}
}

function expandNode(el) {
	// If source treeNode has child nodes, expand it
	var child;
	var imgEl;
	for (var i=0; i<el.childNodes.length; i++) {
		child = el.childNodes[i];
		if (child.src)
			imgEl=child;
		if (child.className=="treeSubnodesHidden") {
			child.className = "treeSubnodes";
			imgEl.src = imgMinus.src;
			break;
		}
	}
}

function syncTree(href) {
	// Selects and scrolls into view the node that references the specified URL
	var loc=new String();
	loc=href.toLowerCase();
	if (loc.substring(0, 7)=='file://') {
		loc='file:///'+loc.substring(7, loc.length);
		loc=loc.replace(/\\/g, '/');
	}

	var base=loc.substr(0, loc.lastIndexOf('/')+1);
	var tocEl=findHref(document.getElementById('treeRoot'), loc, base);
	if (tocEl!=null) {
		selectAndShowNode(tocEl);
	}
}

function findHref(node, href, base) {
	// Find the <a> element with the specified href value
	var el;
	var anchors=node.getElementsByTagName('a');
	var i=0;
	while (i<anchors.length) {
	  el=anchors[i];
		var aref=new String();
		aref=el.getAttribute('href').toLowerCase();
		if (aref!=null) {
		  if ((aref.substring(0, 7)!='http://') &&
				(aref.substring(0, 8)!='https://') &&
				(aref.substring(0, 11)!='javascript:') &&
				(aref.substring(0, 7)!='file://'))
			  aref=base+aref;
    
		  if (aref==href)
			  return el;
		}
		i++;
	}
	return null;
}

function selectAndShowNode(node) {
	// Selects and scrolls into view the specified node
	var el=findNode(node);
	if (el!=null) {
		selectNode(el);
		do {
			expandNode(el);
			el=findNode(el.parentNode);
		} while (el!=null)
		
		// Vertical scroll element into view
		var windowTop;
		var windowBottom;
		var treeDiv=document.getElementById('tree');
		
		var ua=window.navigator.userAgent.toLowerCase();
		if ((i=ua.indexOf('msie'))!=-1) {
			windowTop=node.offsetTop-treeDiv.scrollTop;
			windowBottom=treeDiv.clientHeight-windowTop-node.offsetHeight;
		}
		else if (ua.indexOf('gecko')!=-1) {
			windowTop=node.offsetTop-treeDiv.offsetTop-treeDiv.scrollTop;
			windowBottom=treeDiv.clientHeight-windowTop-node.offsetHeight;
		}
		else
			return;
		
		if (windowTop<0) {
			treeDiv.scrollTop+=windowTop-18;
			return;
		}
		if (windowBottom<0) {
			treeDiv.scrollTop-=windowBottom-18;
			return;
		}
	}
}

function resizeTree() {
	var treeDiv=document.getElementById('tree');
	treeDiv.style.width=document.documentElement.offsetWidth;
	treeDiv.style.height=document.documentElement.offsetHeight-27;
}

