/* ajax.js */

//variables for nodes
var skillArray =[];
var theNodes =[];
var listenerArray=[];
var nodeFile  = "nodes.php";
var allFile =[];
allFile["bg"] =[];
allFile["adv"] =[];
allFile["skill"] =[];
allFile["ak"] =[];

//variables for spinControl
var min = 1;
var max = 5; //can be changed to 3 for HP-buying times
var ms = 500;
var incr = 1;
var running = 0;
var interval = -1;
var bodyEventHooked = false;
var focused;
var spinArray=[];
var knacksMin=[]; //for knack dependency checking
var knacksCurr=[]; //for knack value synchronization

//--------------------------------------------------------------
// BEGIN!
//--------------------------------------------------------------

window.onload=initAll;

function initAll(){
//	MakeRequest(nodeFile);
	initReplace();
	theOpenCloseListeners();
	theAddRmListeners("add");
	theAddRmListeners("rm");
	
	//validate on submit
	for(var i=0; i<document.forms.length;i++){
		document.forms[i].onsubmit=function(){
			return validate();
		}
	}
	//theSubmitListener(); //not for stopping the next page loading
}


//--------------------------------------------------------------
// functions for handling Events across multiple browsers
//--------------------------------------------------------------

//element == node, eventName == the trigger, callback == what function to call
//adding event listeners
function hookEvent(element, eventName, callback){
  if(typeof(element) == "string") element = document.getElementById(element);
  if(element == null) return;
  if(element.addEventListener){
	element.addEventListener(eventName, callback, false);
  } else if(element.attachEvent) element.attachEvent("on" + eventName, callback);
}

//removing event listeners
function unhookEvent(element, eventName, callback){
  if(typeof(element) == "string") element = document.getElementById(element);
  if(element == null) return;
  if(element.removeEventListener) element.removeEventListener(eventName, callback, false);
  else if(element.detachEvent) element.detachEvent("on" + eventName, callback);
}

//getting the thing what the event happened to
function getEventTarget(e){
	e = e ? e : window.event;
	return e.target ? e.target : e.srcElement;
}

//stopping propagation
function cancelEvent(e){
	e = e ? e : window.event;
	if(e.stopPropagation) e.stopPropagation();
	if(e.preventDefault) e.preventDefault();
	e.cancelBubble = true;
	e.cancel = true;
	e.returnValue = false;
	return false;
}


//--------------------------------------------------------------
//this is for general use functions
//--------------------------------------------------------------

function getClassElements(theClass, theNode){
	if(!theNode) theNode=document;
	if(!theClass){
		alert("Problem: no class to find!");
		return false;
	}
	
	//find all the elements
	var allTheElements = theNode.getElementsByTagName("*");
	
	//find just the elements with the proper class
	var classMatch;
	var justTheClass = new Array();
	for(var i=0;i<allTheElements.length;i++){
		//splitting the className string at theClass (length>1 == win)
		classMatch = (allTheElements[i].className.split(theClass)).length;
		if(classMatch>1)
			justTheClass[justTheClass.length]=allTheElements[i];
	}
	//if(!justTheClass[0]) return false;
	return justTheClass;
}

//if no replaceWith, this is more of a "remove class" than a "replace class"
//if no toReplace, this is more of an "add class" than a "replace class"
function replaceClass(theThing, toReplace, replaceWith){
	if(!theThing || (!toReplace && !replaceWith)){
		//replacing empty string with empty string, or missing thing whose class needs editing
		alert("Problem with arguments");
		return false;
	} else if(!toReplace) var newClass = theThing.className+" "+replaceWith; //add a class
	else {
		//replace a class for a thing
		if(!replaceWith){
			//akshully, delete a class from the thing
			replaceWith = "";
		}
		var newClass = "";
		var oldClass = theThing.className;
		oldClass = oldClass.split(" ");
		for(i in oldClass){
			if(oldClass[i].indexOf(toReplace) <= -1){
				if(newClass.length >0) newClass += " ";
				newClass += oldClass[i];
			}
		}
		if(replaceWith.length >0) newClass += " "+replaceWith;
	}

	return newClass;
}


//--------------------------------------------------------------
//this is for validating
//--------------------------------------------------------------

//the LISTENER
function theSubmitListener(){ //use this for validating
	var button = document.getElementsByName("submit");
	for(var i=0;i<button.length;i++){
		hookEvent(button[i],'click', validate);
	}
}

