function collapsible() {
	
	this.cookieLoaded = false;
	
	this.params = {
		id: '',
		expandedImg: '',
		collapsedImg: '',
		branchClass: 'branch',
		iconImageStyle: 'border: solid 1px;',
		collapsed: new Array(),
		persist: null
	};
	
	for (var n in arguments[0]) {this.params[n] = arguments[0][n];}
	
	this.params.expanded = new Array();
	
	//START OF HELPER FUNCTIONS
	this.getElementsByClass = function(searchClass, node, tag) {
		if (tag == null) {tag = "*";}
		var elements = node.getElementsByTagName(tag);
		var results = new Array();
		searchClass = " " + searchClass + " ";
		for (var i = 0; i < elements.length; i++) {
			var elementClass = " " + elements[i].className + " ";
			if (elementClass.indexOf(searchClass) != -1) {
				results[results.length] = elements[i];
			}
		}
		return results;
	}
	
	this.belongsToClass = function(node, searchClass) {
		searchClass = " " + searchClass + " ";
		var nodeClass = " " + node.className + " ";
		if (nodeClass.indexOf(searchClass) != -1) {
			return true;
		}
		return false;
	}
	
	this.inArray = function(needle, haystack, strict) {
		for (index in haystack) {
			if (strict) {
				if (haystack[index] === needle) {return true;}
			}else {
				if (haystack[index] == needle) {return true;}
			}
		}
		return false;
	}
	//END OF HELPER FUNCTIONS
	
	this.expandNode = function(node) {
		node.parentNode.style.listStyleImage = "url(" + this.params.expandedImg + ")";
		var iconImg = document.getElementById(node.id + "img");
		if (iconImg != null) {
			iconImg.src = this.params.expandedImg;
		}
		var nodes = node.parentNode.childNodes;
		for (var i = 0; i < nodes.length; i++) {
			if (nodes[i].nodeType == 1) {
				if (!this.belongsToClass(nodes[i], this.params.branchClass)) {
					nodes[i].style.display = nodes[i].displayx;
					nodes[i].style.listStyleImage = "none";
				}
			}
		}
	}
	
	this.collapseNode = function(node) {
		node.parentNode.style.listStyleImage = "url(" + this.params.collapsedImg + ")";
		var iconImg = document.getElementById(node.id + "img");
		if (iconImg != null) {
			iconImg.src = this.params.collapsedImg;
		}
		var nodes = node.parentNode.childNodes;
		for (var i = 0; i < nodes.length; i++) {
			if (nodes[i].nodeType == 1) {
				if (!this.belongsToClass(nodes[i], this.params.branchClass)) {
					nodes[i].style.display = "none";
				}
			}
		}
	}
	
	this.toggleNode = function(node) {
		var rVal = false;
		for (var i = 0; i < this.params.collapsed.length; i++) {
			if (this.params.collapsed[i] == node.id) {
				this.expandNode(node);
				this.params.collapsed.splice(i, 1);
				this.params.expanded.push(node.id);
				rVal = true;
			}
		}
		if (!rVal) {
			this.collapseNode(node);
			for (var i = 0; i < this.params.expanded.length; i++) {
				if (this.params.expanded[i] == node.id) {
					this.params.expanded.splice(i, 1);
				}
			}
			this.params.collapsed.push(node.id);
		}
		if (this.params.persist) {
			this.writeCookie(this.params.id + "-expanded", this.params.expanded);
		}
		return rVal;
	}
	
	this.writeCookie = function(name, value, duration) {
		if (duration) {
			var date = new Date();
			date.setTime(date.getTime() + duration);
			duration = "; expires=" + date.toGMTString();
		}else {
			duration = "";
		}
		document.cookie = name + "=" + value + duration + "; path=/";
	}
	
	this.readCookie = function(name) {
		var name = name + "=";
		var crumbs = document.cookie.split(';');
		for(var i = 0; i < crumbs.length; i++) {
			var crumb = crumbs[i];
			while (crumb.charAt(0) == ' ') {
				crumb = crumb.substring(1, crumb.length);
			}
			if (crumb.indexOf(name) == 0) {
				return crumb.substring(name.length, crumb.length);
			}
		}
		return null;
	}
	
	//START OF INITIALISATION STUFF ("\(o_o)/") RAWR
	if (this.params.persist && (this.readCookie(this.params.id + "-expanded") != null)) {
		var tmp = this.readCookie(this.params.id + "-expanded").split(",");
		for(var i = 0; i < tmp.length; i++) {
			if (document.getElementById(tmp[i]) != null) {
				for (var j = 0; j < this.params.collapsed.length; j++) {
					if (this.params.collapsed[j] == tmp[i]) {
						this.params.collapsed.splice(j, 1);
					}
				}
				this.params.expanded.push(tmp[i]);
			}
		}
		this.cookieLoaded = true;
	}
	//Store a copy of each nodes current display mode in the node itself.
	var nodes = document.getElementById(this.params.id).getElementsByTagName("*");
	for(var i = 0; i < nodes.length; i++) {
		if (nodes[i].nodeType == 1) {
			if (nodes[i].displayx == undefined) {
				nodes[i].displayx = nodes[i].style.display;
			}
		}
	}
	
	//Initialise all branches
	var self = this;
	var branches = this.getElementsByClass(this.params.branchClass, document.getElementById(this.params.id));
	for(var i = 0; i < branches.length; i++) {
		//Prepend non list-item branches with an image
		if (branches[i].parentNode.tagName.toLowerCase() != "li") {
			branches[i].innerHTML = "<img src='" + this.params.expandedImg + "' " + "id='" + branches[i].id + "img'" + " style='" + this.params.iconImageStyle + "' /> " + branches[i].innerHTML;
		}
		//Enclose branch in an anchor
		branches[i].innerHTML = "<a href='javascript:void(null);'>" + branches[i].innerHTML + "</a>";
		//Add onclick function to the first anchor in the branch (the one just added)
		var anchors = branches[i].getElementsByTagName("a");
		anchors[0].onclick = function() {self.toggleNode(this.parentNode);};
		this.expandNode(branches[i]);
		/*If a cookie has been loaded, add branch to collapsed branches list if 
		it is not present in either the collapsed or expanded lists
		If a cookie has not been loaded, add the branch to the expanded branches
		list*/
		if (!this.inArray(branches[i].id, this.params.collapsed)) {
			if (!this.inArray(branches[i].id, this.params.expanded)) {
				if (!this.cookieLoaded) {
					this.params.expanded.push(branches[i].id);
				}else {
					this.params.collapsed.push(branches[i].id);
				}
			}
		}
	}
	
	//Collapse any nodes marked as collapsed.
	for(var i = 0; i < this.params.collapsed.length; i++) {
		this.collapseNode(document.getElementById(this.params.collapsed[i]));
	}
	//END OF INITIALISATION STUFF ("\(-_-)/") YAWN
}
