$(document).ready(function() {
	$("ul.tree").each(function(i) {
		processList(this);
	});
});

/**
 * Looks for element with specified id and expands tree path to the founded element. Id of element
 * must be unique through document, otherwise only first founded element will be expanded.
 * @param itemId id of element.
 */
function expandItem(itemId) {
	$("#" + itemId).parents("li.treeItemClosed").each(function(i) {
		$(this).removeClass("treeItemClosed");
		$(this).addClass("treeItemOpened");
	});
}

/**
 * Processes specified ul element to convert it into js tree.
 * @param ul ul element
 */
function processList(ul) {
	//If list has no children, then we have nothing to do.
	$(ul).children("li").each(function(i) {
		var subLists = false;
		   
		//recursive processing of nested lists
		$(this).children("ul").each(function(i) {
			subLists = true;
			processList(this);
		});

		var span = document.createElement("SPAN");
		var t = '\u00A0'; // &nbsp;
		$(span).addClass("treeItem");
		
		if (subLists) {//If item has nested list, then we process the item. 
			//Default state is "closed"
			if (!$(this).is(".treeItemOpened,.treeItemClosed")) {
				$(this).addClass("treeItemClosed");
			}

			//Remove all text nodes, they will be written into span latter.
			var textNodes = jQuery.grep(this.childNodes, function(node){return node.nodeType==3;});
			for (var i =0; i<textNodes.length; i++){
				t+=textNodes[i].nodeValue;
				$(textNodes[i]).remove();
			}

			//On click we
			$(span).click(function () {
				var li = $(this).parent();
				var className = $(li).hasClass("treeItemOpened") ? "treeItemClosed" : "treeItemOpened";
				$(li).removeClass("treeItemOpened treeItemClosed")
				$(li).addClass(className);
				return false;
			});
		}
		else {//No nested list means the item is leaf.
			$(this).addClass("treeItemLeaf");
			$(span).click(function(){ return false;});
		}
		        
		$(span).text(t);
		$(this).prepend(span);
	});
}