//validate the form when Submit is clicked
function validate(e){
	var allClear = true;
	var failAlert = "";
	var reqd = getClassElements("reqd");
	for(var i in reqd){
		var yourMom = reqd[i].selectedIndex;
		if((reqd[i].nodeName == "INPUT" && reqd[i].value.length <=0/*(doesn't match /\S/)*/) ||
		   (reqd[i].nodeName == "SELECT" && reqd[i].selectedIndex <=0)){
			allClear = false;
			if(failAlert.length>0) failAlert += ", ";
			failAlert += reqd[i].name;
			//find a way to make fail alert add "and " to the last reqd thing as well
		}
	}
	
	if(!allClear){
		alert("You forgot "+failAlert);
	}
	return allClear;
}


//--------------------------------------------------------------
//this is for knack dependencies
//--------------------------------------------------------------

//checking the knack dependency when removing nodes
function knackRm(liNode){
	if(!liNode.parentNode){ //can't delete things except through the document
		return;
	} else if(liNode.parentNode.className.indexOf("knacks") > -1){
		if(knacksMin[liNode.className] > min){
			knacksMin[liNode.className]--;
			if(knacksCurr[liNode.className] > knacksMin[liNode.className] && knacksCurr[liNode.className] <= max)
				knacksCurr[liNode.className]--;
			else if(knacksCurr[liNode.className] > max) knacksCurr[liNode.className] = max-1;
			else knacksCurr[liNode.className] = knacksMin[liNode.className];
			
			var spin;
			var list = getClassElements(liNode.className);
			for(var x in list){
				spin = (list[x].getElementsByTagName("input"))[0];
				if(spin.value > knacksMin[liNode.className] && spin.value > min)
					spin.value = knacksCurr[liNode.className];
			}
		} else knacksMin[liNode.className] = null; //this knack was alone
	} else if(liNode.parentNode.className.indexOf("skills") > -1){
		var someKnacks = (getClassElements("knacks",liNode))[0].getElementsByTagName("li");
		for(var y in someKnacks) knackRm(someKnacks[y]); //RECURSION, WOO
	}
}

//checking the knack dependency when adding nodes
function knackAdd(liNode){
	if(liNode.parentNode == null || liNode.parentNode.className.indexOf("knacks") > -1){
		if(knacksMin[liNode.className] >= min && knacksMin[liNode.className] < max){
			knacksMin[liNode.className]++;
			if(knacksCurr[liNode.className] >= knacksMin[liNode.className] && knacksCurr[liNode.className] < max)
				knacksCurr[liNode.className]++;
			else if(knacksCurr[liNode.className] >= max) knacksCurr[liNode.className] = max;
			else knacksCurr[liNode.className] = knacksMin[liNode.className];
			
			if(liNode.parentNode == null){
				(liNode.getElementsByTagName("input"))[0].value = knacksCurr[liNode.className];
			}
			
			var spin;
			var list = getClassElements(liNode.className);
			for(var x in list){
				spin = (list[x].getElementsByTagName("input"))[0];
				if(spin.value < max) spin.value = knacksCurr[liNode.className];
			}
		} else if(!knacksMin[liNode.className] || knacksMin[liNode.className] < min){
			//this knack is the first
			knacksMin[liNode.className] = min;
		}
	}
}

//check dependency when changing spinControl value
//(spinControl specifically is dealt with later)
function knackSpin(knackVal){
	var liNode = (focused.parentNode).parentNode;
	
	if((liNode.parentNode).className.indexOf("knacks") > -1){
		if(knackVal < knacksMin[liNode.className]) knackVal = knacksMin[liNode.className];
		knacksCurr[liNode.className] = knackVal;
		
		var spin;
		var list = getClassElements(liNode.className);
		for(var x in list){
			spin = (list[x].getElementsByTagName("input"))[0];
			spin.value = knacksCurr[liNode.className];
		}
		return 1; //done!
	} else 
		return 0; //not-a-knack
}


//--------------------------------------------------------------
//this is for adding/removing skills/knacks/backgrounds/advantages
// (Complicated Node-Adding from dropdown menus)
//--------------------------------------------------------------

