//----------------------------------------------
// set of general functions for handling the dom
function dom(){};


// Copyright Thor Larholm
dom.domLoad = function(handler,obj){
	var me = arguments.callee, obj = obj || window;
	var hnds = me.handlers || (me.handlers = []);

	hnds[hnds.length] = {el:obj,fnc:handler};
	if(me.inserted) return;
	me.inserted = true;

	me.kick = function(E){
		if(me.kickcalled) return;
		me.kickcalled = true;
		for(var i=0, il=hnds.length; i<il; i++) hnds[i].fnc.call(hnds[i].el,E);
	}

	/*@cc_on @*/
	/*@if (@_win32)
	document.write("<script id=__ie_onload defer src=javascript:void(0)></script>");
	var script = document.getElementById("__ie_onload");
	script.onreadystatechange = function(ev){ if(this.readyState=='complete') me.kick(ev); };
	/*@end @*/

	if(document.addEventListener) document.addEventListener("DOMContentLoaded", me.kick, false);

	if(typeof document.readyState=="string") setInterval(function(ev){if(/complete|loaded/.test(document.readyState)) me.kick(ev);},10);
	
	var oldLoad = window.onload;
	window.onload = function(ev){
		me.kick(ev);
		if(typeof oldLoad=="function") oldLoad.call(window,ev);
	}
};

// find the number of columns in a table row, based on colspans
dom.colCount = function(trObj){
	var tr = $(trObj);
	var colCount = 0;
	if (tr && tr.cells && tr.cells.length){
		for (var i=0;i<tr.cells.length;i++){
			if (tr.cells[i].colSpan){
				colCount += tr.cells[i].colSpan;
			}else{
				colCount++;
			}
		}
		return colCount;
	}
	return null;
};


dom.showModalDialog = function(appendObjorID,s){	
	var settings = s?s:{};
	dom.removeObject("modalDialogOverlay");
	dom.removeObject("modalDialogOverlayContent");	
	dom.addNode("",document.body,"div",{id:"modalDialogOverlay"},{display:"none"});
	dom.addNode("",document.body,"div",{id:"modalDialogContentHolder"},{display:"none"});
	dom.addNode("","modalDialogContentHolder","div",{id:"modalDialogContent"},{});
	if (settings.title){
		var modalHeader = dom.addNode(settings.title,"modalDialogContent","div",{id:"innerModalHeader",className:"modalHeader"},{});
	}
	dom.addNode("","modalDialogContent","div",{id:"innerModalContent"},{padding:"15px"});
	
	fadeCSS.setOpacity("modalDialogOverlay",0);
	fadeCSS.setOpacity("modalDialogContentHolder",0);
	
	dom.moveModal(15,false,true,true); // set up modal behavior
	
	dom.toggle("modalDialogContentHolder",true);
	dom.toggle("modalDialogOverlay",true);
	

	//set the content
	var newClone = $(appendObjorID).cloneNode(true);
	dom.toggle(newClone,true);
	$("innerModalContent").appendChild(newClone);
	
	//add controls
	dom.addNode("","modalDialogContent","div",{id:"modalDialogButtons",className:"modalButtonControl"},{});
	dom.addNode("","modalDialogButtons","input",{id:"modalDialogCloseBtn",type:"button",value:"Close"},{});
	addEvent("modalDialogCloseBtn","click",function(){dom.killModalDialog()});
	
	var selectAry = document.body.getElementsByTagName("select");
	for (var i=0;i<selectAry.length;i++){
		var s = selectAry[i];
		if ((s.style && s.style.display && s.style.display == "") || (!s.style.display) || (!s.style)){
			dom.toggle(s,false);
			s.modalToggle = true;
		}
	}
	fadeCSS.ease(null,0,93,.12,"easeInExponential",fadeCSS.setOpacity,["modalDialogOverlay"]);
	fadeCSS.ease(null,0,110,.12,"easeInExponential",fadeCSS.setOpacity,["modalDialogContentHolder"]);
	dom.modalDisplayStatus = true;
}

dom.moveModal = function(offSet,scrollContent,scrollBG,initSetup){
	var offSet = offSet?offSet:10;
	if (initSetup){
		addEvent(window,"scroll",function(){dom.moveModal(offSet,scrollContent,scrollBG)});
		addEvent(window,"resize",function(){dom.moveModal(offSet,scrollContent,scrollBG)});
	}
	if (scrollContent || initSetup){
		if ($("modalDialogContentHolder")){
			$("modalDialogContentHolder").style.top = (document.documentElement.scrollTop + offSet) + "px";
		}
	}
	if (scrollBG || initSetup){
		if ($("modalDialogOverlay")){
			$("modalDialogOverlay").style.top = (document.documentElement.scrollTop) + "px";
			$("modalDialogOverlay").style.width = (window.innerWidth || document.body.offsetWidth) + "px";
			$("modalDialogOverlay").style.height = (window.innerHeight || document.body.offsetHeight) + "px";
		}
		
	}
}


dom.killModalDialog = function(){
	if (dom.modalDisplayStatus == true){
		dom.removeObject("modalDialogContent");
		fadeCSS.ease(null,93,0,.2,"easeOutExponential",fadeCSS.setOpacity,["modalDialogOverlay"],function(){
																																															dom.removeObject("modalDialogOverlay");
																																															dom.removeObject("modalDialogContentHolder");
		});
		
		var selectAry = document.body.getElementsByTagName("select");			
		for (var i=0;i<selectAry.length;i++){
			var s = selectAry[i];
			if (s.modalToggle){
				dom.toggle(s,true);
				s.modalToggle = false;
			}
		}
		dom.modalDisplayStatus = false;
	}
}


