//javascript.js

function init() {
	var inputs = document.getElementsByTagName('input');
	for (var i=0; i<inputs.length; i++) {
		var input = inputs[i];
		if (input.getAttribute('type') == 'text') {
			if (document.all) {
				//ie needs onkeydown for tab and backspace
				input.onkeydown = reactToKeypress;
			}
			else {
				//sane browsers use onkeypress
				input.onkeypress = reactToKeypress;		
			}
		}
	}
}

function reactToKeypress(e) {
	if (!e) {
		var e = window.event; // e gives access to the event in all browsers
	}
//	alert(e.keyCode);
	
	if(e.keyCode == '38' || e.keyCode == '63232') {
	//firefox keycode 8: up arrow
	//safari keycode 63232: up arrow
		var txtInput = this;
		var listItem = this.parentNode;
		var parentUL = getParentUL(listItem);
		
		var LI_index = getIndexOfLI(parentUL, listItem);
		var siblings = getSiblingLIs(parentUL, listItem);
		var txtInput_to_focus;
		
		if(LI_index > 0) {
			txtInput_to_focus = siblings[LI_index - 1].firstChild;
			txtInput_to_focus.setAttribute('id', 'active');
		}		
		
		setTimeout("focusActive()", 50);
	}
	
	if(e.keyCode == '40' || e.keyCode == '63233') {
	//firefox keycode 40: down arrow
	//safari keycode 63233: down arrow
		var txtInput = this;
		var listItem = this.parentNode;
		var parentUL = getParentUL(listItem);
		
		var LI_index = getIndexOfLI(parentUL, listItem);
		var siblings = getSiblingLIs(parentUL, listItem);
		var txtInput_to_focus;
		
		if(LI_index != siblings.length - 1) {
			txtInput_to_focus = siblings[LI_index + 1].firstChild;
			txtInput_to_focus.setAttribute('id', 'active');
		}		
		setTimeout("focusActive()", 50);
	}
		
	
	if(e.keyCode == '8') {
	//keycode 8: backspace -> delete LI if txt is empty
		if(this.value == '') {
			var txtInput = this;
			var listItem = this.parentNode;
			var parentUL = getParentUL(listItem);
			
			var LI_index = getIndexOfLI(parentUL, listItem);
			var siblings = getSiblingLIs(parentUL, listItem);
			var txtInput_to_focus;
			
			if(LI_index < siblings.length - 1) {
				//there's at least one sibling after this list item so set the focus to that one after removal
				txtInput_to_focus = siblings[LI_index + 1].firstChild;
				txtInput_to_focus.setAttribute('id', 'active');
			}
			else {
				//there's no siblings after this so we'll want to focus on prev sibling (if it exists) after removal
				if (LI_index != 0) {
					//prev sibling exists
					txtInput_to_focus = siblings[LI_index - 1].firstChild;
					txtInput_to_focus.setAttribute('id', 'active');
				}
				else {
					//no prev sibling exists (this is the only node in this UL)
					if(parentUL.parentNode.nodeName == 'BODY') {
						return; //not allowed to delete the last root node
					}
					else {
						//focus on parentUL's txtInput
						//hilite(parentUL.parentNode.firstChild); 
						txtInput_to_focus = parentUL.parentNode.firstChild;
						txtInput_to_focus.setAttribute('id', 'active');
					}
				}
			}
			
			//do the removals
			listItem.removeChild(txtInput);
			parentUL.removeChild(listItem);
			
			setTimeout("focusActive()", 50);			
		}
	}
		
	if (e.keyCode == '9' && e.shiftKey == false) {
	//keycode 9: <tab>	-> indent
		var txtInput = this;
		var listItem = txtInput.parentNode;
		var current_ul = listItem.parentNode;
		var current_ul_parent = current_ul.parentNode;
		
		if (prevLIExists(listItem)) {
			this.setAttribute('id', 'active');
			indentLI(listItem);
			setTimeout("focusActive()", 50);
		}
		else {
			//we're at the root node for this ul, so you can't indent
		}

		//reset focus because otherwise it's lost upon new element creation		
		this.focus();
	}

	if (e.keyCode == '13') {
	//keycode 33: <enter> -> new line
		var txtInput = this;
		var listItem = txtInput.parentNode;

		insertNewLineAfterLI(listItem);
		setTimeout("focusActive()", 50);
	}
	
	if ((e.keyCode == '9' && e.shiftKey == true) ||
		(e.keyCode == '25' && e.shiftKey == true)) {
		// firefox correctly reports keyCode 9 for shift+tab
		// safari reports keyCode '25' for shift+tab

		var txtInput = this;
		this.setAttribute('id', 'active');
		var listItem = txtInput.parentNode;
		
		unIndent(listItem);
		setTimeout("focusActive()", 50);
		return false;
	}
	
}