//the LISTENER
function theAddRmListeners(toDo){
	var button = getClassElements(toDo);
	
	//checking for the listenerArray[array] for the kind of listener
	if(!listenerArray[toDo]){
		var nodeArray=[];
		listenerArray[toDo]=nodeArray;
	}

	for(var i=0;i<button.length;i++){
		var j=0;
		var isPresent=false;
		while(j<listenerArray[toDo].length && !isPresent){
			if(button[i] == listenerArray[toDo][j])
				isPresent=true;
			j++;
		}
		//if not present, add the listener
		if(!isPresent){
			listenerArray[toDo][listenerArray[toDo].length] = button[i];
			if(toDo == "add")
				hookEvent(button[i],'click', add);
			else //if(toDo == "rm")
				hookEvent(button[i],'click', rm);
		}
	}
}

//remove-a-node function -- pretty universal!
function rm(e){
	//find nodes w/ listeners (from listener array) and unhook them
	
	var pretarget = getEventTarget(e).parentNode;
	var target = pretarget.parentNode; 
	if(target.nodeName == "LI") var toRm = target;
	else var toRm = target.parentNode;
	var rmFrom = toRm.parentNode;
	
	if(toRm.nodeName == "LI"){
		
		//knack dependency check
		knackRm(toRm);
		//get the class name in order to re-add the option to the select array from which it came
		addOpt(toRm);
		//finish up and remove the node!
		rmFrom.removeChild(toRm);
	} else {
		alert("Nothing to remove!");
	}
	
	return false;
}