dom.setFormValue = function(f,elName,v,forceBoolean){
	//console.info("dom.setFormValue(",f,elName,v,forceBoolean);
	var el = null; //$(f)?($(f)[elName]):$(elName);
	if (document.forms[f] && document.forms[f][elName]){
		el = document.forms[f][elName];
		//console.info('----------------   ',elName,'   --------------');
		//for (var p in el){
		//	console.info(p,':',el[p]);
		//}
		//console.info('matched [form][element]: ',f,elName,v);
	}else if ($(f) && $(f).tagName == 'FORM' && $(f)[elName]){
		el = $(f)[elName];
		//console.info('matched $(form)[element]: ',f,elName,v);
	}else if ($(elName)){
		el = $(elName);
		//console.info('matched $(element): ',f,elName,v);
	}else{
		console.info('dom.setFormValue failed for: ',f,elName,v);
		return false;
	}
	if (typeof el!='undefined'){
		//dom.alert("<br>Setting " + f + "." + elName + " = " + v);
		var isRadio = false;
		if (el.length){				//handle radio buttons
			
			if(!el.type && el[0] && el[0].type.indexOf("radio") > -1){
				for (var i=0;i<el.length;i++){
					isRadio = true;
					var radioEl = el[i];
					if (forceBoolean){
						var compBoolean = v.toLowerCase();
						if (radioEl.value.toLowerCase()=="true" || radioEl.value.toLowerCase()=="yes" || radioEl.value=="1"){ 
							var thisBoolean = "true"; 
						}else{
							var thisBoolean = radioEl.value.toLowerCase();
						}
						if (thisBoolean == compBoolean) {
							radioEl.checked = true;
						}else{
							radioEl.checked = false;
						}
					}else{
						if (radioEl.value == v){
							radioEl.checked = true;
						}else{
							radioEl.checked = false;
						}
					}
				}
			}
			
		}
		if (!isRadio){
			//console.info('-- made it --',f,elName,v,el.type);
			if (el.type && el.type.indexOf("select") > -1){
				for (var i=0; i<el.options.length;i++){
					if (el.options[i].value == v){
						el.options.selectedIndex = i;
					}
				}
				//dom.alert(el.options[el.options.selectedIndex].value);
				//el.options[el.options.selectedIndex].value = v;
				//dom.alert(""select: "" + el.name + "" value: "" + v);
				
			}else if (el.type && el.type.indexOf("text") > -1 || el.type.indexOf("hidden") > -1 || el.type.indexOf("textarea") > -1 ){
				el.value = v;
				//alert (el + "":"" + el.value);
			}else if (el.type.indexOf("checkbox") > -1){ // handle check boxes?
				//dom.alert(el.name + "": "" + el.type + ""="" + el.value + "" / v="" + v);
				if (((v.toLowerCase() == "true" && el.value.toLowerCase() == "true") || (v.toLowerCase() == "false" && el.value.toLowerCase() == "false")) || el.value == v){
					el.checked = true;
				}else{
					el.checked = false;
				}
			}
		}
	}
};
	

dom.createMonthSelect = function(parentObj,elementID){
	if($(parentObj)){
		var monthObj = {'Month':'','Jan - 01':'01','Feb - 02':'02','Mar - 03':'03','Apr - 04':'04','May - 05':'05','Jun - 06':'06','Jul - 07':'07','Aug - 08':'08','Sep - 09':'09','Oct - 10':'10','Nov - 11':'11','Dec - 12':'12'};
		dom.addFormData(parentObj,elementID,null,"select",false,null,null,monthObj);
	}
};
	
dom.createStateSelect = function(parentObj,elementID,firstLine,abbreviateAll,groupCountries){
	if($(parentObj)){
		var stateSelect = dom.addNode(null,parentObj,"select",{id:(elementID)?elementID:null},{});
		var spl = dom.stateProvinceList;
		
		if (firstLine){ dom.addNode(firstLine,stateSelect,"option",{},{}); }
		for (var ii=0;ii<spl.length;ii++){
			var curSt = spl[ii];
			var curOptGroup = null;
			if (groupCountries){
				if (!$(elementID + "_" + curSt.country + "_optGroup")){
					curOptGroup = dom.addNode(null,stateSelect,"optgroup",{id:elementID + "_" + curSt.country + "_optGroup",label:curSt.countryName},{});
				}else{
					curOptGroup = $(elementID + "_" + curSt.country + "_optGroup")
				}
			}
			
			var stateParent = (groupCountries)?curOptGroup:stateSelect;
			
			dom.addNode((abbreviateAll?curSt.abbreviation:curSt.name),stateParent,"option",{value:curSt.abbreviation},{});
		}
		
	}else{
		return null;	
	}
};

