addEvent(window, 'load', initTrees);

// function for summable lists (used internally and externally)
function updateTotal(currentInput, inputClass, divId, isCurrency, currencySymbol, groupSeparator, decimalSeparator) {
	var totalDiv = document.getElementById(divId);

	if (decimalSeparator == null) decimalSeparator = '.';

	// create variable for precision because we'll need to determine precision below if non-currency
	var precision = 0;
	if (isCurrency) {
		precision = 2;		// always assume two digits for any currency
	} 

	// make sure div containing total exists before doing all the calculations
	if (totalDiv) {
		// set to default if not indicated
		if (isCurrency == null) isCurrency = false;
		if (currencySymbol == null) currencySymbol = '$';
		if (groupSeparator == null) groupSeparator = ',';

		// define regular expression to be used
		var reg;
		// account for $ being special
		if (currencySymbol == '$') {
			reg = new RegExp("\\" + currencySymbol + "|" + groupSeparator, "gi");	// global, case-insensitive match
		} else {
			reg = new RegExp(currencySymbol + "|" + groupSeparator, "gi");			// global, case-insensitive match
		}
		var currValue = currentInput.value.replace(reg, '');
		var total = 0;

		if (isNaN(currValue)) {
			alert("Please enter a valid numbers!");
			currentInput.value = '';
			currentInput.focus();
		} else {
			// get values for each text box, convert to number
			var numberInput = getElementsByClass(inputClass,'input');
			var cleanedNumber;
			for (var i = 0; i < numberInput.length; i++) {
				cleanedNumber = numberInput[i].value;
				if (cleanedNumber != '') {
					// find the highest degree of precision used, and keep the summary at that level
					if (cleanedNumber.indexOf(decimalSeparator) >= 0) {
						if ((cleanedNumber.substring(cleanedNumber.indexOf(".") + 1)).length > precision) 
							precision = (cleanedNumber.substring(cleanedNumber.indexOf(".") + 1)).length;
					}

					cleanedNumber = cleanedNumber.replace(reg, '');
					total = total + (cleanedNumber * 1);	// convert to number
				}
			}

			// format the total as needed; need to set precision due to the conversion of numbers from base 2 and then back to base 10
			var formattedTotal = formatNumber((total.toFixed(precision)), groupSeparator, isCurrency, currencySymbol);

			totalDiv.firstChild.nodeValue = formattedTotal;
		}

		// check for a wrapper parent that is currently hidden
		var parentSpan = document.getElementById(divId + "Wrapper");
		if (parentSpan) {
			parentSpan.style.display = 'inline';
		}
	}
}

/*
 * Based on javascript tree widget at http://www.silverstripe.com/blog
 * Copyright (C) 2005 SilverStripe Limited
*/

/*
 * Initialise all trees identified by <ul class="tree">
 */
function initTrees() {
	var trees = getElementsByClass('tree', 'ul');
	if (trees && trees.length > 0) {

		if (testforDOMBug()) {
			for(var i = 0; i < trees.length; i++) {
				initTree(trees[i]);
			}
		} else {
			var closedLi = getElementsByClass("closed", "li");

			for(var i = 0; i < closedLi.length; i++) {
				removeClass(closedLi[i], "closed");
			}
		}
	}
}

// https://bugzilla.mozilla.org/show_bug.cgi?id=204784
// workaround for bug where when DOM functions are used to move/create input elements, they are added to the end of the elements array
function testforDOMBug() {
	var ok = false;
	var parentNode = document.forms[0];

	if (parentNode) {
		// create a couple of hidden inputs, and add one in front of the other (as far as document tree), then compare with order in elements array
		var testNode1 = document.createElement("input");
		var testNode2 = document.createElement("input");

		testNode1.setAttribute("type", "hidden");
		testNode1.setAttribute("name", "dummy");
		testNode1.setAttribute("value", "1");

		testNode2.setAttribute("type", "hidden");
		testNode2.setAttribute("name", "dummy");
		testNode2.setAttribute("value", "2");

		parentNode.appendChild(testNode2);
		parentNode.insertBefore(testNode1, testNode2);

		// testNode1 should be first in elements, but if not, return false
		var checkString = ""

		var formChildren = parentNode.elements;
		for(i = 0; i < formChildren.length; i++) {
			if(formChildren[i].name && formChildren[i].name.toLowerCase() == 'dummy') {
				checkString = checkString + formChildren[i].value;
			}
		}

		if (checkString == "12") {
			ok = true;
		}

		parentNode.removeChild(testNode1);
		parentNode.removeChild(testNode2);

		return ok;
	}
}
 
