/*

tree (version 3.5) by Riki "Fczbkk" Fridrich, 2002
http://www.fczbkk.com/
mailto:riki@fczbkk.com

You should find latest version of this script and documentation at
http://www.fczbkk.com/js/tree/

*/



// object holding all functions and variables
tree = {
	/* ------------------ user customization starts here ------------------ */
	
	// classes used in HTML document to mark important elements
	classRoot			: "tree",		// ULs with this class will be transformed into trees
	classDefault		: "default",	// LIs with this class will be expanded by default
	classLast			: "last",		// this class will be added to all last branches of the tree
										// (this is good for easier CSS formatting of the tree)
	
	// paths to images used in tree nodes
	nodeExpand			: "images/tree-plus.gif",		// image of expandable node
	nodeExpandAlt		: "[ + ] ",
	nodeCollapse		: "images/tree-minus.gif",		// image of collapsable node
	nodeCollapseAlt		: "[ - ] ",
	nodeNone			: "images/tree-none.gif",		// image for node without children
	nodeNoneAlt			: "[ · ] ",
	
	/* ------------------ user customization ends here ------------------ */	


	// initialisation of the tree
	init : function() {
		// find all unordered lists marked as trees
		var uls = tree.getElementsByClassName(document, tree.classRoot, "ul");
		for (var i = 0; i < uls.length; i++) {
			// find all last branches of the tree and mark them
			tree.markLast(uls[i]);
			var uls2 = uls[i].getElementsByTagName("ul");
			for (var j = 0; j < uls2.length; j++) {
				tree.markLast(uls2[j]);
			}
			
			// ad node pictures to all branches
			var lis = uls[i].getElementsByTagName("li");
			for (var j = 0; j < lis.length; j++) {
				tree.addNode(lis[j]);
			}
			
			// collapse all branches at the start
			tree.collapseAll(uls[i]);
			
			// find default branches and expand them		
			var def = tree.getElementsByClassName(uls[i], tree.classDefault, "li");
			for (var j = 0; j < def.length; j++) {
				var path = new Array();
				var step = def[j];
				while (step != uls[i]) {
					if (step.tagName == "LI") {
						tree.expand(step);
					}
					step = step.parentNode;
				}
			}
		}
	},

	// adds node picture at the beginning of all branches
	addNode : function(elm) {
		var uls = elm.getElementsByTagName("ul");
		var image = document.createElement("img");
		if (uls.length > 0) {
			image.src = tree.nodeExpand;
			image.alt = tree.nodeExpandAlt;
			evt.add(image, "click", tree.changeState);
		} else {
			image.src = tree.nodeNone;
			image.alt = tree.nodeNoneAlt;
		}
		elm.insertBefore(image, elm.firstChild);
	},
	
	// gets the actual state of branch and changes it
	changeState : function(e) {
		e = evt.fix(e);
		var obj = (e.currentTarget) ? e.currentTarget : e.target;
		while (obj.tagName != "LI") {
			obj = obj.parentNode;
		}
		if (obj.state == "collapsed") {
			tree.expand(obj);
		} else {
			tree.collapse(obj);
		}
	},
	
	// expands given branch
	expand : function(elm) {
		var uls = elm.getElementsByTagName("ul");
		for (var i = 0; i < uls.length; i++) {
			if (uls[i].parentNode == elm) {
				uls[i].style.display = "block";
				uls[i].parentNode.state = "expanded";
				elm.firstChild.src = tree.nodeCollapse;
				elm.firstChild.alt = tree.nodeCollapseAlt;
			}
		}
	},
	
	// collapses given branch
	collapse : function(elm) {
		var uls = elm.getElementsByTagName("ul");
		for (var i = 0; i < uls.length; i++) {
			if (uls[i].parentNode == elm) {
				uls[i].style.display = "none";
				uls[i].parentNode.state = "collapsed";
				elm.firstChild.src = tree.nodeExpand;
				elm.firstChild.alt = tree.nodeExpandAlt;
			}
		}
	},
	
	// collapses all branches in the given tree
	collapseAll : function(elm) {
		if (elm.tagName == "LI") {tree.expand(elm);}
		var lis = elm.getElementsByTagName("li");
		for (var i = 0; i < lis.length; i++) {
			tree.collapse(lis[i]);
		}
	},
	
	// expands all branches in the given tree
	expandAll : function(elm) {
		if (elm.tagName == "LI") {tree.expand(elm);}
		var lis = elm.getElementsByTagName("li");
		for (var i = 0; i < lis.length; i++) {
			tree.expand(lis[i]);
		}
	},
	
	// marks the last branch in the given branch as last
	markLast : function(elm) {
		var lis = elm.getElementsByTagName("li");
		var i = lis.length - 1;
		while (lis[i].parentNode != elm) {i--;}
		cls.add(lis[i], tree.classLast);
	},
	
	// returns all elements with given class, that are children of given source element
	// attribute tagName is not required, but it speeds up the function a bit
	getElementsByClassName : function(srcElm, clName, tName) {
		foundElements = [];
		tName = (tName) ? tName.toUpperCase() : "*";
		allElements = srcElm.getElementsByTagName(tName);
		for (var i = 0; i < allElements.length; i++) {
			if (cls.has(allElements[i], clName)) {
				foundElements[foundElements.length] = allElements[i];
			}
		}
		return foundElements;
	}

};








// initialisation of the script on load
evt.add(window, "load", tree.init);