dom.stateProvinceList = [{abbreviation:"AL",name:"Alabama",country:"US",countryName:"United States"},
	{abbreviation:"AK",name:"Alaska",country:"US",countryName:"United States"},
    {abbreviation:"AZ",name:"Arizona",country:"US",countryName:"United States"},
    {abbreviation:"AR",name:"Arkansas",country:"US",countryName:"United States"},
    {abbreviation:"CA",name:"California",country:"US",countryName:"United States"},
    {abbreviation:"CO",name:"Colorado",country:"US",countryName:"United States"},
    {abbreviation:"CT",name:"Connecticut",country:"US",countryName:"United States"},
    {abbreviation:"DE",name:"Delaware",country:"US",countryName:"United States"},
   	{abbreviation:"FL",name:"Florida",country:"US",countryName:"United States"},
    {abbreviation:"GA",name:"Georgia",country:"US",countryName:"United States"},
    {abbreviation:"HI",name:"Hawaii",country:"US",countryName:"United States"},
    {abbreviation:"ID",name:"Idaho",country:"US",countryName:"United States"},
    {abbreviation:"IL",name:"Illinois",country:"US",countryName:"United States"},
    {abbreviation:"IN",name:"Indiana",country:"US",countryName:"United States"},
    {abbreviation:"IA",name:"Iowa",country:"US",countryName:"United States"},
    {abbreviation:"KS",name:"Kansas",country:"US",countryName:"United States"},
    {abbreviation:"KY",name:"Kentucky",country:"US",countryName:"United States"},
    {abbreviation:"LA",name:"Louisiana",country:"US",countryName:"United States"},
    {abbreviation:"ME",name:"Maine",country:"US",countryName:"United States"},
    {abbreviation:"MD",name:"Maryland",country:"US",countryName:"United States"},
    {abbreviation:"MA",name:"Massachusetts",country:"US",countryName:"United States"},
    {abbreviation:"MI",name:"Michigan",country:"US",countryName:"United States"},
    {abbreviation:"MN",name:"Minnesota",country:"US",countryName:"United States"},
    {abbreviation:"MS",name:"Mississippi",country:"US",countryName:"United States"},
    {abbreviation:"MO",name:"Missouri",country:"US",countryName:"United States"},
    {abbreviation:"MT",name:"Montana",country:"US",countryName:"United States"},
    {abbreviation:"NE",name:"Nebraska",country:"US",countryName:"United States"},
    {abbreviation:"NV",name:"Nevada",country:"US",countryName:"United States"},
    {abbreviation:"NH",name:"New Hampshire",country:"US",countryName:"United States"},
    {abbreviation:"NJ",name:"New Jersey",country:"US",countryName:"United States"},
    {abbreviation:"NM",name:"New Mexico",country:"US",countryName:"United States"},
    {abbreviation:"NY",name:"New York",country:"US",countryName:"United States"},
    {abbreviation:"NC",name:"North Carolina",country:"US",countryName:"United States"},
    {abbreviation:"ND",name:"North Dakota",country:"US",countryName:"United States"},
    {abbreviation:"OH",name:"Ohio",country:"US",countryName:"United States"},
    {abbreviation:"OK",name:"Oklahoma",country:"US",countryName:"United States"},
    {abbreviation:"OR",name:"Oregon",country:"US",countryName:"United States"},
    {abbreviation:"PA",name:"Pennsylvania",country:"US",countryName:"United States"},
    {abbreviation:"RI",name:"Rhode Island",country:"US",countryName:"United States"},
    {abbreviation:"SC",name:"South Carolina",country:"US",countryName:"United States"},
    {abbreviation:"SD",name:"South Dakota",country:"US",countryName:"United States"},
    {abbreviation:"TN",name:"Tennessee",country:"US",countryName:"United States"},
    {abbreviation:"TX",name:"Texas",country:"US",countryName:"United States"},
    {abbreviation:"UT",name:"Utah",country:"US",countryName:"United States"},
    {abbreviation:"VT",name:"Vermont",country:"US",countryName:"United States"},
    {abbreviation:"VA",name:"Virginia",country:"US",countryName:"United States"},
    {abbreviation:"WA",name:"Washington",country:"US",countryName:"United States"},
    {abbreviation:"DC",name:"Washington D.C.",country:"US",countryName:"United States"},
    {abbreviation:"WV",name:"West Virginia",country:"US",countryName:"United States"},
    {abbreviation:"WI",name:"Wisconsin",country:"US",countryName:"United States"},
    {abbreviation:"WY",name:"Wyoming",country:"US",countryName:"United States"},

	{abbreviation:"AB",name:"Alberta",country:"CA",countryName:"Canada"},
	{abbreviation:"BC",name:"British Columbia",country:"CA",countryName:"Canada"},
	{abbreviation:"MB",name:"Manitoba",country:"CA",countryName:"Canada"},
	{abbreviation:"NB",name:"New Brunswick",country:"CA",countryName:"Canada"},
	{abbreviation:"NL",name:"Newf. & Labrador",country:"CA",countryName:"Canada"},
	{abbreviation:"NT",name:"NW Territories",country:"CA",countryName:"Canada"},
	{abbreviation:"NS",name:"Nova Scotia",country:"CA",countryName:"Canada"},
	{abbreviation:"NU",name:"Nunavut",country:"CA",countryName:"Canada"},
	{abbreviation:"ON",name:"Ontario",country:"CA",countryName:"Canada"},
	{abbreviation:"PE",name:"Prince E. Island",country:"CA",countryName:"Canada"},
	{abbreviation:"QC",name:"Quebec",country:"CA",countryName:"Canada"},
	{abbreviation:"SK",name:"Saskatchewan",country:"CA",countryName:"Canada"},
	{abbreviation:"YT",name:"Yukon",country:"CA",countryName:"Canada"}];




dom.addForm = function(fName,fAction,fMethod,noAppend,parentObj){
	if ($(fName)){dom.removeObject(fName);}
	var newForm = document.createElement('form');
	newForm.name = fName;
	newForm.id = fName;
	newForm.action = fAction?fAction:null;
	newForm.method = fMethod?fMethod:"POST"; 

	if (!noAppend){
		//var newDiv = document.createElement('div');
		//newDiv.appendChild(newForm);
		if (parentObj){
			$(parentObj).appendChild(newForm);
		}else{
			document.body.appendChild(newForm);
		}
	}
	return newForm;
};