/*
 * Initialise a tree node, converting all its LIs appropriately
 */
function initTree(el) {
	
	// Find all LIs to process
	var childLis = el.childNodes;

	for(var i = 0; i < childLis.length; i++) {
		if(childLis[i].tagName && childLis[i].tagName.toLowerCase() == 'li') {
			var spanA, spanB, spanC;
			var startingPoint, stoppingPoint, childUL;

			var li = childLis[i];

			// Create our extra spans
			spanA = document.createElement('span');
			spanB = document.createElement('span');
			spanC = document.createElement('span');
			spanA.appendChild(spanB);
			spanB.appendChild(spanC);
			if (hasClass(li, 'closed')) {
				spanA.className = 'a spanClosed';
			} else {
				spanA.className = 'a';
			}
			spanA.onMouseOver = function() {}
			spanB.className = 'b';
			spanB.onclick = treeToggle;
			spanC.className = 'c';
			
			
			// Find the UL within the LI, if it exists
			stoppingPoint = li.childNodes.length;
			startingPoint = 0;
			childUL = null;

			for(var j = 0; j < li.childNodes.length; j++) {
				if(li.childNodes[j].tagName && li.childNodes[j].tagName.toLowerCase() == 'ul') {
					childUL = li.childNodes[j];
					stoppingPoint = j;
					break;					
				}
			}
				
			// Move all the nodes up until that point into spanC
			for(j=startingPoint;j<stoppingPoint;j++) {
				spanC.appendChild(li.childNodes[startingPoint]);
			}
			
			// Insert the outermost extra span into the tree
			if (childUL != null) {
				li.insertBefore(spanA, li.firstChild);	// the first child should be the UL at this point

//				li.insertBefore(spanA, li.childNodes[startingPoint]);
			} else li.appendChild(spanA);
			
			// Process the children
			if(childUL != null) {
				if(initTree(childUL)) {
					addClass(li, 'children', 'closed');
					addClass(spanA, 'children', 'spanClosed');
				}
			}
		}
	}
	
	if(li) {
		// li and spanA will still be set to the last item
		addClass(li, 'last', 'closed');
		addClass(spanA, 'last', 'spanClosed');
		return true;
	} else {
		return false;
	}
		
}
 

/*
 * +/- toggle the tree, where el is the <span class="b"> node
 * force, will force it to "open" or "close"
 */
function treeToggle(el, force) {
	el = this;
	
	while(el != null && (!el.tagName || el.tagName.toLowerCase() != "li")) el = el.parentNode;
	
	// Get UL within the LI
	var childSet = findChildWithTag(el, 'ul');
	var topSpan = findChildWithTag(el, 'span');

	if( force != null ){
		
		if( force == "open"){
			treeOpen( topSpan, el )
		}
		else if( force == "close" ){
			treeClose( topSpan, el )
		}
		
	}
	
	else if( childSet != null) {
		// Is open, close it
		if(!el.className.match(/(^| )closed($| )/)) {		
			treeClose( topSpan, el )
		// Is closed, open it
		} else {			
			treeOpen( topSpan, el )
		}
	}
}


function treeOpen( a, b ){
	removeClass(a,'spanClosed');
	removeClass(b,'closed');
}
	
	
function treeClose( a, b ){
	addClass(a,'spanClosed');
	addClass(b,'closed');
}

/*
 * Find the a child of el of type tag
 */
function findChildWithTag(el, tag) {
	for(var i=0;i<el.childNodes.length;i++) {
		if(el.childNodes[i].tagName != null && el.childNodes[i].tagName.toLowerCase() == tag) return el.childNodes[i];
	}
	return null;
}