//create a node of appropriate type, append it to proper section. New buttons get Listeners
function add(e){
	//globalFile has a name!
	//theNodes.

	//get the anchor (then the div) that felt the click
	var anchorThing = getEventTarget(e).parentNode;
	var divThing = anchorThing.parentNode;
	
	var selected = findSelected(divThing);
	rmOpt(selected[1].value, selected[1]);
	var thingName = selected[1].value; //the name of the skill/knack/advantage/background to be added
	
	//get the anchor's sibling OL (more specifically, it's className)
	var theOl = divThing.previousSibling;
	while(theOl.nodeType == 3){
		theOl = theOl.previousSibling;
		theOl.parentNode.removeChild(theOl.nextSibling);
	}

	//check class
	if(theOl.className.indexOf("skills") > -1){
		var skillNode = allFile["skill"][thingName];
		if(!skillNode) alert("ERROR -- SKILL NOT FOUND");

		//make the +/- anchor/images, and the open/close
		var anImg = document.createElement("img");
		var neg = document.createElement("a");
		neg.appendChild(anImg);
		//neg.href = "#";
		
		//the small + image
		var pos = neg.cloneNode(1);
		pos.className = "add";
		pos.childNodes[0].src = "images/plus_small.gif";
		pos.childNodes[0].alt = "Add Skill";
		
		//the > image
		var toggle = neg.cloneNode(1);
		toggle.className = "opener";
		toggle.childNodes[0].src = "images/opened.gif";
		toggle.childNodes[0].alt = "Show/Hide Section";
		
		//expanding the - and creating the small - images
		neg.className = "rm";
		neg.childNodes[0].src = "images/minus.gif";
		neg.childNodes[0].alt = "Remove Skill";
		var smallNeg = neg.cloneNode(1);
		smallNeg.childNodes[0].src = "images/minus_small.gif";
		
		//make spinControl nodes
		var numBox = document.createElement("span");
		numBox.className = "spinContainer";
		var textSpin = document.createElement("input");
		textSpin.type = "text";
		textSpin.className = "spinInput";
		textSpin.value = min;
		var upBtn = document.createElement("div");
		upBtn.className = "spinUpBtn";
		var dnBtn = document.createElement("div");
		dnBtn.className = "spinDownBtn";
		numBox.appendChild(textSpin);
		numBox.appendChild(upBtn);
		numBox.appendChild(dnBtn);
		
		//build a skill to append
		var skillLi = document.createElement("li");
		skillLi.id = thingName; //civil-skill-thingName
		
		//all of thingHeader
		var header = document.createElement("div");
		header.className = "thingHeader";
		var aLabel = document.createElement("label");
		aLabel.className = "headLabel";
		aLabel.textContent = thingName;
		header.appendChild(toggle);
		header.appendChild(aLabel.cloneNode(1));
		aLabel.className = "";
		header.appendChild(neg);
		//the thing that isn't visible upon "node close"
		var closer = document.createElement("div");
		closer.className = "thingCloser opened";
		header.appendChild(closer);

		skillLi.appendChild(header);
		
		//the ol with all the knacks in it
		var subList = document.createElement("ol");
		subList.className = "knacks";
		var basicLi = document.createElement("li");
		
		//add all the basic knacks
		var theBasics = skillNode[0];
		for(var i in theBasics){
			basicLi.className = i;
			aLabel.textContent = i;
			basicLi.appendChild(aLabel.cloneNode(1));
			numBox.childNodes[0].name = "Basic-"+selected[0].id+"-"+thingName+"-"+i;
			basicLi.appendChild(numBox.cloneNode(1));
			knackAdd(basicLi); //knack dependency check
			subList.appendChild(basicLi.cloneNode(1));
			basicLi = basicLi.cloneNode(0);
		}
		closer.appendChild(subList);
		
		//add all the advanced knacks (in a separate section, of course)
		var theAdvanced = skillNode[1];
		for(i in theAdvanced){
			if(i){
				var footer = document.createElement("div");
				footer.className = "thingFooter";
				aLabel.textContent = "Advanced Knacks:";
				footer.appendChild(aLabel);
				var selAdv = document.createElement("select");
				selAdv.id = selected[0].id+"-"+thingName;
				var optAdv = document.createElement("option");
				for(var j in theAdvanced){
					selAdv.appendChild(optAdv.cloneNode(1));
					optAdv.value = j;//theAdvanced[i].childNodes[0].textContent;
					optAdv.textContent = j;//theAdvanced[i].childNodes[0].textContent;
				}
				selAdv.appendChild(optAdv);
				footer.appendChild(selAdv);
				footer.appendChild(pos);
				closer.appendChild(footer);
			}
			break;
		}
		
		theOl.appendChild(skillLi);
		
	} else if(theOl.className.indexOf("knacks") > -1){
		var knackNode = allFile["ak"][thingName];
		if(knackNode != 0) alert("ERROR -- KNACK NOT FOUND");
		
		//build an advanced knack to append
		var knackLi = document.createElement("li");
		knackLi.className = thingName;
		
		var aLabel = document.createElement("label");
		aLabel.textContent = thingName;
		var em = document.createElement("em");
		em.appendChild(aLabel);
		knackLi.appendChild(em);

		//make spinControl node
		var numBox = document.createElement("span");
		numBox.className = "spinContainer";
		var textSpin = document.createElement("input");
		textSpin.type = "text";
		textSpin.className = "spinInput";
		textSpin.value = min;
		textSpin.name = "AK-" + selected[0].id + "-" + thingName;
		var upBtn = document.createElement("div");
		upBtn.className = "spinUpBtn";
		var dnBtn = document.createElement("div");
		dnBtn.className = "spinDownBtn";
		numBox.appendChild(textSpin);
		numBox.appendChild(upBtn);
		numBox.appendChild(dnBtn);
		knackLi.appendChild(numBox);

		//make the - anchor/image
		var anImg = document.createElement("img");
		var neg = document.createElement("a");
		neg.appendChild(anImg);
		//neg.href = "#";
		neg.className = "rm";
		neg.childNodes[0].src = "images/minus_small.gif";
		neg.childNodes[0].alt = "Remove Knack";
		
		knackAdd(knackLi); //knack dependency check
		knackLi.appendChild(neg);
		theOl.appendChild(knackLi);
		
	} else if(theOl.className.indexOf("bgs") > -1){
		var bgNode = allFile["bg"][thingName];
		if(!bgNode) alert("ERROR -- BACKGROUND NOT FOUND");

		//make spinControl node
		var numBox = document.createElement("span");
		numBox.className = "spinContainer";
		var textSpin = document.createElement("input");
		textSpin.type = "text";
		textSpin.className = "spinInput";
		textSpin.value = min;
		textSpin.name = "Bg-"+thingName;
		var upBtn = document.createElement("div");
		upBtn.className = "spinUpBtn";
		var dnBtn = document.createElement("div");
		dnBtn.className = "spinDownBtn";
		numBox.appendChild(textSpin);
		numBox.appendChild(upBtn);
		numBox.appendChild(dnBtn);

		//make the - anchor/images, and the open/close
		var anImg = document.createElement("img");
		var neg = document.createElement("a");
		neg.appendChild(anImg);
		
		//the > image
		var toggle = neg.cloneNode(1);
		toggle.className = "opener";
		toggle.childNodes[0].src = "images/opened.gif";
		toggle.childNodes[0].alt = "Show/Hide Section";
		
		//expanding the - image
		neg.className = "rm";
		neg.childNodes[0].src = "images/minus.gif";
		neg.childNodes[0].alt = "Remove Background";
		
		//build a background to append
		var bgLi = document.createElement("li");
		bgLi.id = thingName;
		
		//all of thingHeader
		var header = document.createElement("div");
		header.className = "thingHeader";
		var aLabel = document.createElement("label");
		aLabel.className = "headLabel";
		aLabel.textContent = thingName;
		header.appendChild(toggle);
		header.appendChild(aLabel.cloneNode(1));
		aLabel.className = "";
		header.appendChild(neg);
		//the thing that isn't visible upon "node close"
		var closer = document.createElement("div");
		closer.className = "thingCloser opened";
		header.appendChild(closer);

		bgLi.appendChild(header);
		
		//P for short descrip goes here
		var shortDescrip = document.createElement("p");
		shortDescrip.textContent = bgNode[0];//.childNodes[1].textContent;
		
		//label for cost
		aLabel.textContent = "Background Value: ";
		aLabel.className = "largelabel";
		
		closer.appendChild(shortDescrip);
		closer.appendChild(aLabel);
		closer.appendChild(numBox);
		theOl.appendChild(bgLi);

	} else if(theOl.className.indexOf("advs") > -1){
		var advNode = allFile["adv"][thingName];
		if(!advNode) alert("ERROR -- ADVANTAGE NOT FOUND");

		//make the - anchor/images, and the open/close
		var anImg = document.createElement("img");
		var neg = document.createElement("a");
		neg.appendChild(anImg);
		//neg.href = "#";
		
		//the > image
		var toggle = neg.cloneNode(1);
		toggle.className = "opener";
		toggle.childNodes[0].src = "images/opened.gif";
		toggle.childNodes[0].alt = "Show/Hide Section";
		
		//expanding the - image
		neg.className = "rm";
		neg.childNodes[0].src = "images/minus.gif";
		neg.childNodes[0].alt = "Remove Advantage";
		
		//build an Advantage to append
		var advLi = document.createElement("li");
		advLi.id = thingName;
		
		//all of thingHeader
		var header = document.createElement("div");
		header.className = "thingHeader";
		var aLabel = document.createElement("label");
		aLabel.className = "headLabel";
		aLabel.textContent = thingName;
		var hidden = document.createElement("input");
		hidden.type = 'hidden';
		hidden.name = "Adv-"+thingName;
		header.appendChild(toggle);
		header.appendChild(aLabel.cloneNode(1));
		aLabel.className = "";
		header.appendChild(neg);
		header.appendChild(hidden);
		//the thing that isn't visible upon "node close"
		var closer = document.createElement("div");
		closer.className = "thingCloser opened";
		header.appendChild(closer);

		advLi.appendChild(header);		
		
		//P for short descrip goes here
		var shortDescrip = document.createElement("p");
		shortDescrip.textContent = advNode[0];//.childNodes[1].textContent;
		closer.appendChild(shortDescrip);
		
		//label for cost
		aLabel.textContent = "Advantage Cost: ";//+advNode.childNodes[2].textContent;
		aLabel.className = "largelabel";
 		closer.appendChild(aLabel);
		var costLI = document.createElement("li");
		costLI.textContent = advNode[2];//.childNodes[2].textContent;
		var costUL = document.createElement("ul");
		costUL.appendChild(costLI);
		closer.appendChild(costUL);
		
		
		theOl.appendChild(advLi);
		
	} else alert("shit is real, yo");
	
	//make sure to re-add listeners for all the new button-y things
	theAddRmListeners("add");
	theAddRmListeners("rm");
	theOpenCloseListeners(divThing.parentNode);
	theSpinListeners(divThing.parentNode);
}