dom.setFieldFormat = function(fieldObjorID,filterObj){	
	var f = $(fieldObjorID);
	var flt = filterObj?filterObj:{};

	if (!flt.nomark){
		var fieldMark = document.createElement("span");
		fieldMark.style.color = "red";
		fieldMark.style.fontSize = "14px";
		fieldMark.style.paddingLeft = "4px";
		//fieldMark.style.fontStyle = "bold";
		fieldMark.innerHTML = "*";
		f.parentNode.insertBefore(fieldMark,f.nextSibling);
	}
	if (flt.label){
		f.label = flt.label;
	}
	var propKeywordAry = ["keyup","final","change"];
	for (var i=0;i<propKeywordAry.length;i++){
		//console.info(typeof flt[propKeywordAry[i]]);
		if (typeof flt[propKeywordAry[i]] == "string"){
			//console.info("ding!" + propKeywordAry[i]);
			switch(flt[propKeywordAry[i]]){
				case "notempty":
					flt[propKeywordAry[i]] = /^.+$/;
					flt.cleanfilter =  /^[\d]*$/;
					break;
				case "numeric":
					flt[propKeywordAry[i]] = /^[\d]*$/;
					flt.cleanfilter =  /^[\d]*$/;
					break;
				case "alphanumeric":
					flt[propKeywordAry[i]] = /^[\w \/\.]*$/;
					flt.cleanfilter =  /^[\w \/\.]$/;
					break;
				case "alphanumericnospace":
					flt[propKeywordAry[i]] = /^[\w]*$/;
					flt.cleanfilter =  /^[\w]$/;
					break;
				case "alphanumericdash":
					flt[propKeywordAry[i]] = /^[\w\-]*$/;
					flt.cleanfilter =  /^[\w\-]$/;
					break;
				case "zippostalcode":
					flt[propKeywordAry[i]] = /^(\d{5}(( |-)\d{4})?)|([A-Za-z]\d[A-Za-z]( |-)\d[A-Za-z]\d)$/;
					break;
				case "email":
					flt[propKeywordAry[i]] = /^\w+[\w\-\.]+\w+@\w+.+\..{2,3}$/;
					flt.cleanfilter =  /^[\w\-\.\@]$/;
					break;					
				case "date": // mm/dd/yyyy format
					//flt[propKeywordAry[i]] = /^\d{1,2}(\/)\d{1,2}\1\d{4}$/;
					flt[propKeywordAry[i]] = function(fff,obj){return isDate(obj.value);};
					break;
				case "datetime": // mm/dd/yyyy hh:mm:ss format
					flt[propKeywordAry[i]] = /^\d{1,2}(\/)\d{1,2}\1\d{4} \d{1,2}(:)\d{1,2}(:)\d{4}  $/;
					break;							
				case "afternow":	//date comparison - kludgy
					flt[propKeywordAry[i]] = function(fff){ return( smallDate(fff.dateval(),true) > now()); };
					//console.info(flt[propKeywordAry[i]]);
					break;					
				case "beforenow": //date comparison - kludgy
					flt[propKeywordAry[i]] = function(fff){ return( smallDate(fff.dateval(),true) < now()); };
					break;
				case "creditcard": //needs a .cctype field passed
					flt.cleanfilter =  /^[\d]$/;
					flt[propKeywordAry[i]] = function(fff){
									//var fff = (e.srcElement || e.target).fieldFormatFilter;
								 	if (fff.cctype && fff.cctype.type && fff.cctype.type.indexOf("select") > -1){
								 		var cctype = fff.cctype.value;
								 	}else if (flt.cctype && typeof flt.cctype == "string"){
								 		var cctype = fff.cctype;
								 	}
								 	if (cctype){
										switch(cctype.toLowerCase()) {
											case "amex":
												return /^3[47]{1}[0-9]{13}$/;
												break;
											case "visa":
												return /^4[0-9]{15}$/;
												break;
											case "mc":
												return /^5[1-5]{1}[0-9]{14}$/;
												break;
											case "disc":
												return /^6011[0-9]{12}$/;
												break;
											default:
												return /^[0-9]{15,16}$/;
										}								 		
								 	}else{
								 		flt[propKeywordAry[i]] = /^[a-z]{1000}$/; //a ridiculous hack of an unachievable criteria
								 	}
							}
				 	break;				
				case "cvv2": //needs a .cctype field passed
					flt.cleanfilter =  /^[\d]*$/;
					flt[propKeywordAry[i]] = function(fff){
									//var fff = (e.srcElement || e.target).fieldFormatFilter;
								 	if (fff.cctype && fff.cctype.type && fff.cctype.type.indexOf("select") > -1){
								 		var cctype = fff.cctype.value;
								 	}else if (flt.cctype && typeof flt.cctype == "string"){
								 		var cctype = fff.cctype;
								 	}
								 	if (cctype){
										switch(cctype.toLowerCase()) {
											case "amex":
												return /^[0-9]{4}$/;
												break;
											case "visa": case "mc": case "disc":
												return /^[0-9]{3}$/;
												break;
											default:
												return false;
										}								 		
								 	}else{
								 		flt[propKeywordAry[i]] = /^[a-z]{1000}$/;
								 	}
							}
				 	break;
				 	
			}
		}
	}
		
	//console.info("setFieldFormat(" + f.name + ")" + typeof flt.final);
	if (f){
		f.fieldFormatFilter = flt;
		if (flt.forcelength||flt.minlength||flt.maxlength){
			var lengthtest = "";
			if (flt.minlength){ lengthtest = flt.minlength + ","; }
			if (flt.maxlength){ lengthtest += flt.maxlength; }
			if (flt.forcelength){ lengthtest = flt.forcelength; }
			
			f.fieldFormatFilter.lengthtest = new RegExp("^[\\s\\S]{" + lengthtest + "}$"); 
			//flt.final = /^[.\n]{}$/;
		}

		f.fieldOriginalStyle = {};
		f.fieldOriginalStyle = f.style;
		f.fieldCompareFunction = function(re,extCall){
													if (re){
														//console.info("before: ", this.name + ".fieldCompareFunction(" + re + ") - re.constructor:" + re.constructor);														
														if (re.constructor == Function){ re = re(this.fieldFormatFilter,this); }
														var fm = true; //default to true for a fieldmatch
														if (this.fieldFormatFilter.fieldmatch){
																if (this.fieldFormatFilter.fieldmatch.value != this.value){ 
																	fm = false;
																}	
																if (!extCall){
																	dom.checkFieldFormat(this.fieldFormatFilter.fieldmatch,true);
																}																	
														}
														
														
														if (this.fieldFormatFilter.retest){
															if (!extCall){																		
																//if (this.fieldFormatFilter.retest.constructor == Array){																			
																//	for (var i=0;i<this.fieldFormatFilter.retest.length;i++){
																//		dom.checkFieldFormat(this.fieldFormatFilter.retest[i],true);
																//	}
																//}else{
																//	console.info("calling a single value");
																	dom.checkFieldFormat(this.fieldFormatFilter.retest,true);
																//}
															}		
														}
														
														//perform cleaning if specified with clean:true and a cleanfilter regex provided
														//console.info(this.id + " :: " + this.fieldFormatFilter.cleanfilter.test(this.value));
														if (this.type == "text" && this.fieldFormatFilter.clean
																		&& this.fieldFormatFilter.cleanfilter
																		&& !this.fieldFormatFilter.cleanfilter.test(this.value)){																		
															//console.info("test: " + this.value + " with: " + this.fieldFormatFilter.cleanfilter);
															var cleaned = "";
															for (var i=0;i<this.value.length;i++){
																if(this.fieldFormatFilter.cleanfilter.test(this.value.charAt(i))){
																	cleaned += this.value.charAt(i);
																}
															}
															this.value = cleaned;
														}
														
														
														//perform the testing
														if (re){
															if (re.constructor == RegExp){
																
																if (re.test(this.value) && fm){
																	this.isFormFieldValid = true;												
																}else{
																	this.isFormFieldValid = false;											
																}
															}else if(re.constructor == Boolean){
																this.isFormFieldValid = re;
															}
														}else{
															this.isFormFieldValid = false;
														}
																														
														//handle displaying text indicators for success
														dom.removeObject(this.fieldFormatStatusMsg);
														if (this.fieldFormatFilter.writestatus){
															this.fieldFormatStatusMsg = dom.addNode("",document.body,"div",{},{display:"none",position:"absolute",left:0,top:0});													
															var pos = dom.findXYWH(this);
															this.fieldFormatStatusMsg.style.left = parseInt(pos.x + pos.w + 5) + "px";
															this.fieldFormatStatusMsg.style.top = pos.y + "px";
															if (this.isFormFieldValid){ 
																if (!this.fieldFormatFilter.onlyshowerror){																	
																	this.fieldFormatStatusMsg.style.color = "green";
																	this.fieldFormatStatusMsg.innerHTML = "correct";
																	dom.toggle(this.fieldFormatStatusMsg,true);
																}else{
																	dom.toggle(this.fieldFormatStatusMsg,false);
																}
															}else{
																this.fieldFormatStatusMsg.style.color = "red";
																this.fieldFormatStatusMsg.innerHTML = "error";													
																dom.toggle(this.fieldFormatStatusMsg,true);
															}
														}								
														
														//display color indicators for success
														if(!this.fieldFormatFilter.nohighlight){
															if (this.isFormFieldValid){ 
																if (this.fieldFormatFilter.onlyshowerror){
																	this.style.backgroundColor = f.fieldOriginalStyle.backgroundColor;
																}else{
																	this.style.backgroundColor = "#D3FEBA";
																}
																if (f.fieldOriginalStyle.border){																			
																	this.style.border = f.fieldOriginalStyle.border;
																	alert(this.style.border);
																}
															}else{
																this.style.backgroundColor = "#FFB9B9";
															}
															//
														}											
														//console.info(this.isFormFieldValid);
														return this.isFormFieldValid;
													}
													return true;
												}														

		if (flt.keyup || flt.change || flt.nextfield){
			//handle keyup capabilities		
			if (flt.keyup || flt.change){		
				f.fieldKeyupFunction = function(extCall){
											if (this.fieldFormatFilter.allownull && this.fieldCompareFunction((/^$/),extCall)){
												return true;
											}else{
												//console.info(this.id,"keyup compare:",this.fieldCompareFunction(this.fieldFormatFilter.keyup,extCall));
												return (this.fieldCompareFunction(this.fieldFormatFilter.keyup,extCall)
														&& this.fieldCompareFunction(this.fieldFormatFilter.change,extCall)
														&& this.fieldCompareFunction(this.fieldFormatFilter.lengthtest,extCall));
											}
										}
				addEvent(f,"keyup", function(e){(e.srcElement || e.target).fieldKeyupFunction();},false);
				if (flt.change){
					addEvent(f,"change", function(e){(e.srcElement || e.target).fieldKeyupFunction();},false);
				}
			}
					
			//handle the nextfield capabilty
			if (flt.nextfield){
				f.setAttribute("autocomplete","off");
				f.fieldNextFieldFunction = function(e){
																			//console.info("testing nextfield");																
																			if (this.fieldFinalFunction() && this.fieldKeyupFunction()){
																				//console.info("passed - ready for the next field");
																				$(this.fieldFormatFilter.nextfield).focus();
																			}
																		}
				addEvent(f,"keyup", function(e){(e.srcElement || e.target).fieldNextFieldFunction();},false);
			}
		}
		
		if (flt.final || flt.lengthtest){
			f.fieldFinalFunction = function(extCall){
										//console.info ("testing final function");
										//console.info(this,this.fieldFormatFilter.allownull);
										if (this.fieldFormatFilter.allownull && this.fieldCompareFunction((/^$/),extCall)){
											return true;
											//alert("null and valid");
										}else{
											//alert("not null");
											return (this.fieldCompareFunction(this.fieldFormatFilter.final,extCall) 
												&& this.fieldCompareFunction(this.fieldFormatFilter.lengthtest,extCall));
										}
									}
		}

	}
};