function focusActive() {
	var element = document.getElementById('active');
	element.focus();
	element.removeAttribute("id");	
}

function hilite(element) {
	element.setAttribute('style', 'border: 7px solid yellow');
}

function unIndent(listItem) {
	if (listItem.parentNode.parentNode.nodeName != 'BODY') {
		var containingUL = getParentUL(listItem);
		var parentUL = containingUL.parentNode;
		
		insertAfter(parentUL.parentNode, listItem, containingUL.parentNode);
	}
}

function getIndexOfLI(parentUL, targetLI) {
	var allChildLIs = parentUL.getElementsByTagName('LI');
	var siblingLIs = new Array();
	
	//populate siblingLIs from allChildLIs
	for (var i=0; i<allChildLIs.length; i++) {
		var LI = allChildLIs[i];
		if (LI.parentNode == targetLI.parentNode) {
			siblingLIs[siblingLIs.length] = LI;
		}
	}
		
	//find this element's position amongst the other LI's in thne parent UL
	for (var i=0; i<siblingLIs.length; i++) {
		if (siblingLIs[i] == targetLI) {
			return i;
			break;
		}
	}
	
	//if we got this far, then no match
	return null;
}

function insertNewLineAfterLI(listItem) {
		var parentUL = listItem.parentNode;
		
		var newLI = document.createElement('li');
		var newTextInput = document.createElement('input');
		
		newTextInput.setAttribute("type", "text");
		if (document.all) {
			//ie needs onkeydown for tab and backspace
			newTextInput.onkeydown = reactToKeypress;
		}
		else {
			//sane browsers use onkeypress
			newTextInput.onkeypress = reactToKeypress;
		}

		newLI.appendChild(newTextInput);

		//insert after current txtinput list item
		insertAfter(parentUL, newLI, listItem);
		
		newTextInput.setAttribute('id', 'active');
}

function insertAfter(parent, node, referenceNode) {
    parent.insertBefore(node, referenceNode.nextSibling);
}

function prevLIExists(listItem) {
	if (getPrevLI(listItem) != null &&
		getPrevLI(listItem).nodeName == 'LI') {
		return true;
	}
	else {
		return false;
	}
}

function getParentUL(element) {
	if (element.nodeName != 'UL' && element.nodeName != 'BODY') {
		return(getParentUL(element.parentNode));
	}
	else {
		return(element);
	}
}

function getPrevLI(element) {
	var parentUL = getParentUL(element);
	var allChildLIs = parentUL.getElementsByTagName('LI');
	var siblingLIs = new Array();
	
	//populate siblingLIs from allChildLIs
	for (var i=0; i<allChildLIs.length; i++) {
		var LI = allChildLIs[i];
		if (LI.parentNode == element.parentNode) {
			siblingLIs[siblingLIs.length] = LI;
		}
	}
		
	//find this element's position amongst the other LI's in thne parent UL
	for (var i=0; i<siblingLIs.length; i++) {
		if (siblingLIs[i] == element) {
			break;
		}
	}
	
	var prevLI = siblingLIs[i-1];
	return prevLI;
}

function getSiblingLIs(parentUL, targetLI) {
	var allChildLIs = parentUL.getElementsByTagName('LI');
	var siblingLIs = new Array();
	
	//populate siblingLIs from allChildLIs
	for (var i=0; i<allChildLIs.length; i++) {
		var LI = allChildLIs[i];
		if (LI.parentNode == targetLI.parentNode) {
			siblingLIs[siblingLIs.length] = LI;
		}
	}
	return siblingLIs;
}

function prevLIHasUL(listItem) {
	var prevLI = getPrevLI(listItem);
	if (prevLI && prevLI.getElementsByTagName('ul').length != 0) {
		return true;
	}
	else {
		return false;
	}
}

function indentLI(listItem) {
	if (prevLIHasUL(listItem)) {
		//make this the last child of the prev li's ul				
		newParent = getPrevLI(listItem).getElementsByTagName('ul').item(0);
		newParent.appendChild(listItem);
	}
	else {
		//make a new UL for prev LI and make this a child of the prev LI's new UL
		newParent = getPrevLI(listItem);
		var ul = document.createElement('ul');
		ul.appendChild(listItem);
		newParent.appendChild(ul);
	}
}

/*
<ul>
<li><input id="txt1" type="text" size="20" />
	<ul>
		<li><input id="txt2" type="text" size="20" /></li>
		<li><input id="txt3" type="text" size="20" /></li>
	</ul>
</li>
<li><input id="txt4" type="text" size="20" /></li>
<li><input id="txt5" type="text" size="20" /></li>
</ul>

*/