//find the SELECT node and the selected OPTION
function findSelected(theParent){
	var selOpt=[];
	
	for(x in theParent.childNodes){
		if(theParent.childNodes[x].nodeName == "SELECT"){
			selOpt[0]=theParent.childNodes[x];
			for(y in selOpt[0].childNodes){
				if(selOpt[0].childNodes[y].selected){
					selOpt[1]=selOpt[0].childNodes[y];
					break;
				}
			}
			break;
		}
	}
	
	return selOpt;
}

//fetch the xml section to insert into the document
function getNodeFor(thingName, bigOlString){

	var i=0;
	var start=0;
	var thingString="";
	
	//find the Beginning!
	var splitThings = bigOlString.split("\n");
	while(start == 0 && i < splitThings.length){
		if(splitThings[i].indexOf(thingName) > -1){
			start=i;
		}
		i++;
	}
	
	//find the End!
	var stop=start;
	var searchIndex = "li id";
	if(splitThings[start].indexOf(searchIndex) <= -1) searchIndex = "li class";
	while(stop==start && i < splitThings.length){
		if(splitThings[i].indexOf(searchIndex) > -1){
			stop=i-1;
		}
		i++;
	}
	//if the End! is not found, make the End!
	if(stop == start) stop = splitThings.length-1;
	
	for(i=start;i<=stop;i++){
		thingString += splitThings[i];
	}
	
	return thingString;
}