dom.checkFieldFormat = function(fieldObjorID,extCall){
	
	var f = $(fieldObjorID);	
	if (f.fieldFormatFilter){
		//console.info("fieldObjorID:", fieldObjorID);
		//console.info("extCall: ",extCall);		
		if (f.fieldKeyupFunction){ f.fieldKeyupFunction(extCall); }
		if (f.fieldFinalFunction){  f.fieldFinalFunction(extCall); }		
		return f.isFormFieldValid;
	}else{
		return true;
	}
};


dom.validateForm = function(formObjorID,returnErrorAry){
	var frm = $(formObjorID);
	var errAry = [];
	var isFormValid = true;
	for (var i=0;i<frm.length;i++){
		if (!dom.checkFieldFormat(frm[i])){ 
			errAry.push(frm[i]);
			isFormValid = false; 
		}
	}
	if (returnErrorAry){ 
		return errAry;
	}else{
		return isFormValid;
	}
};


dom.addFormData = function(formNameOrObject,elName,elValue,elType,returnObject,cssStyle,otherProp,selectListObj){
	var f = $(formNameOrObject);
	if (!f && !returnObject){f = dom.addForm(formNameOrObject);} //create the form if it doesn't exist
	elType = elType?elType.toLowerCase():"text";
	
	//if (!$(elName)){ // if the form element doesn't already exist
	if (!f[elName]){ // if the form element doesn't already exist
		switch(elType){
			case "static":
				var newInput = document.createElement("span");
				newInput.innerHTML = elValue;
				break;
			case "textarea":
				var newInput = document.createElement("textarea");
				newInput.name = elName;
				break;
			case "select":
				var newInput = document.createElement("select");
				newInput.name = elName;
				break;
			case "checkboxbit":
				var newInput = document.createElement("input");
				newInput.type = "hidden";
				newInput.name = elName;
				var cBox = document.createElement("input");
				cBox.type = "checkbox";
				cBox.name = elName + '_checkbox';
				cBox.id = elName + '_checkbox';
				if (elValue){ cBox.checked = true; }
				//cBox.onclick = function(){$(elName).value = this.checked?1:0;};
				cBox.onclick = function(){f[elName].value = this.checked?1:0;};
				returnObject?null:f.appendChild(cBox);
				newInput.name = elName;
				break;
			default:
				//alert(elType);
				var newInput = document.createElement("input");
				newInput.type = elType;
				newInput.name = elName;
			}
		newInput.id = elName;
	}else{
		//console.info("attempting to add an exisiting form element: " + elName);
		//var newInput = $(elName);
		var newInput = f[elName];
	}
	//console.info(elType);
	if (!(elValue==null) ){newInput.value = elValue;}

	if(cssStyle){newInput.className = cssStyle;}
	if (otherProp){
		for (p in otherProp){
			//alert(p);
			newInput[p] = otherProp[p];
		}
	}
	if (elType == "select" && selectListObj){
		//alert(newInput.options.length);
		if (selectListObj.constructor == Array){ //set name and value as the same thing if we've got an Array
			for (var o=0;o<selectListObj.length;o++){
				newInput.options[newInput.options.length] = new Option(selectListObj[o], selectListObj[o]);
			}
		}else{
			for (var o in selectListObj){
				newInput.options[newInput.options.length] = new Option(o, selectListObj[o]);
			}			
		}
	}
	
	if(returnObject){
		return newInput;
	}else{
		f.appendChild(newInput);
		if (otherProp && otherProp.addselectprompt){
			dom.addNode("add",f,"span",{"selectObj":newInput,"promptText":otherProp.addselectprompt,"className":"fakeLink",onclick:function(e){dom.addNewSelectOption((e.srcElement || e.target).selectObj,(e.srcElement || e.target).promptText)}},{"padding":"0 5px 0 5px"});
		}
	}
};