//--------------------------------------------------------------
//this is for opening/closing sections/skills of the form
//--------------------------------------------------------------

//the LISTENER
function theOpenCloseListeners(theNode){
	if(!theNode) theNode = document;
	
	var aNode = getClassElements("opener", theNode);
	if(aNode.length >0)
		for(i in aNode)
			if(aNode[i].className.indexOf("opener")>-1)
				hookEvent(aNode[i], 'click', openclose);
}

//opens/closes the "subnodes" of the open/close trigger
function openclose(e){
	var anImg = getEventTarget(e);
	var anAnchor = anImg.parentNode; //this should be an anchor!
	var theNode = anAnchor.parentNode; //this should be a div! but is it "section" or "thingHeader"?
	var closerClass;
	if(theNode.className.indexOf("thingHeader") > -1) closerClass = "thingCloser";
	else if(theNode.className.indexOf("section") > -1) closerClass = "sectCloser";
	else {
		alert("Problem: div has wrong class!");
		return false;
	}
	
	var newClass = "opened";
	var oldClass = "closed";
	var closeNodes = getClassElements(closerClass, theNode);
	if(closeNodes[0].className.indexOf("opened")>-1){
		newClass = "closed";
		oldClass = "opened";
	} else if(closeNodes[0].className.indexOf("closed")<=-1)
		alert("you ain't got no class, dawg");

	for(var i in closeNodes){
		closeNodes[i].className = replaceClass(closeNodes[i], oldClass, newClass);
	}
	
	//change the img!
	anImg.src = "images/"+newClass+".gif";
	
	//test if this is the first section (special case)
	var sect1 = document.getElementById("section1");
	if((closeNodes[0].parentNode).parentNode == sect1){
		if(newClass == "opened"){
			var oldHeight = "";
			var newHeight = "firstheight";
		} else {
			var oldHeight = "firstheight";
			var newHeight = "";
		}

		for(y in closeNodes){
			closeNodes[y].parentNode.className = replaceClass(closeNodes[y].parentNode, oldHeight, newHeight);
		}
	}
}

//this is for hiding/showing OPTIONs within the SELECT menu
function addOpt(theNode){//the LI being removed
	if(!theNode) return false;
	
	var optName = theNode.className;
	if(optName.length <=0) optName = theNode.id;
	if(optName.length <=0) return false;
	
	//find the select node where the option was hidden
	var theOl = theNode.parentNode;
	var theDiv = theOl.nextSibling;
	//sometimes there's weird TextNode objects for no reason...
	while(theDiv.nodeType == 3){
		theDiv = theDiv.nextSibling;
		theDiv.parentNode.removeChild(theDiv.previousSibling);
	}
	var theSel = theDiv.getElementsByTagName("select");
	theSel = getClassElements("hide", theSel[0]);
	for(x in theSel){
		theSel[x].className = replaceClass(theSel[x], "hide"); //unhide!
		theSel[x].selected = false; //unselect!
	}
}

function rmOpt(theName, theNode){ //name -> to Rm, theNode -> select to rm from
	if(!theName || !theNode) return false;
	
	if(theNode.nodeName == "OPTION") {
		theNode.className = replaceClass(theNode, "", "hide");
		theNode.selected = false;
	} else {
		var i=0;
		var hidden = false;
		var theChild;
		while(i<theNode[0].length && !hidden){
			theChild = theNode[0].childNodes[i];
			if(theChild.value == theName){
				theChild.className = replaceClass(theChild, "", "hide"); //hide!
				theChild.selected = false; //unselect!
				hidden = true;
			}
			i++;
		}
	}
}


//--------------------------------------------------------------
//this is for dealing with spin control
//--------------------------------------------------------------

//prep the FORM for using spin control boxes
//replace the list (OL) of CHECKBOXes with a SELECT dropdown
function initReplace(){
	var theMulti = getClassElements("multi");
	var theInput;
	var newSel;
	var newText;
	var blankOpt;
	var newOpt;
	var newLink;
	var newImg;
	for(var i=0;i<theMulti.length;i++){
		//make a SELECT node to replace the list
		newSel = document.createElement("select");
		newSel.id = theMulti[i].id;
		newSel.setAttribute("name" , theMulti[i].getAttribute("name"));
		newSel.className = replaceClass(theMulti[i], "multi");
		blankOpt = document.createElement("option");
		newSel.appendChild(blankOpt);
		
		//make an OPTION node for every CHECKBOX node
		theInput = theMulti[i].getElementsByTagName("input");
		for(var j=0;j<theInput.length;j++){
			newOpt = document.createElement("option");
			newOpt.value = theInput[j].name;
			newText = document.createTextNode(newOpt.value);
			newOpt.appendChild(newText);
			newSel.appendChild(newOpt);
		}
		theMulti[i].parentNode.replaceChild(newSel, theMulti[i]);
		
		newLink = document.createElement("a");
		newLink.className = "add";
		newImg = document.createElement("img");
		newImg.src = "images/plus.gif";
		newImg.alt = "Add "+theMulti[i].id;
		newLink.appendChild(newImg);
		newSel.parentNode.appendChild(newLink);
	}
}

//the LISTENER
function theSpinListeners(theNode){
	if(!theNode) theNode=false;
	if(!listenerArray["spinContainer"]){
		var nodeArray=[];
		listenerArray["spinContainer"]=nodeArray;
	}
	
	var listener = listenerArray["spinContainer"];
	var isThere = false;
	
	//get all elements of class spinBox from either the fieldset or the document
	var aDiv = getClassElements("spinContainer", theNode);
	var input;
	var button;
	for(x in aDiv){
		//go through each div and find their Stuff
		input = aDiv[x].getElementsByTagName("input");
		button = aDiv[x].getElementsByTagName("div");
		
		//for events within the text box
		for(y in input){
			if(input[y].type != "HIDDEN"){
				for(z in listener){
					if(listener[z] == input[y]) isThere = true;
				}
				
				if(!isThere){
					hookEvent(input[y],'change', spinBox);
					hookEvent(input[y],'focus', spinBox);
					hookEvent(input[y],'blur', spinBox);
					
					listener[listener.length] = input[y];
				}
				isThere = false;
			}
		}
		
		//for users clicking up/down buttons
		for(y in button){
			for(z in listener){
				if(listener[z] == button[y]) isThere = true;
			}
			
			if(!isThere){
				hookEvent(button[y],'mousedown', spinBox);
				hookEvent(button[y],'mouseup', spinBox);
				hookEvent(button[y],'mouseover', spinBox);
				listener[listener.length] = button[y];
			}
			isThere = false;
		}
	}
}