dom.addNewSelectOption = function(selectObj,promptText){
	promptText?promptText:"Add an item to this list:"
	var newOption = prompt(promptText);
	var hasMatch = false;

	if (newOption){
		var sObj = $(selectObj);
		var sOpt = sObj.options;
		
		if (sOpt.length){ //are there already options?
			for (var ii = 0; ii<sOpt.length;ii++){
				if (newOption.toLowerCase() == sOpt[ii].value.toLowerCase()){
					hasMatch = true;
					sObj.selectedIndex=ii;
				}
			}
		}
		
		if (!hasMatch){
			sOpt[sOpt.length] = new Option(newOption, newOption);
			sObj.selectedIndex=[sOpt.length-1];
		}
	}
}


dom.addNode = function(nodeText,nodeParent,nodeType,otherProp,styleProp){
	var np = $(nodeParent)?$(nodeParent):$(document.body);
	var nt = nodeType?nodeType:"span";
	var t = (nodeText == "" || !nodeText)?null:nodeText;
	
	if (otherProp && otherProp.id && $(otherProp.id) && $(otherProp.id).tagName.toLowerCase() == nt.toLowerCase()){
		var n = $(otherProp.id);
	}else{
		var n = document.createElement(nt);
	}
	//if (t){n.innerHTML = t;}

	if (otherProp){
		for (var p in otherProp){
			n[p] = otherProp[p];
		}
	}
	if (styleProp){
		for (var p in styleProp){
			n.style[p] = styleProp[p];
		}
	}
	//can't use this to add a string of <td></td><td></td> to a <tr> in IE
	//must add each <td> on its own, as a seperate node. Who knows why.
	if (t && nodeType != "tr" && nodeType != "trd"){n.innerHTML = t;}
	np.appendChild(n);
	return n;
};



// -- remove an object from a dom
//		defaults to removal from the document object
// 		can be passed an object or an ID
dom.removeObject = function(obID,domObj){
	if (obID){
		if(!domObj){domObj = document}; //defaults to 
		
		if (typeof obID == "object"){
			//alert("removing " + typeof obID);
			if (obID.parentNode){
				obID.parentNode.removeChild(obID);
			}else{
				obID.removeNode(true);
			}
		}else{
			if (domObj.getElementById(obID)){
				domObj.getElementById(obID).parentNode.removeChild(document.getElementById(obID));
			}
		}
	}
};

// -- set the visibility of an object 
//		pass in either an object refrence or its unique ID
dom.toggle = function(objOrID,forceState){
	//figure out the object if not passed one
	var ob = $(objOrID);
	if (ob){
		if ((ob.style.display != "none" && arguments.length == 1) || (arguments.length >= 2 && !forceState)){	
			ob.style.display = "none";
		}else{
			ob.style.display = "";
		}
	}
};