//deal with the class: spinContainer when it is clicked
function spinBox(e){
	var target = getEventTarget(e); //target should be a div or input within spinContainer
	var spinContainer = target.parentNode;
	var action = e.type;
	var key = e.keyCode;
	var upDn = -1;
	
	if(target.nodeName == "INPUT"){
		//do stuff with the arrow buttons
		switch(action) {
			case 'change':
				var val = parseFloat(target.value);
				if(isNaN(val))
					val = min;
				else {
					target.value = UpdateCurrentValue(val);
				}
				break;
			case 'keydown':
				var btn = target.nextSibling;
				if(key == 38){ //up arrow
					upDn = 1;
					if(btn.className.indexOf("UpBtn") >-1) btn.className = "spinUpBtnPress";
					else ("All your upBase!");
				} else if(key == 40){ //down arrow
					upDn = -1;
					btn = btn.nextSibling;
					if(btn.className.indexOf("DownBtn") >-1) btn.className = "spinDownBtnPress";
					else ("Are Belong Down!");
				} else break;
				focused = target;
				StartRunning(upDn);
				break;
			case 'keyup':
				//hover
				var btn = target.nextSibling;
				if(key == 38){ //up arrow
					if(btn.className.indexOf("UpBtn") >-1) btn.className = "spinUpBtn";
					else ("UpBtn is Alarmed!");
				} else if(key == 40){ //down arrow
					btn = btn.nextSibling;
					if(btn.className.indexOf("DownBtn") >-1) btn.className = "spinDownBtn";
					else ("DownBtn is Down!");
				} else alert("What you must realize is there is no Btn");
				
				if(!bodyEventHooked) hookEvent(document.body, 'mouseover', ClearBtns);
				CancelRunning();
				break;
			case 'focus':
				focused = target;
				hookEvent(window, 'DOMMouseScroll', MouseWheel);
				hookEvent(document, 'mousewheel', MouseWheel);
				hookEvent(target,'keydown', spinBox);
				hookEvent(target,'keyup', spinBox);
				break;
			case 'blur':
				unhookEvent(window, 'DOMMouseScroll', MouseWheel);
				unhookEvent(document, 'mousewheel', MouseWheel);
				unhookEvent(target,'keydown', spinBox);
				unhookEvent(target,'keyup', spinBox);
				break;
			default:
				alert("These are not the actions you are looking for...");
		}
	} else if(target.nodeName == "DIV"){
		if(target.className.indexOf("UpBtn") >-1) upDn = 1;
		switch(action){
			case 'keydown':
				if(key == 38) //up arrow
					upDn = 1;
				else if(key == 40) //down arrow
					upDn = -1;
				else break;
			case 'mousedown':
				//press
				if(upDn == 1)
					target.className = "spinUpBtnPress";
				else if(upDn == -1)
					target.className = "spinDownBtnPress";
				var text = target.previousSibling;
				while(text && text.nodeName != "INPUT"){
					text = text.previousSibling;
				}
				focused = text;
				StartRunning(upDn);
				text.focus();
				break;
			case 'keyup':
			case 'mouseup':
			case 'mouseover':
				//hover
				if(upDn == 1) target.className = "spinUpBtn";
				else target.className = "spinDownBtn";
				if(!bodyEventHooked) hookEvent(document.body, 'mouseover', ClearBtns);
				CancelRunning();
				break;
			default:
				alert("Your princess is in another bottle");
		}
	}
	return cancelEvent(e);
}


function MouseWheel(e){
	e = e ? e : window.event;
	var movement = e.detail ? e.detail / -3 : e.wheelDelta/120;
	
	if(focused){
		var val = parseFloat(focused.value);
		if(isNaN(val)) val = min;
		UpdateCurrentValue(val + incr * movement);
	}
	return cancelEvent(e);
}

function ClearBtns(e){
	var target = getEventTarget(e);
	if(target.className.indexOf("UpBtn") >-1 || target.className.indexOf("DownBtn") >-1) return;
	CancelRunning();
	
	if(bodyEventHooked){
		unhookEvent(document.body, 'mouseover', ClearBtns);
		bodyEventHooked = false;
	}
	return cancelEvent(e);
}

function UpdateCurrentValue(newVal){
	if(newVal < min) newVal = min;
	if(newVal > max) newVal = max;
	
	newVal = Math.round(1000*newVal)/1000;
	
	if(focused){
		var isAKnack = knackSpin(newVal);
		if(!isAKnack)
			focused.value = newVal;
	} else alert("focused is not a real node!");
}

function Run(){
	if(running == 0) return;
	
	var inc = incr;
	
	DoChange(inc);
}

function CancelRunning(){
	running = 0;
	if(interval != -1){
		clearInterval(interval);
		interval = -1;
	}
}

function DoChange(inc){
	var val = parseFloat(focused.value);
	if(isNaN(val)) val = min;
	var newVal = val + inc * running;
	UpdateCurrentValue(newVal);
}

function StartRunning(newState){
	if(running != 0) CancelRunning();
	
	running = newState;
	
	DoChange(incr);
	
	interval = setInterval(Run, 150);
}


/*
// creates a new SpinControl object and defines its methods
function SpinControl(aName){
	/*
	* Because IE 6 and lower don't support the transparent png background 
	* mask that we use for the buttons.
	* So we use a regular old gif instead.
	* This means that, sadly, the button coloring does not work in IE6 and lower.
	*/
	
	/*
	if(document.body.filters){
		var arVersion = navigator.appVersion.split("MSIE");
		var version = parseFloat(arVersion[1]);
		if(version < 7){
		_downButton.style.backgroundImage = 'url(images/spin_control_buttons.gif)';
		_upButton.style.backgroundImage = 'url(images/spin_control_buttons.gif)';
		}
	}
	
}*/