/*--------------------------------------------------------
	dom.getElementsByClassName
	Written by Jonathan Snook, http://www.snook.ca/jonathan
	Add-ons by Robert Nyman, http://www.robertnyman.com
	http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/
	Usage:
		To get all a elements in the document with a info-links class:
			getElementsByClassName(document, "a", "info-links");
		To get all div elements within the element named "container", with a "col" class.
			getElementsByClassName(document.getElementById("container"), "div", "col"); 
		To get all elements within in the document with a "click-me" class.
			getElementsByClassName(document, "*", "click-me"); 	
			
	//modified by AH to accept a non-existent oElm argument, and return an empty array
*/
dom.getElementsByClassName = function(oElm, strTagName, strClassName){
	oElm = $(oElm);
	var arrElements = (strTagName == "*" && document.all)?document.all:(oElm)?oElm.getElementsByTagName(strTagName):[];
    var arrReturnElements = new Array();    
    strClassName = strClassName.replace(/\-/g, "\\-");
    
    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    var oElement;
    for(var i=0; i<arrElements.length; i++){
        oElement = arrElements[i];      
        if(oRegExp.test(oElement.className)){
            arrReturnElements.push(oElement);
        }   
    }
    
    return (arrReturnElements);

};

//*** This code is copyright 2002-2003 by Gavin Kistner and Refinery Inc.; www.refinery.com
//*** It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt
//*** Reuse or modification is free provided you abide by the terms of that license.

// Find the x,y location in pixels for a relatively positioned object
// returns an object with .x and .y properties.
// modified 3/22/2006 by andrew hughes
dom.findXY = function(objOrID){
	var ob = $(objOrID);
	var x=0,y=0;
	while (ob!=null){
		x+=ob.offsetLeft-ob.scrollLeft;
		y+=ob.offsetTop-ob.scrollTop;
		ob=ob.offsetParent;
	}
	return {x:x,y:y};
};

// Find the x,y location in pixels for a relatively positioned object
// returns an object with .x, .y, .w (width) and .h (height) properties.
dom.old_findXYWH = function(objOrID){
	var ob = $(objOrID);	
	var objXY = dom.findXY(ob);
	if(ob){
		return objXY?{ x:objXY.x, y:objXY.y, w:ob.offsetWidth, h:ob.offsetHeight }:{ x:0, y:0, w:0, h:0 };
	}
};

dom.alert = function(msg,parentObject,escTags,forceClear){
	var dac = document.getElementById("__domAlertConsole")?document.getElementById("__domAlertConsole"):null;
	if (!dac){
		var cons = document.createElement('div');
		cons.id = "__domAlertConsole";
		cons.style["border"] = "1px dotted #000";
		cons.style["backgroundColor"] = "#ffff44";
		cons.style["color"] = "#000";
		cons.style["padding"] = "4px";
		cons.style["fontSize"] = "11px";
		cons.style["width"] = "80%";
		cons.style["margin"] = "15px";
		cons.style["overflow"] = "auto";
		cons.style["textAlign"] = "left";
		var pCon = document.getElementById(parentObject)?document.getElementById(parentObject):document.body;
		if (!pCon){
			addEvent(window,"load",function(){ dom.alert(msg,parentObject,escTags,forceClear);},false);
			return;
		}else{
			pCon.appendChild(cons);
			dac = document.getElementById("__domAlertConsole");
		}
	}
   
	if (escTags){
		//msg = msg.replace(/</g,"&lt;");
		//msg = msg.replace(/>/g,"&gt;");
		msg = "<xmp>" + msg + "</xmp>";
	}

	if (forceClear){
		dac.innerHTML = msg;
	}else{
		dac.innerHTML += msg;
	}
	return;
};

//*** This code is copyright 2002-2003 by Gavin Kistner and Refinery Inc.; www.refinery.com
//*** It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt
//*** Reuse or modification is free provided you abide by the terms of that license.
// Find the CSS rule by its selector text, in any styleshet
dom.getCSSrule = function(selText){
	for (var j=document.styleSheets.length-1;j>=0;j--){
		var ss = document.styleSheets[j];
		var cache = ss.cssRulesCache = ss.cssRulesCache || {};
	
		//screw case sensitivity; IE and Mozilla don't agree on case for elements themselves
		selText=selText.toLowerCase();
	
		if (cache[selText]) return cache[selText];
		var rules = ss.cssRules || ss.rules;
		for (var i=0,len=rules.length;i<len;i++){
			var rule=rules[i], ruleSelText = rule.selectorText;
			
			// Clean up Safari's weirdness
			ruleSelText = ruleSelText.replace(/\.(\w+)\[CLASS~="\1"\]/g,'.$1').replace(/\[ID"([^"]+)"\]/g,'#$1');
			
			// Clean up IEMac's weirdness
			ruleSelText = ruleSelText.replace(/\*([.#])/g,'$1');
	
			//screw case sensitivity; IE and Mozilla don't agree on case for elements themselves
			ruleSelText = ruleSelText.toLowerCase();
	
			if (ruleSelText==selText) return (cache[selText]=rules[i]);
		}
	}
	return null;
};


//create the DOMParser object if needed
// DOMParser turns strings of XML into an xml object
if (typeof DOMParser == "undefined") {
	var DOMParser = function (){};
	DOMParser.prototype.parseFromString = function (str, contentType) {
		
	  if (typeof ActiveXObject != "undefined") {
			var progIDs = [ 'Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.5.0', 'Msxml2.DOMDocument.4.0', 'Msxml2.DOMDocument.3.0', 'Msxml2.DOMDocument' ];
			for (var i = 0; i < progIDs.length; i++) {
				try {
					var d = new ActiveXObject(progIDs[i]);
					d.async = false;
					d.loadXML(str);
					return d;
				}catch (ex) {}
			}
	  } else if (typeof XMLHttpRequest != "undefined") {
	     var req = new XMLHttpRequest;
	     req.open("GET", "data:" + (contentType || "application/xml") +
	                     ";charset=utf-8," + encodeURIComponent(str), false);
	     if (req.overrideMimeType) {
	        req.overrideMimeType(contentType);
	     }
	     req.send(null);
	     return req.responseXML;
		}
	};
}
dom.parser = new DOMParser();


dom.findXYWH = function(o){
	var o = $(o);
	if (!o) { return null;}
    
	var fixBrowserQuirks = true;
  var left = 0;
  var top = 0;
  var width = 0;
  var height = 0;
  var parentNode = null;
  var offsetParent = null;

	var offsetParent = o.offsetParent;
	var originalObject = o;
	var el = o; // "el" will be nodes as we walk up, "o" will be saved for offsetParent references
	while (el.parentNode!=null) {
		el = el.parentNode;
		if (el.offsetParent==null) {
		}else {
			var considerScroll = true;
			/*
			In Opera, if parentNode of the first object is scrollable, then offsetLeft/offsetTop already 
			take its scroll position into account. If elements further up the chain are scrollable, their 
			scroll offsets still need to be added in. And for some reason, TR nodes have a scrolltop value
			which must be ignored.
			*/
			if (fixBrowserQuirks && window.opera) {
				if (el==originalObject.parentNode || el.nodeName=="TR") {
					considerScroll = false;
				}
			}
			if (considerScroll) {
				if (el.scrollTop && el.scrollTop>0) {
					top -= el.scrollTop;
				}
				if (el.scrollLeft && el.scrollLeft>0) {
					left -= el.scrollLeft;
				}
			}
		}
		
		// If this node is also the offsetParent, add on the offsets and reset to the new offsetParent
		if (el == offsetParent) {
			left += o.offsetLeft;
			if (el.clientLeft && el.nodeName!="TABLE") { 
				left += el.clientLeft;
			}
			top += o.offsetTop;
			if (el.clientTop && el.nodeName!="TABLE") {
				top += el.clientTop;
			}
			o = el;
			if (o.offsetParent==null) {
				if (o.offsetLeft) { left += o.offsetLeft;}
				if (o.offsetTop) { top += o.offsetTop;}
			}
			offsetParent = o.offsetParent;
		}
	}

	if (originalObject.offsetWidth) {
		width = originalObject.offsetWidth;
	}
	if (originalObject.offsetHeight) {
		height = originalObject.offsetHeight;
	}
	return {x:left, y:top, w:width, h:height};
};

var progressBar = {};
progressBar.start = function(barID,appendToObjOrID,barText,maxCount,refreshSpeed){
	if (!maxCount){ maxCount = 10; }
	if (!refreshSpeed){ refreshSpeed = 280; }
	if (!progressBar.barList){progressBar.barList = {}; }
	if (!barText){barText = "";}
	progressBar.barList[barID] = {};
	var pb = progressBar.barList[barID];
	pb.barID = barID;
	pb.parentObj = $(appendToObjOrID);
	pb.barText = barText;
	pb.maxCount = maxCount;
	pb.refreshSpeed = refreshSpeed;
	if (pb.parentObj){
		pb.timeoutid = setInterval(function(){progressBar.handleProgressBar(pb);},refreshSpeed);
	}
};

progressBar.end = function(barID){
	if (barID){
		window.clearInterval(progressBar.barList[barID].timeoutid);
		dom.removeObject(barID + "_progressBar");
		progressBar.barList[barID] = null;
	}else{
		for (var b in progressBar.barList){
			window.clearInterval(progressBar.barList[b].timeoutid);
			dom.removeObject(b + "_progressBar");
			progressBar.barList[b] = null;
		}
		progressBar.barList = {};
	}	
};

progressBar.handleProgressBar = function(pbObj){
	var barID = pbObj.barID;
	if (!$(barID + "_progressBar")){
		var curPB = document.createElement("span");
		curPB.id = barID + "_progressBar";
		pbObj.parentObj.appendChild(curPB);
		if (pbObj.barText){curPB.innerHTML = pbObj.barText;}
		curPB.style.paddingLeft = "5px";
	}
	var curPB = $(barID + "_progressBar");
	if (curPB.childNodes.length >= pbObj.maxCount){
		curPB.innerHTML = pbObj.barText;
	}
	dom.addNode("&nbsp;",curPB,"span",null,{"fontSize":"8px","margin":"2px","border":"1px #888 solid","background":"#FEFCAB"});
};

dom.toJSON = function (o) {
  var m = {'\b': '\\b','\t': '\\t','\n': '\\n','\f': '\\f','\r': '\\r','"' : '\\"','\\': '\\\\'},
      s = {
          array: function (x) {
              var a = ['['], b, f, i, l = x.length, v;
              for (i = 0; i < l; i += 1) {
                  v = x[i];
                  f = s[typeof v];
                  if (f) {
                      v = f(v);
                      if (typeof v == 'string') {
                          if (b) {
                              a[a.length] = ',';
                          }
                          a[a.length] = v;
                          b = true;
                      }
                  }
              }
              a[a.length] = ']';
              return a.join('');
          },
          'boolean': function (x) {
              return String(x);
          },
          'null': function (x) {
              return "null";
          },
          number: function (x) {
              return isFinite(x) ? String(x) : 'null';
          },
          object: function (x) {
              if (x) {
                  if (x instanceof Array) {
                      return s.array(x);
                  }
                  var a = ['{'], b, f, i, v;
                  for (i in x) {
                      v = x[i];
                      f = s[typeof v];
                      if (f) {
                          v = f(v);
                          if (typeof v == 'string') {
                              if (b) {
                                  a[a.length] = ',';
                              }
                              a.push(s.string(i), ':', v);
                              b = true;
                          }
                      }
                  }
                  a[a.length] = '}';
                  return a.join('');
              }
              return 'null';
          },
          string: function (x) {
              if (/["\\\x00-\x1f]/.test(x)) {
                  x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                      var c = m[b];
                      if (c) {
                          return c;
                      }
                      c = b.charCodeAt();
                      return '\\u00' +
                          Math.floor(c / 16).toString(16) +
                          (c % 16).toString(16);
                  });
              }
              return '"' + x + '"';
          }
       };
    if (o instanceof Array){
	  	return s.array(o);
	  }else if (o instanceof Object){
	  	return s.object(o);
	  }
};