function massDeleteConfirmation(refresh) {
	var answer = confirm("Are you sure you want to delete this records?")
	if (answer){
		document.forms[0].submit();
	} else {
		alert("No records where deleted.")
	}
}

var swit = true;

function checkAll(f,butn){
	for(x=0; x<=f.elements.length-1; x++) {
		var boxColl=f.elements[x];
		boxColl.checked = swit;
	}
   if(swit == true) {
		swit       = false;
	} else {
		swit       = true;
	}
}

function getAnchorPosition(anchorname){var useWindow=false;var coordinates=new Object();var x=0,y=0;var use_gebi=false, use_css=false, use_layers=false;if(document.getElementById){use_gebi=true;}else if(document.all){use_css=true;}else if(document.layers){use_layers=true;}if(use_gebi && document.all){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_gebi){var o=document.getElementById(anchorname);x=AnchorPosition_getPageOffsetLeft(o);y=AnchorPosition_getPageOffsetTop(o);}else if(use_css){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_layers){var found=0;for(var i=0;i<document.anchors.length;i++){if(document.anchors[i].name==anchorname){found=1;break;}}if(found==0){coordinates.x=0;coordinates.y=0;return coordinates;}x=document.anchors[i].x;y=document.anchors[i].y;}else{coordinates.x=0;coordinates.y=0;return coordinates;}coordinates.x=x;coordinates.y=y;return coordinates;}
function getAnchorWindowPosition(anchorname){var coordinates=getAnchorPosition(anchorname);var x=0;var y=0;if(document.getElementById){if(isNaN(window.screenX)){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else{x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}}else if(document.all){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else if(document.layers){x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}coordinates.x=x;coordinates.y=y;return coordinates;}
function AnchorPosition_getPageOffsetLeft(el){var ol=el.offsetLeft;while((el=el.offsetParent) != null){ol += el.offsetLeft;}return ol;}
function AnchorPosition_getWindowOffsetLeft(el){return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;}
function AnchorPosition_getPageOffsetTop(el){var ot=el.offsetTop;while((el=el.offsetParent) != null){ot += el.offsetTop;}return ot;}
function AnchorPosition_getWindowOffsetTop(el){return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;}

var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
function LZ(x){return(x<0||x>9?"":"0")+x}
function isDate(val,format){var date=getDateFromFormat(val,format);if(date==0){return false;}return true;}
function compareDates(date1,dateformat1,date2,dateformat2){var d1=getDateFromFormat(date1,dateformat1);var d2=getDateFromFormat(date2,dateformat2);if(d1==0 || d2==0){return -1;}else if(d1 > d2){return 1;}return 0;}
function formatDate(date,format){format=format+"";var result="";var i_format=0;var c="";var token="";var y=date.getYear()+"";var M=date.getMonth()+1;var d=date.getDate();var E=date.getDay();var H=date.getHours();var m=date.getMinutes();var s=date.getSeconds();var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;var value=new Object();if(y.length < 4){y=""+(y-0+1900);}value["y"]=""+y;value["yyyy"]=y;value["yy"]=y.substring(2,4);value["M"]=M;value["MM"]=LZ(M);value["MMM"]=MONTH_NAMES[M-1];value["NNN"]=MONTH_NAMES[M+11];value["d"]=d;value["dd"]=LZ(d);value["E"]=DAY_NAMES[E+7];value["EE"]=DAY_NAMES[E];value["H"]=H;value["HH"]=LZ(H);if(H==0){value["h"]=12;}else if(H>12){value["h"]=H-12;}else{value["h"]=H;}value["hh"]=LZ(value["h"]);if(H>11){value["K"]=H-12;}else{value["K"]=H;}value["k"]=H+1;value["KK"]=LZ(value["K"]);value["kk"]=LZ(value["k"]);if(H > 11){value["a"]="PM";}else{value["a"]="AM";}value["m"]=m;value["mm"]=LZ(m);value["s"]=s;value["ss"]=LZ(s);while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(value[token] != null){result=result + value[token];}else{result=result + token;}}return result;}
function _isInteger(val){var digits="1234567890";for(var i=0;i < val.length;i++){if(digits.indexOf(val.charAt(i))==-1){return false;}}return true;}
function _getInt(str,i,minlength,maxlength){for(var x=maxlength;x>=minlength;x--){var token=str.substring(i,i+x);if(token.length < minlength){return null;}if(_isInteger(token)){return token;}}return null;}
function getDateFromFormat(val,format){val=val+"";format=format+"";var i_val=0;var i_format=0;var c="";var token="";var token2="";var x,y;var now=new Date();var year=now.getYear();var month=now.getMonth()+1;var date=1;var hh=now.getHours();var mm=now.getMinutes();var ss=now.getSeconds();var ampm="";while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(token=="yyyy" || token=="yy" || token=="y"){if(token=="yyyy"){x=4;y=4;}if(token=="yy"){x=2;y=2;}if(token=="y"){x=2;y=4;}year=_getInt(val,i_val,x,y);if(year==null){return 0;}i_val += year.length;if(year.length==2){if(year > 70){year=1900+(year-0);}else{year=2000+(year-0);}}}else if(token=="MMM"||token=="NNN"){month=0;for(var i=0;i<MONTH_NAMES.length;i++){var month_name=MONTH_NAMES[i];if(val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()){if(token=="MMM"||(token=="NNN"&&i>11)){month=i+1;if(month>12){month -= 12;}i_val += month_name.length;break;}}}if((month < 1)||(month>12)){return 0;}}else if(token=="EE"||token=="E"){for(var i=0;i<DAY_NAMES.length;i++){var day_name=DAY_NAMES[i];if(val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()){i_val += day_name.length;break;}}}else if(token=="MM"||token=="M"){month=_getInt(val,i_val,token.length,2);if(month==null||(month<1)||(month>12)){return 0;}i_val+=month.length;}else if(token=="dd"||token=="d"){date=_getInt(val,i_val,token.length,2);if(date==null||(date<1)||(date>31)){return 0;}i_val+=date.length;}else if(token=="hh"||token=="h"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>12)){return 0;}i_val+=hh.length;}else if(token=="HH"||token=="H"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>23)){return 0;}i_val+=hh.length;}else if(token=="KK"||token=="K"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>11)){return 0;}i_val+=hh.length;}else if(token=="kk"||token=="k"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>24)){return 0;}i_val+=hh.length;hh--;}else if(token=="mm"||token=="m"){mm=_getInt(val,i_val,token.length,2);if(mm==null||(mm<0)||(mm>59)){return 0;}i_val+=mm.length;}else if(token=="ss"||token=="s"){ss=_getInt(val,i_val,token.length,2);if(ss==null||(ss<0)||(ss>59)){return 0;}i_val+=ss.length;}else if(token=="a"){if(val.substring(i_val,i_val+2).toLowerCase()=="am"){ampm="AM";}else if(val.substring(i_val,i_val+2).toLowerCase()=="pm"){ampm="PM";}else{return 0;}i_val+=2;}else{if(val.substring(i_val,i_val+token.length)!=token){return 0;}else{i_val+=token.length;}}}if(i_val != val.length){return 0;}if(month==2){if( ((year%4==0)&&(year%100 != 0) ) ||(year%400==0) ){if(date > 29){return 0;}}else{if(date > 28){return 0;}}}if((month==4)||(month==6)||(month==9)||(month==11)){if(date > 30){return 0;}}if(hh<12 && ampm=="PM"){hh=hh-0+12;}else if(hh>11 && ampm=="AM"){hh-=12;}var newdate=new Date(year,month-1,date,hh,mm,ss);return newdate.getTime();}
function parseDate(val){var preferEuro=(arguments.length==2)?arguments[1]:false;generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');var d=null;for(var i=0;i<checkList.length;i++){var l=window[checkList[i]];for(var j=0;j<l.length;j++){d=getDateFromFormat(val,l[j]);if(d!=0){return new Date(d);}}}return null;}

function PopupWindow_getXYPosition(anchorname){var coordinates;if(this.type == "WINDOW"){coordinates = getAnchorWindowPosition(anchorname);}else{coordinates = getAnchorPosition(anchorname);}this.x = coordinates.x;this.y = coordinates.y;}
function PopupWindow_setSize(width,height){this.width = width;this.height = height;}
function PopupWindow_populate(contents){this.contents = contents;this.populated = false;}
function PopupWindow_setUrl(url){this.url = url;}
function PopupWindow_setWindowProperties(props){this.windowProperties = props;}
function PopupWindow_refresh(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).innerHTML = this.contents;}else if(this.use_css){document.all[this.divName].innerHTML = this.contents;}else if(this.use_layers){var d = document.layers[this.divName];d.document.open();d.document.writeln(this.contents);d.document.close();}}else{if(this.popupWindow != null && !this.popupWindow.closed){if(this.url!=""){this.popupWindow.location.href=this.url;}else{this.popupWindow.document.open();this.popupWindow.document.writeln(this.contents);this.popupWindow.document.close();}this.popupWindow.focus();}}}
function PopupWindow_showPopup(anchorname){this.getXYPosition(anchorname);this.x += this.offsetX;this.y += this.offsetY;if(!this.populated &&(this.contents != "")){this.populated = true;this.refresh();}if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.left = this.x + "px";document.getElementById(this.divName).style.top = this.y;document.getElementById(this.divName).style.visibility = "visible";}else if(this.use_css){document.all[this.divName].style.left = this.x;document.all[this.divName].style.top = this.y;document.all[this.divName].style.visibility = "visible";}else if(this.use_layers){document.layers[this.divName].left = this.x;document.layers[this.divName].top = this.y;document.layers[this.divName].visibility = "visible";}}else{if(this.popupWindow == null || this.popupWindow.closed){if(this.x<0){this.x=0;}if(this.y<0){this.y=0;}if(screen && screen.availHeight){if((this.y + this.height) > screen.availHeight){this.y = screen.availHeight - this.height;}}if(screen && screen.availWidth){if((this.x + this.width) > screen.availWidth){this.x = screen.availWidth - this.width;}}var avoidAboutBlank = window.opera ||( document.layers && !navigator.mimeTypes['*']) || navigator.vendor == 'KDE' ||( document.childNodes && !document.all && !navigator.taintEnabled);this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");}this.refresh();}}
function PopupWindow_hidePopup(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.visibility = "hidden";}else if(this.use_css){document.all[this.divName].style.visibility = "hidden";}else if(this.use_layers){document.layers[this.divName].visibility = "hidden";}}else{if(this.popupWindow && !this.popupWindow.closed){this.popupWindow.close();this.popupWindow = null;}}}
function PopupWindow_isClicked(e){if(this.divName != null){if(this.use_layers){var clickX = e.pageX;var clickY = e.pageY;var t = document.layers[this.divName];if((clickX > t.left) &&(clickX < t.left+t.clip.width) &&(clickY > t.top) &&(clickY < t.top+t.clip.height)){return true;}else{return false;}}else if(document.all){var t = window.event.srcElement;while(t.parentElement != null){if(t.id==this.divName){return true;}t = t.parentElement;}return false;}else if(this.use_gebi && e){var t = e.originalTarget;while(t.parentNode != null){if(t.id==this.divName){return true;}t = t.parentNode;}return false;}return false;}return false;}
function PopupWindow_hideIfNotClicked(e){if(this.autoHideEnabled && !this.isClicked(e)){this.hidePopup();}}
function PopupWindow_autoHide(){this.autoHideEnabled = true;}
function PopupWindow_hidePopupWindows(e){for(var i=0;i<popupWindowObjects.length;i++){if(popupWindowObjects[i] != null){var p = popupWindowObjects[i];p.hideIfNotClicked(e);}}}
function PopupWindow_attachListener(){if(document.layers){document.captureEvents(Event.MOUSEUP);}window.popupWindowOldEventListener = document.onmouseup;if(window.popupWindowOldEventListener != null){document.onmouseup = new Function("window.popupWindowOldEventListener();PopupWindow_hidePopupWindows();");}else{document.onmouseup = PopupWindow_hidePopupWindows;}}
function PopupWindow(){if(!window.popupWindowIndex){window.popupWindowIndex = 0;}if(!window.popupWindowObjects){window.popupWindowObjects = new Array();}if(!window.listenerAttached){window.listenerAttached = true;PopupWindow_attachListener();}this.index = popupWindowIndex++;popupWindowObjects[this.index] = this;this.divName = null;this.popupWindow = null;this.width=0;this.height=0;this.populated = false;this.visible = false;this.autoHideEnabled = false;this.contents = "";this.url="";this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";if(arguments.length>0){this.type="DIV";this.divName = arguments[0];}else{this.type="WINDOW";}this.use_gebi = false;this.use_css = false;this.use_layers = false;if(document.getElementById){this.use_gebi = true;}else if(document.all){this.use_css = true;}else if(document.layers){this.use_layers = true;}else{this.type = "WINDOW";}this.offsetX = 0;this.offsetY = 0;this.getXYPosition = PopupWindow_getXYPosition;this.populate = PopupWindow_populate;this.setUrl = PopupWindow_setUrl;this.setWindowProperties = PopupWindow_setWindowProperties;this.refresh = PopupWindow_refresh;this.showPopup = PopupWindow_showPopup;this.hidePopup = PopupWindow_hidePopup;this.setSize = PopupWindow_setSize;this.isClicked = PopupWindow_isClicked;this.autoHide = PopupWindow_autoHide;this.hideIfNotClicked = PopupWindow_hideIfNotClicked;}


/* SOURCE FILE: CalendarPopup.js */

function CalendarPopup(){var c;if(arguments.length>0){c = new PopupWindow(arguments[0]);}else{c = new PopupWindow();c.setSize(150,175);}c.offsetX = -152;c.offsetY = 25;c.autoHide();c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");c.dayHeaders = new Array("S","M","T","W","T","F","S");c.returnFunction = "CP_tmpReturnFunction";c.returnMonthFunction = "CP_tmpReturnMonthFunction";c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";c.returnYearFunction = "CP_tmpReturnYearFunction";c.weekStartDay = 0;c.isShowYearNavigation = false;c.displayType = "date";c.disabledWeekDays = new Object();c.disabledDatesExpression = "";c.yearSelectStartOffset = 2;c.currentDate = null;c.todayText="Today";c.cssPrefix="";c.isShowNavigationDropdowns=false;c.isShowYearNavigationInput=false;window.CP_calendarObject = null;window.CP_targetInput = null;window.CP_dateFormat = "MM/dd/yyyy";c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;c.setReturnFunction = CP_setReturnFunction;c.setReturnMonthFunction = CP_setReturnMonthFunction;c.setReturnQuarterFunction = CP_setReturnQuarterFunction;c.setReturnYearFunction = CP_setReturnYearFunction;c.setMonthNames = CP_setMonthNames;c.setMonthAbbreviations = CP_setMonthAbbreviations;c.setDayHeaders = CP_setDayHeaders;c.setWeekStartDay = CP_setWeekStartDay;c.setDisplayType = CP_setDisplayType;c.setDisabledWeekDays = CP_setDisabledWeekDays;c.addDisabledDates = CP_addDisabledDates;c.setYearSelectStartOffset = CP_setYearSelectStartOffset;c.setTodayText = CP_setTodayText;c.showYearNavigation = CP_showYearNavigation;c.showCalendar = CP_showCalendar;c.hideCalendar = CP_hideCalendar;c.getStyles = getCalendarStyles;c.refreshCalendar = CP_refreshCalendar;c.getCalendar = CP_getCalendar;c.select = CP_select;c.setCssPrefix = CP_setCssPrefix;c.showNavigationDropdowns = CP_showNavigationDropdowns;c.showYearNavigationInput = CP_showYearNavigationInput;c.copyMonthNamesToWindow();return c;}
function CP_copyMonthNamesToWindow(){if(typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null){window.MONTH_NAMES = new Array();for(var i=0;i<this.monthNames.length;i++){window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];}for(var i=0;i<this.monthAbbreviations.length;i++){window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];}}}
function CP_tmpReturnFunction(y,m,d){if(window.CP_targetInput!=null){var dt = new Date(y,m-1,d,0,0,0);if(window.CP_calendarObject!=null){window.CP_calendarObject.copyMonthNamesToWindow();}window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);}else{alert('Use setReturnFunction() to define which function will get the clicked results!');}}
function CP_tmpReturnMonthFunction(y,m){alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m);}
function CP_tmpReturnQuarterFunction(y,q){alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q);}
function CP_tmpReturnYearFunction(y){alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y);}
function CP_setReturnFunction(name){this.returnFunction = name;}
function CP_setReturnMonthFunction(name){this.returnMonthFunction = name;}
function CP_setReturnQuarterFunction(name){this.returnQuarterFunction = name;}
function CP_setReturnYearFunction(name){this.returnYearFunction = name;}
function CP_setMonthNames(){for(var i=0;i<arguments.length;i++){this.monthNames[i] = arguments[i];}this.copyMonthNamesToWindow();}
function CP_setMonthAbbreviations(){for(var i=0;i<arguments.length;i++){this.monthAbbreviations[i] = arguments[i];}this.copyMonthNamesToWindow();}
function CP_setDayHeaders(){for(var i=0;i<arguments.length;i++){this.dayHeaders[i] = arguments[i];}}
function CP_setWeekStartDay(day){this.weekStartDay = day;}
function CP_showYearNavigation(){this.isShowYearNavigation =(arguments.length>0)?arguments[0]:true;}
function CP_setDisplayType(type){if(type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year"){alert("Invalid display type! Must be one of: date,week-end,month,quarter,year");return false;}this.displayType=type;}
function CP_setYearSelectStartOffset(num){this.yearSelectStartOffset=num;}
function CP_setDisabledWeekDays(){this.disabledWeekDays = new Object();for(var i=0;i<arguments.length;i++){this.disabledWeekDays[arguments[i]] = true;}}
function CP_addDisabledDates(start, end){if(arguments.length==1){end=start;}if(start==null && end==null){return;}if(this.disabledDatesExpression!=""){this.disabledDatesExpression+= "||";}if(start!=null){start = parseDate(start);start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}if(end!=null){end=parseDate(end);end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}if(start==null){this.disabledDatesExpression+="(ds<="+end+")";}else if(end  ==null){this.disabledDatesExpression+="(ds>="+start+")";}else{this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")";}}
function CP_setTodayText(text){this.todayText = text;}
function CP_setCssPrefix(val){this.cssPrefix = val;}
function CP_showNavigationDropdowns(){this.isShowNavigationDropdowns =(arguments.length>0)?arguments[0]:true;}
function CP_showYearNavigationInput(){this.isShowYearNavigationInput =(arguments.length>0)?arguments[0]:true;}
function CP_hideCalendar(){if(arguments.length > 0){window.popupWindowObjects[arguments[0]].hidePopup();}else{this.hidePopup();}}
function CP_refreshCalendar(index){var calObject = window.popupWindowObjects[index];if(arguments.length>1){calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));}else{calObject.populate(calObject.getCalendar());}calObject.refresh();}
function CP_showCalendar(anchorname){if(arguments.length>1){if(arguments[1]==null||arguments[1]==""){this.currentDate=new Date();}else{this.currentDate=new Date(parseDate(arguments[1]));}}this.populate(this.getCalendar());this.showPopup(anchorname);}
function CP_select(inputobj, linkname, format){var selectedDate=(arguments.length>3)?arguments[3]:null;if(!window.getDateFromFormat){alert("calendar.select: To use this method you must also include 'date.js' for date formatting");return;}if(this.displayType!="date"&&this.displayType!="week-end"){alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");return;}if(inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea"){alert("calendar.select: Input object passed is not a valid form input object");window.CP_targetInput=null;return;}if(inputobj.disabled){return;}window.CP_targetInput = inputobj;window.CP_calendarObject = this;this.currentDate=null;var time=0;if(selectedDate!=null){time = getDateFromFormat(selectedDate,format)}else if(inputobj.value!=""){time = getDateFromFormat(inputobj.value,format);}if(selectedDate!=null || inputobj.value!=""){if(time==0){this.currentDate=null;}else{this.currentDate=new Date(time);}}window.CP_dateFormat = format;this.showCalendar(linkname);}
function getCalendarStyles(){var result = "";var p = "";if(this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!=""){p=this.cssPrefix;}result += "<STYLE>\n";result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation{background-color:#C0C0C0;text-align:center;vertical-align:center;text-decoration:none;color:#000000;font-weight:bold;}\n";result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText{font-family:arial;font-size:8pt;}\n";result += "TD."+p+"cpDayColumnHeader{text-align:right;border:solid thin #C0C0C0;border-width:0 0 1 0;}\n";result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate{text-align:right;text-decoration:none;}\n";result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled{color:#D0D0D0;text-align:right;text-decoration:line-through;}\n";result += "."+p+"cpCurrentMonthDate, .cpCurrentDate{color:#000000;}\n";result += "."+p+"cpOtherMonthDate{color:#808080;}\n";result += "TD."+p+"cpCurrentDate{color:white;background-color: #C0C0C0;border-width:1;border:solid thin #800000;}\n";result += "TD."+p+"cpCurrentDateDisabled{border-width:1;border:solid thin #FFAAAA;}\n";result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled{border:solid thin #C0C0C0;border-width:1 0 0 0;}\n";result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled{height:20px;}\n";result += "A."+p+"cpTodayText{color:black;}\n";result += "."+p+"cpTodayTextDisabled{color:#D0D0D0;}\n";result += "."+p+"cpBorder{border:solid thin #808080;}\n";result += "</STYLE>\n";return result;}
function CP_getCalendar(){var now = new Date();if(this.type == "WINDOW"){var windowref = "window.opener.";}else{var windowref = "";}var result = "";if(this.type == "WINDOW"){result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';}else{result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';result += '<TR><TD ALIGN=CENTER>\n';result += '<CENTER>\n';}if(this.displayType=="date" || this.displayType=="week-end"){if(this.currentDate==null){this.currentDate = now;}if(arguments.length > 0){var month = arguments[0];}else{var month = this.currentDate.getMonth()+1;}if(arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]){var year = arguments[1];}else{var year = this.currentDate.getFullYear();}var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);if( ((year%4 == 0)&&(year%100 != 0) ) ||(year%400 == 0) ){daysinmonth[2] = 29;}var current_month = new Date(year,month-1,1);var display_year = year;var display_month = month;var display_date = 1;var weekday= current_month.getDay();var offset = 0;offset =(weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;if(offset > 0){display_month--;if(display_month < 1){display_month = 12;display_year--;}display_date = daysinmonth[display_month]-offset+1;}var next_month = month+1;var next_month_year = year;if(next_month > 12){next_month=1;next_month_year++;}var last_month = month-1;var last_month_year = year;if(last_month < 1){last_month=12;last_month_year--;}var date_class;if(this.type!="WINDOW"){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";}result += '<TR>\n';var refresh = windowref+'CP_refreshCalendar';var refreshLink = 'javascript:' + refresh;if(this.isShowNavigationDropdowns){result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpMonthNavigation" name="cpMonth" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';for( var monthCounter=1;monthCounter<=12;monthCounter++){var selected =(monthCounter==month) ? 'SELECTED' : '';result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';}result += '</select></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpYearNavigation" name="cpYear" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';for( var yearCounter=year-this.yearSelectStartOffset;yearCounter<=year+this.yearSelectStartOffset;yearCounter++){var selected =(yearCounter==year) ? 'SELECTED' : '';result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';}result += '</select></TD>';}else{if(this.isShowYearNavigation){result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;</A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;</A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');">&lt;</A></TD>';if(this.isShowYearNavigationInput){result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';}result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">&gt;</A></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;&lt;</A></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;&gt;</A></TD>\n';}}result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';result += '<TR>\n';for(var j=0;j<7;j++){result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';}result += '</TR>\n';for(var row=1;row<=6;row++){result += '<TR>\n';for(var col=1;col<=7;col++){var disabled=false;if(this.disabledDatesExpression!=""){var ds=""+display_year+LZ(display_month)+LZ(display_date);eval("disabled=("+this.disabledDatesExpression+")");}var dateClass = "";if((display_month == this.currentDate.getMonth()+1) &&(display_date==this.currentDate.getDate()) &&(display_year==this.currentDate.getFullYear())){dateClass = "cpCurrentDate";}else if(display_month == month){dateClass = "cpCurrentMonthDate";}else{dateClass = "cpOtherMonthDate";}if(disabled || this.disabledWeekDays[col-1]){result += '	<TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';}else{var selected_date = display_date;var selected_month = display_month;var selected_year = display_year;if(this.displayType=="week-end"){var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);d.setDate(d.getDate() +(7-col));selected_year = d.getYear();if(selected_year < 1000){selected_year += 1900;}selected_month = d.getMonth()+1;selected_date = d.getDate();}result += '	<TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';}display_date++;if(display_date > daysinmonth[display_month]){display_date=1;display_month++;}if(display_month > 12){display_month=1;display_year++;}}result += '</TR>';}var current_weekday = now.getDay() - this.weekStartDay;if(current_weekday < 0){current_weekday += 7;}result += '<TR>\n';result += '	<TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';if(this.disabledDatesExpression!=""){var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());eval("disabled=("+this.disabledDatesExpression+")");}if(disabled || this.disabledWeekDays[current_weekday+1]){result += '		<SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';}else{result += '		<A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';}result += '		<BR>\n';result += '	</TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year"){if(arguments.length > 0){var year = arguments[0];}else{if(this.displayType=="year"){var year = now.getFullYear()-this.yearSelectStartOffset;}else{var year = now.getFullYear();}}if(this.displayType!="year" && this.isShowYearNavigation){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');">&lt;&lt;</A></TD>\n';result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">&gt;&gt;</A></TD>\n';result += '</TR></TABLE>\n';}}if(this.displayType=="month"){result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<4;i++){result += '<TR>';for(var j=0;j<3;j++){var monthindex =((i*3)+j);result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="quarter"){result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<2;i++){result += '<TR>';for(var j=0;j<2;j++){var quarter =((i*2)+j+1);result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="year"){var yearColumnSize = 4;result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');">&lt;&lt;</A></TD>\n';result += '	<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">&gt;&gt;</A></TD>\n';result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<yearColumnSize;i++){for(var j=0;j<2;j++){var currentyear = year+(j*yearColumnSize)+i;result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.type == "WINDOW"){result += "</BODY></HTML>\n";}return result;}

var months=new Array(13);	// set up an array for string literal months
months[1]="January";		// array starts at [1] rather than [0] for
months[2]="February";		// familiar month numbering convention, could
months[3]="March";		// just as easily be [0..11] but that is less clear
months[4]="April";
months[5]="May";
months[6]="June";
months[7]="July";
months[8]="August";
months[9]="September";
months[10]="October";
months[11]="November";
months[12]="December";

var today=new Date();				// store date in today

var lmonth=months[today.getMonth() + 1];	// pull out month name
var date=today.getDate();			// pull out numerical date
var year=today.getFullYear();			// pull out numerical year
var daynum = today.getDay() + 1;		// pull out day number

if(daynum==1) day = "Sunday";			// match day name to day number
if(daynum==2) day = "Monday";
if(daynum==3) day = "Tuesday";
if(daynum==4) day = "Wednesday";
if(daynum==5) day = "Thursday";
if(daynum==6) day = "Friday";
if(daynum==7) day = "Saturday";

// make entire date into one variable, allows easy adjustment of format

// us format: var todaysdate= (day + ", " + date + " " + lmonth + " " + year);
var todaysdate= (day + ", " + lmonth + " " + date + " " + year);


var timer = null

function stop()
{
clearTimeout(timer)
}

function start()
{
var time = new Date()
var hours = time.getHours()
var minutes = time.getMinutes()
minutes=((minutes < 10) ? "0" : "") + minutes
var seconds = time.getSeconds()
seconds=((seconds < 10) ? "0" : "") + seconds
var clock = todaysdate + " " + hours + ":" + minutes + ":" + seconds
document.date.display.value = clock
timer = setTimeout("start()",1000)
}

function fValConfig()
{
	/*	Globals.  Modify these to suit your setup
	------------------------------------------- */
		
	//	Attribute used for fValidate Validator codes
	this.code = 'alt';
	
	//	Attribute used for custom error messages (override built-in error messages)
	this.emsg = 'emsg';
	
	//	Attribute used for pattern with custom validator type
	this.pattern = 'pattern';
	
	//	Change this to the classname you want for the error highlighting
	this.errorClass = 'text_error';

	//	If you wish fValidate to use only single classNames for errors
	this.useSingleClassNames = false; // or true
	
	//	This is the even that triggers the clearing of the errorClass hilighting
	this.clearEvent = 'change'; // 'change' | 'blur' | null
	
	//	For browsers that don't support attachEvent or addEventListere - override existing events for error reverting?
	this.eventOverride = false;
	
	//	If the bConfirm flag is set to true, the users will be prompted with CONFIRM box with this message
	//	See your language file for this value
	this.confirmMsg = fvalidate.i18n.config.confirmMsg;
	
	//	If user cancels CONFIRM, then this message will be alerted.  If you don't want this alert to show, then
	//	empty the variable (  this.confirmAbortMsg = '';  )
	//	See your langauge file for this value
	this.confirmAbortMsg = fvalidate.i18n.config.confirmAbortMsg;
	
	//	Enter the name/id of your form's submit button here.  Can be a string or array of strings
	this.submitButton = ['Submit','Submit2'];
	
	//	Enter the name/id of your form's reset button here
	this.resetButton = 'Reset';
	
	//	Ender the name or id of the SELECT object here. Make sure you pay attention to the values (CC Types)
	//	used in the case statement for the function validateCC()
	this.ccType = 'Credit_Card_Type';
	
	//	NOTE: The config value below exists for backwards compatibility with fValidate 3.55b.  If you have a newer 
	//	version, use the above this.ccType instead.
	//	Enter the DOM name of the SELECT object here. Make sure you pay attention to the values (CC Types)
	//	used in the case statement for the function validateCC()
	this.ccTypeObj = 'form1.Credit_Card_Type';
	
	//	Element where box errors will appear
	this.boxError = 'errors';
	
	//	Prefix given to all error paragraphs in box error mode
	this.boxErrorPrefix = 'fv_error_';
}


/*	Create static fvalidate object
------------------------------------------- */
if ( typeof fvalidate == 'undefined' )
{
	var fvalidate = new Object();
}

/*	Generic event handling
------------------------------------------- */
fvalidate.addEvent = function( obj, evt, fn, useCapture )
{
	if ( typeof obj.attachEvent != 'undefined' )
	{
		obj.attachEvent( "on" + evt, fn );
	}
	else if ( typeof obj.attachEventListener != 'undefined' )
	{
		obj.addEventListener( evt, fn, Boolean( useCapture ) );
	}
}
fvalidate.addEvents = function( obj, evts, fn, useCapture )
{
	var i = 0, evt;
	while( evt = evts[i++] )
	{
		this.addEvent( obj, evt, fn, Boolean( useCapture ) );
	}
}

/*	Main validation routine
------------------------------------------- */
function validateForm( f, bConfirm, bDisable, bDisableR, groupError, errorMode )
{
	//	Set defaults
	bConfirm	= Boolean( bConfirm );
	bDisable	= Boolean( bDisable );
	bDisableR	= Boolean( bDisableR );
	groupError	= Boolean( groupError );
	errorMode	= ( typeof errorMode != 'undefined' ) ? parseInt( errorMode, 10 ) : 0;

	//	Init vars and fValidate object
	var params, fvCode, type;
	if ( typeof f.fv == 'undefined' )
	{
		f.fv = new fValidate( f, errorMode, groupError );
	} else {		
		f.fv._reset();
		f.fv.errorMode = errorMode;
	}
	
	//	Loop through all form elements	
	var elem, i = 0, attr = f.fv.config.code;
	while ( elem = f.elements[i++] )
	{
		//	Skip fieldsets
		if ( elem.nodeName == "FIELDSET" ) continue;

		//	Does element have validator attribute? (short-circuit check)
		fvCode			= ( elem[attr] ) ? elem[attr] : elem.getAttribute( attr );
		if ( !( typeof fvCode == 'undefined' || fvCode == null || fvCode == "" ) )
		{
			//	Set params, validation type, and validation state
			params			= fvCode.split( "|" );
			type			= params[0];
			elem.validated	= true;
			
			//	Valid validator type?
			if ( typeof f.fv[type] == 'undefined' )
			{				
				f.fv.devError( [type, elem.name], 'notFound' );
				return false;
			}
			
			//	Check for modifiers
			switch( params.last() )
			{				
				case 'bok'	:	//	bok requested
					params = params.reduce( 1, 1 );
					elem.bok = true;
					break;
				case 'if'	:	//	Conditional validation requested
					params = params.reduce( 1, 1 );
					elem._if_ = true;
					break;
				case 'then'	:	//	Conditional validation requested
					params = params.reduce( 1, 1 );
					elem._then_ = true;
					break;
				default		:	//	No modifiers
					params = params.reduce( 1, 0 );
				
			}

			//	Is element an array?
			if ( /radio|checkbox/.test( elem.type ) )
			{
				//	Set group property
				elem.group = f.elements[elem.name];
			}
			
			//	Add events if not already added
			if ( typeof elem.fName == 'undefined' )
			{
				//	If element is an array			
				if ( typeof elem.group != 'undefined' )
				{
					for ( var j = 0; j < elem.group.length; j++ )				
					{
						//	Apply event-function to each child
						if ( f.fv.config.clearEvent != null )
						{
						//	fvalidate.addEvent( elem.group.item( j ), fv.config.clearEvent, fv.revertError, false );
							addEvent( elem.group.item( j ), f.fv.config.clearEvent, f.fv, 'revertError', false );
						}
					}
				}
				else
				{
					//	Apply event-function to element
				//	fvalidate.addEvent( elem, fv.config.clearEvent, fv.revertError, false );
					addEvent( elem, f.fv.config.clearEvent, f.fv, 'revertError', false );
				}
			}
			
			//	Set formatted name, current element
			elem.fName	= elem.name.format();
			f.fv.elem		= elem;
			f.fv.type		= type;

			//	Create function to call the proper validator method of the fValidate class
			var func = new Function( "obj", "method", "obj[method]( " + params.toArgString() + " );" );
			func( f.fv, type );
		
			//	If element test failed AND group error is off, return false
			if ( elem.validated == false && groupError == false ) return false;
			
			//	Clear error if field okay
			if ( elem.validated == true ) f.fv.revertError();
		}
	} //	end of element loop
	
	//	If group error, show it
	if ( groupError ) f.fv.showGroupError();

	//	Return false if errors found
	if ( f.fv.errors.length > 0 ) return false;

	//	Show pre-submission confirmation
	if ( bConfirm && !confirm( f.fv.config.confirmMsg ) )
	{
		if ( f.fv.config.confirmAbortMsg != '' ) alert( f.fv.config.confirmAbortMsg );
		return false;
	}
	
	//	Disable reset and/or submit buttons if requested
	if ( bDisable ) 
	{
		if ( typeof f.fv.config.submitButton == 'object' )
		{
			var sb, j = 0;
			while( sb = f.fv.config.submitButton[j++] )
			{
				if ( f.fv.elementExists( sb ) )
				{
					f.elements[sb].disabled = true;
				}
			}
		}
		else if ( f.fv.elementExists( f.fv.config.submitButton ) )
		{
			f.elements[f.fv.config.submitButton].disabled = true;
		}
	}
	if ( bDisableR && f.fv.elementExists( f.fv.config.resetButton ) )
	{
		f.elements[f.fv.config.resetButton].disabled = true;
	}

	//	Successful Validation.  Submit form
	return true;
	
	function addEvent( elem, evt, obj, method, capture )
	{
		var self = elem;
		if ( typeof elem.attachEvent != 'undefined' )
		{
			elem.attachEvent( "on" + evt, function() { obj[method]( self ) } );
		}
		else if ( typeof elem.addEventListener != 'undefined' )
		{
			elem.addEventListener( evt, function() { obj[method]( self ) }, capture );
		}
		else if ( f.fv.config.eventOverride )
		{
			eleme['on' + evt] = function() { obj[method]( self ) };
		}
	}
}

/*	Constructor
------------------------------------------- */
function fValidate( f, errorMode, groupError )
{
	var self        = this;
	this.form       = f;
	this.errorMode  = errorMode;
	this.groupError = groupError;
	this.errors     = new Array();
	this.validated  = true;
	this.config     = new fValConfig();
	this.i18n		= fvalidate.i18n;
	
	//	Add reset action to clear visual error cues
	f.onreset = function()
	{
		var elem, i = 0;
		while ( elem = this.elements[i++] )
		{
			self.revertError( elem );
		}
	}
	
	addLabelProperties();
	
	//	Parses form and adds label properties to elements that have one specified
	function addLabelProperties()
	{
		//	Collect all label elements in form, init vars		
		if ( typeof f.getElementsByTagName == 'undefined' ) return;
		var labels = f.getElementsByTagName( "label" );
		var label, i = j = 0;
		var elem;

		//	Loop through labels retrieved
		while ( label = labels[i++] )
		{
			//	For Opera 6
			if ( typeof label.htmlFor == 'undefined' ) return;
			
			//	Retrieve element
			elem = f.elements[label.htmlFor];
			if ( typeof elem == 'undefined' )
			{	//	No element found for label				
				self.devError( [label.htmlFor], 'noLabel' );
			}
			else if ( typeof elem.label != 'undefined' )
			{	//	label property already added
				continue;
			}
			else if ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' )
			{	//	For arrayed elements
				for ( j = 0; j < elem.length; j++ )
				{
					elem.item( j ).label = label;
				}
			}
			//	Regular label
			elem.label = label;
		}
	}		
}

/*	Reset for another validation
------------------------------------------- */
fValidate.prototype._reset = function()
{
	this.errors		= new Array();
	this.showErrors	= new Array();
}

/*	Checks if element exists in form
------------------------------------------- */
fValidate.prototype.elementExists = function( elemName )
{
	return Boolean( typeof this.form.elements[elemName] != 'undefined' );
}

/*	Receives error message and determines action
------------------------------------------- */
fValidate.prototype.throwError = function( args, which )
{
	var elem  = this.elem;

	//	Arrayed element?
	if ( typeof elem.name == 'undefined' )
	{
		elem = elem[0];
	}

	//	Bok requested AND element blank OR conditional validation?
	if ( elem.bok && this.isBlank() )
	{	//	skip		
		elem.validated = true;
		return;
	}

	//	Part of a conditional validation?
	if ( elem.cv )
	{
		return;
	}
	
	//	Set failsafe to false	
	elem.validated = false;

	//	Create error message
	which	= this.setArg( which, 0 );
	args	= this.setArg( args, [] );
	emsgElem = ( typeof this.elem.getAttribute == "undefined" ) ?
			this.elem[0]:
			this.elem;
	if ( emsgElem.getAttribute( this.config.emsg ) )
	{
		var error = emsgElem.getAttribute( this.config.emsg );
	}
	var error = this.translateMessage( args, this.i18n.errors[this.type][which] );

	//	Group error mode?
	if ( this.groupError )
	{
		//	Push error onto stack
		this.errors.push( {'elem':elem, 'msg': error} );		
	}
	else
	{
		//	Process error message		
		this.showError( error, false, emsgElem );

		var focusElem = ( typeof elem.fields != 'undefined' )?
			elem.fields[0]:
			elem;
		
		//	Focus and select elements, if possible
		this.selectFocus( focusElem );
	}
}


/*	Shows error message to user
------------------------------------------- */
fValidate.prototype.showError = function( emsg, last, elem )
{
	//	Set variables
	var self		= this,
		elem		= this.setArg( elem, this.elem ),
		isHidden	= Boolean( elem.type == 'hidden' ),
		label		= ( isHidden ) ? null : elem.label || null,
		emsg		= ( elem.getAttribute( this.config.emsg ) ) ? elem.getAttribute( this.config.emsg ).replace( /\\n/g, "\n" ) : emsg,
		errorClass	= this.config.errorClass,
		singleCSS	= this.config.useSingleClassNames;

	if ( typeof this.showErrors == 'undefined' ) this.showErrors = new Array();	
	
	//	Determine which error modes to use
	switch( this.errorMode )
	{	//	This represents all possible combinations
		case 0  : alertError(); break;
		case 1  : inputError(); break;
		case 2  : labelError(); break;
		case 3  : appendError(); break;
		case 4  : boxError(); break;
		case 5  : inputError(); labelError(); break;
		case 6  : inputError(); appendError(); break;
		case 7  : inputError(); boxError(); break;
		case 8  : inputError(); alertError(); break;
		case 9  : labelError(); appendError(); break;
		case 10 : labelError(); boxError(); break;
		case 11 : labelError(); alertError(); break;
		case 12 : appendError(); boxError(); break;
		case 13 : appendError(); alertError(); break;
		case 14 : boxError(); alertError(); break;
		case 15 : inputError(); labelError(); appendError(); break;
		case 16 : inputError(); labelError(); boxError(); break;
		case 17 : inputError(); labelError(); alertError(); break;
		case 18 : inputError(); appendError(); boxError(); break;
		case 19 : inputError(); appendError(); alertError(); break;
		case 20 : inputError(); boxError(); alertError(); break;
		case 21 : labelError(); appendError(); boxError(); break;
		case 22 : labelError(); appendError(); alertError(); break;
		case 23 : appendError(); boxError(); alertError(); break;
		case 24 : inputError(); labelError(); appendError(); boxError(); break;
		case 25 : inputError(); labelError(); appendError(); alertError(); break;
		case 26 : inputError(); appendError(); boxError(); alertError(); break;
		case 27 : labelError(); appendError(); boxError(); alertError(); break;
		case 28 : inputError(); labelError(); appendError(); boxError(); alertError(); break;		
	}
	//	Regular alert error
	function alertError()
	{
		if ( self.groupError ) self.showErrors.push( emsg );
		else alert( emsg );
		if ( last ) alert( self.i18n.groupAlert + self.showErrors.join( "\n\n- " ) );			
	}
	//	Applies class to form element
	function inputError()
	{
		if ( ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' ) || isHidden )
		{
			var subelem, i = 0;
			while( subelem = ( isHidden ) ? elem.fields[i++] : elem.item( i++ ) )			
			{
				if ( subelem.className != '' && singleCSS )
				{
					subelem.revertClass = subelem.className;
					subelem.className = errorClass;
				} else {
					self.addCSSClass( subelem, errorClass );
				}				
			}
		}
		else
		{
			if ( singleCSS )
			{
				elem.revertClass = elem.className;
				elem.className = errorClass;
			} else {
				self.addCSSClass( elem, errorClass );
			}
		}
	}
	//	Applies class to element's label
	function labelError()
	{
		if ( label == null ) return;
		if ( self.config.useSingleClassNames )
		{
			label.className = errorClass;
		} else {
			self.addCSSClass( label, errorClass );
		}
		
	}
	//	Appends error message to element's label
	function appendError()
	{
		if ( label == null || typeof label.innerHTML == 'undefined' ) return;
		if ( typeof label.original == 'undefined' )
			label.original = label.innerHTML;
		label.innerHTML = label.original + " - " + emsg.toHTML();
	}
	//	Appends Error message to pre-defined element
	function boxError()
	{
		if ( typeof self.boxError == 'undefined' ) self.boxError = document.getElementById( self.config.boxError );
		if ( self.boxError == null )
		{			
			self.devError( [self.config.boxError], 'noBox' );
			return;
		}
		if ( typeof self.elem.name == 'undefined' || self.elem.name == "" )
		{
			self.devError( [self.elem[self.config.code]], 'missingName' );
			return;
		}
		var errorId = self.config.boxErrorPrefix + self.elem.name,
			errorElem;
		if ( errorElem = document.getElementById( errorId ) ) // short-circuit
		{
			errorElem.firstChild.nodeValue = emsg.toHTML();
		}
		else
		{
			errorElem = document.createHTMLElement( 'li', { id: errorId, 'innerHTML': emsg.toHTML(), title: self.i18n.boxToolTip } );
			self.boxError.appendChild( errorElem );
			errorElem.onclick = function()
			{
				var elem = self.form.elements[this.id.replace( self.config.boxErrorPrefix, "" )];
				if ( typeof elem.fields != 'undefined' ) elem = elem.fields[0];
				if ( typeof elem.select != 'undefined' ) elem.select();
				if ( typeof elem.focus != 'undefined' ) elem.focus();
			}
		}
		self.boxError.style.display = "block";
	}
}

/*	Handles element className manipulation
------------------------------------------- */
fValidate.prototype.removeCSSClass = function( elem, className )
{
	elem.className = elem.className.replace( className, "" ).trim();
}
fValidate.prototype.addCSSClass = function( elem, className )
{
	this.removeCSSClass( elem, className );
	elem.className = ( elem.className + " " + className ).trim();
}

/*	Processes errors in stack for group error mode
------------------------------------------- */
fValidate.prototype.showGroupError = function()
{
	for ( var error, firstElem, i = 0; ( error = this.errors[i] ); i++ )
	{
		if ( i == 0 ) firstElem = error.elem;
		this.elem = error.elem;
		this.showError( error.msg, Boolean( i == ( this.errors.length - 1 ) ) );
	}
	var focusElem = ( typeof firstElem.fields != 'undefined' )?
		firstElem.fields[0]:
		firstElem;
	this.selectFocus( focusElem );
}

/*	Reverts any visible error notification upon event
------------------------------------------- */
fValidate.prototype.revertError = function( elem )
{
	elem = this.setArg( elem, this.elem );
	var isHidden	= Boolean( elem.type == 'hidden' ),
		errorClass	= this.config.errorClass,
		i			= 0,
		errorElem,
		subelem;

	if ( ( typeof elem.length != 'undefined' && elem.length > 1 && elem.nodeName != 'SELECT' ) || isHidden )
	{
		if ( isHidden && typeof elem.fields != 'undefined' )
		{		
			while( subelem = ( isHidden ) ? elem.fields[i++] : elem.item( i++ ) )		
			{
				if ( typeof subelem.revertClass != 'undefined' )
				{
					subelem.className = subelem.revertClass;
				}
			}
		}
	} else {
		if ( this.config.useSingleClassNames )
		{
			if ( typeof subElement.revertClass != 'undefined' )
			{
				elem.className = elem.revertClass;
			}
		} else {
			this.removeCSSClass( elem, errorClass );
		}		
	}
	if ( typeof elem.label != 'undefined' )
	{
		if ( this.config.useSingleClassNames )
		{
			elem.label.className = '';
		} else {
			this.removeCSSClass( elem.label, errorClass );
		}
		elem.label.innerHTML = ( elem.label.original || elem.label.innerHTML );
	}
	if ( typeof this.boxError != 'undefined' )
	{
		if ( typeof this.boxError.normalize != 'undefined' ) this.boxError.normalize();
		if ( errorElem = document.getElementById( this.config.boxErrorPrefix + elem.name ) )
		{
			this.boxError.removeChild( errorElem );
		}
		if ( this.boxError.childNodes.length == 0 ) this.boxError.style.display = "none";
	}
}

/*	Focus and select elements, if possible
------------------------------------------- */
fValidate.prototype.selectFocus = function( elem )
{
	if ( typeof elem.select != 'undefined' ) elem.select();
	if ( typeof elem.focus != 'undefined' )  elem.focus();
}

/*	Developer assistance method - shows error if validator/element-type mismatch
------------------------------------------- */
fValidate.prototype.typeMismatch = function()
{
	var pats = {
		'text':		'text|password|textarea',
		'ta':		'textarea',
		'hidden':	'hidden',
		's1':		'select-one',
		'sm':		'select-multiple',
		'select':	'select-one|select-multiple',
		'rg':		'radio',
		'radio':	'radio',
		'cb':		'checkbox',
		'file':		'file'
		};
	var fail		= false,
		expected	= new Array(),
		result = key = type = regex = "";
	for ( var i = 0; i < arguments.length; i++ )
	{
		type	= pats[arguments[i]];
		regex	= new RegExp( type );
		result	+= ( regex.test( this.elem.type ) ) ? "1" : "0";
		key		+= "0";
		expected.push( type );		
	}
	if ( key ^ result == 0 )
	{
		this.devError( [this.elem.fName, this.elem.type, expected.join( "|" ).replace( /\|/g, this.i18n.or )], 'mismatch' );
		this.elem.validated = false;
		return true;
	}
	return false;
}

/*	Returns value(s) of reference element passed
------------------------------------------- */
fValidate.prototype.getValue = function( elem )
{
	switch ( elem.type )
	{
		case 'text' :
		case 'password' :
		case 'textarea' :
		case 'hidden' :
		case 'file' :
			return elem.value;
		case 'radio':
		case 'select-single':
			if ( typeof elem.length == 'undefined' )
			{
				return elem.value;
			} else {
				for ( var i = 0; i < elem.length; i++ )
				{
					choice = ( elem.type == 'radio' ) ? "checked" : "selected";
					if ( elem[i][choice] )
					{
						return elem[i].value;
					}
				}
			}
		case 'select-multiple' :
		case 'checkbox' :
			if ( typeof elem.length == 'undefined' )
			{
				return elem.value
			} else {
				var returnValues = new Array();
				for ( var i = 0; i < elem.length; i++ )
				{
					choice = ( elem.type == 'checkbox' ) ? "checked" : "selected";
					if ( elem[i][choice] )
					{
						returnValues.push( elem[i].value );
					}
				}
				return returnValues;
			}
		default: return null;
	}
}

/*	Generic argument setting method
------------------------------------------- */
fValidate.prototype.setArg = function( arg, def )
{
	return ( typeof arg == 'undefined' || arg == '' || arg == null ) ? def : arg;
}

/*	Blank checker.  Optional string argument for evaluating element other than current
------------------------------------------- */
fValidate.prototype.isBlank = function( el )
{
	var elem = this.form.elements[el] || this.elem;
	return Boolean( /^\s*$/.test( elem.value ) );
}

/*	Translates messages using language file
------------------------------------------- */
fValidate.prototype.translateMessage = function( args, format )
{
	var msg		= ""
	for ( var i = 0; i < format.length; i++ )
	{			
			msg += ( typeof format[i] == 'number' ) ? args[format[i]] : format[i];
	}
	return msg;
}

/*	Throws developer errors
------------------------------------------- */
fValidate.prototype.devError = function( args, which )
{
	if ( typeof args == 'string' )
	{
		which = args;
		args = [];
	}
	which = this.setArg( which, this.type );
	var format = this.i18n.devErrors[which];
	var a = [
		this.i18n.devErrors.lines[0],
		'----------------------------------------------------------------------------------------------',
		this.translateMessage( args, format ),
		'----------------------------------------------------------------------------------------------',
		this.i18n.devErrors.lines[1]
		];
	alert( a.join( "\n" ) );
}

/*	Throws specific developer error
------------------------------------------- */
fValidate.prototype.paramError = function( param, elemName )
{
	elemName = this.setArg( elemName, this.elem.name );
	this.devError( [param, this.type, elemName], 'paramError' );
}
/* Non-fValidate methods *****************************************/

/*	For easy creation of DOM nodes
------------------------------------------- */
document.createHTMLElement = function( elemName, attribs )
{
	if ( typeof document.createElement == 'undefined' ) return;
	var elem = document.createElement( elemName );
	if ( typeof attribs != 'undefined' )
	{
		for ( var i in attribs )
		{
			switch ( true )
			{
				case ( i == 'text' )  : elem.appendChild( document.createTextNode( attribs[i] ) ); break;
				case ( i == 'class' ) : elem.className = attribs[i]; break;
				default : elem.setAttribute( i, '' ); elem[i] = attribs[i];
			}
		}
	}
	return elem;    
}

/*	Trims b items from the beginning of the array, e items from the end
------------------------------------------- */
Array.prototype.reduce = function( b, e )
{
	var a = new Array();
	var count = 0;
	for ( var i = b; i < this.length - e; i++ )
	{
		a[count++] = this[i];
	}
	return a;
}

/*	Returns array as argument-compatible string
------------------------------------------- */
Array.prototype.toArgString = function()
{
	var a = new Array();
	for ( var i = 0; i < this.length; i++ )
	{
		a.push( "'" + this[i] + "'" );
	}	
	return a.toString();
}

/*	Prototype push if missing
------------------------------------------- */
if ( typeof Array.push == 'undefined' )
Array.prototype.push = function()
{
	var arg, i = 0;
	while( arg = arguments[i++] )
	{
		this[this.length] = arg;
	}
	return this.length;
}

/*	Returns last item of the array
------------------------------------------- */
Array.prototype.last = function()
{
	return this[this.length-1];
}

/*	Removes the follow charaters _[] from an elements name for human-reading
------------------------------------------- */
String.prototype.format = function()
{
	return this.replace( /\_/g, " ").replace( /\[|\]/g, "" );
}

/*	Replaces newline characters with XHTML BR tags
------------------------------------------- */
String.prototype.toHTML = function()
{
	return this.replace( /\n/g, "<br />" ).replace( /\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;" );
}

/*	Trims leading and trailing whitespace from string
------------------------------------------- */
String.prototype.trim = function()
{
	return this.replace( /^\s+|\s+$/, "" );
}

/*	Escapes necessary charactes for string-generated regular expressions
------------------------------------------- */
String.prototype.toPattern = function()
{
	return this.replace( /([\.\*\+\{\}\(\)\<\>\^\$\\])/g, "\\$1" );
}

if ( typeof fvalidate == 'undefined' )
{
	var fvalidate = new Object();
}

fvalidate.i18n =
{
	//	Validation errors
	errors:
	{
		blank:		[
			["Please enter ", 0]
			],
		length:		[
			[0, " must be at least ", 1, " characters long"],
			[0, " must be no more than ", 1, " characters long.\nThe current text is ", 2, " characters long."]
			],
		equalto:	[
			[0, " must be equal to ", 1]
			],
		number:		[
			["The number you entered for ", 0, " is not valid"]
			],
		numeric:	[
			["Only numeric values are valid for the ", 0],
			["A minimum of ", 0, " numeric values are required for the ", 1]
			],
		alnum:		[
			["The data you entered, \"", 0, "\", does not match the requested format for ", 1,  
			"\nMinimum Length: ", 2,
			"\nCase: ", 3,
			"\nNumbers allowed: ", 4,
			"\nSpaces allowed: ", 5,
			"\nPunctuation characters allowed: ", 6, "\n"]
			],
		decimal:	[
			["The data you entered,", 0, " is not valid.  Please re-enter the ", 1]
			],
		decimalr:	[
			[0, " is not a valid. Please re-enter."]
			],
		ip:			[
			["Please enter a valid IP"],
			["The port number you specified, ", 0, ",  is out of range.\nIt must be between ", 1, " and ", 2]
			],
		ssn:		[
			["You need to enter a valid Social Security Number.\nYour SSN must be entered in 'XXX-XX-XXXX' format."]
			],
		money:		[
			[0, " does not match the required format of ", 1]
			],
		cc:			[
			["The ", 0, " you entered is not valid. Please check again and re-enter."]
			],
		ccDate:		[
			["You credit card has expired! Please use a different card."]
			],
		zip:		[
			["Please enter a valid 5 or 9 digit Zip code."]
			],
		phone:		[
			["Please enter a valid phone number plus Area Code."],
			["Please enter a valid phone number - seven or ten digits."]
			],
		email:		[
			["Please enter a valid email address"]
			],
		url:		[
			[0, " is not a valid domain"]
			],
		date:		[
			["The data entered for ", 0, " is not a valid date\nPlease enter a date using the following format: ", 1],
			["Date must be before ", 0],
			["Date must be on or before ", 0],
			["Date must be after ", 0],
			["Date must be on or after ", 0]
			],
		select:		[
			["Please select a valid option for ", 0]
			],
		selectm:	[
			["Please select between ", 0, " and ", 1, " options for ", 2, ".\nYou currently have ", 3, " selected"]
			],
		selecti:	[
			["Please select a valid option for ", 0]
			],
		checkbox:	[
			["Please check ", 0, " before continuing"],
			["Please select between ", 0, " and ", 1, " options for ", 2, ".\nYou currently have ", 3, " selected"]
			],
		radio:		[
			["Please check ", 0, " before continuing"],
			["Please select an option for ", 0 ]
			],
		comparison:	[
			[0, " must be ", 1, " ", 2]
			],
		eitheror:	[
			["One and only one of the following fields must be entered:\n\t-", 0, "\n"]
			],
		atleast:	[
			["At least ", 0, " of the following fields must be entered:\n\t-", 1, "\n\nYou have only ", 2, " filled in.\n"]
			],
		allornone:	[
			["All or none of the following fields must be entered and accurate:\n\t-", 0, "\nYou have only ", 1, " accurate field entered.\n"]
			],
		file:		[
			["The file must be one of the following types:\n", 0, "\nNote: File extension may be case-sensitive."]
			],
		custom:		[
			[0, " is invalid."]
			],
		cazip:		[
			["Please enter a valid postal code."]
			],
		ukpost:		[
			["Please enter a valid postcode."]
			],
		germanpost:	[
			["Please enter a valid postcode."]
			],
		swisspost:	[
			["Please enter a valid postcode."]
			]
	},

	comparison:
	{
		gt:		"greater than",
		lt:		"less than",
		gte:	"greater than or equal to",
		lte:	"less than or equal to",
		eq:		"equal to",
		neq:	"not equal to"
	},

	//	Developer assist errors
	devErrors:
	{
		number:		["The lower-bound (", 0, ") is greater than the upper-bound (", 1, ") on this element: ", 2],
		length:		["The minimum length (", 0, ") is greater than the maxiumum legnth (", 1, ") on this element: ", 2],
		cc:			["Credit Card type (", 0, ") not found."],

		lines:		["! WARNING ! -- fValidate developer-assist error\n", "\nIf you are not the developer, please contact the website administrator regarding this error."],
		paramError: ["You must include the '", 0, "' parameter for the '", 1, "' validator type on this field: ", 2],
		notFound:	["The validator '", 0, "' was not found.\nRequested by: ", 1],
		noLabel:	["No element found for label: ", 0],
		noBox:		["An element with the requested id '", 0, "' was not found for the 'boxError' config value."],
		missingName:["The hidden input calling the following logical validator must have a valid name\nattribute when used in conjunction with the 'box' error-type.\n\t", 0],
		mismatch:	["Validator/Element type mismatch.\n\nElement: ", 0, "\nElement type: ", 1, "\nType required by validator: ", 2],
		noCCType:	["You must include a SELECT item with Credit Card type choices!"]
	},

	//	Config values
	config :
	{
		confirmMsg :		"Your data is about to be sent.\nPlease click 'Ok' to proceed or 'Cancel' to abort.",
		confirmAbortMsg :	"Submission cancelled.  Data has not been sent."
	},

	//	Tooltip attached to Box-item errors
	boxToolTip:	"Click to target field",

	//	Message displayed at top of alert error in group mode
	groupAlert:	"The following errors occured:\n\n- ",

	//	Literal translation of the English 'or', include padding spaces.
	or:			" or "
}
/*< blank basic *******************************************************************/
fValidate.prototype.blank = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( this.isBlank() )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< number numbers *******************************************************************/
fValidate.prototype.number = function( type, lb, ub )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var num  = ( type == 0 ) ? parseInt( this.elem.value, 10 ) : parseFloat( this.elem.value );
	lb       = this.setArg( lb, 0 );
	ub       = this.setArg( ub, Number.infinity );
	if ( lb > ub )
	{
		this.devError( [lb, ub, this.elem.name] );
		return;
	}
	var fail = Boolean( isNaN( num ) || num != this.elem.value );
	if ( !fail )
	{
		switch( true )
		{
			case ( lb != false && ub != false ) : fail = !Boolean( lb <= num && num <= ub ); break;
			case ( lb != false ) : fail = Boolean( num < lb ); break;
			case ( ub != false ) : fail = Boolean( num > ub ); break;
		}
	}
	if ( fail )
	{
		this.throwError( [this.elem.fName] );
		return;
	}
	this.elemPass = true;
}
/*/>*/
/*< numeric numbers *******************************************************************/
fValidate.prototype.numeric = function( len )
{
	if ( this.typeMismatch( 'text' ) ) return;
	len = this.setArg( len, '*' );
	var regex = new RegExp( ( len == '*' ) ? "^\\d+$" : "^\\d{" + parseInt( len, 10 ) + "}\\d*$" );
	if ( !regex.test( this.elem.value ) )
	{
		if ( len == "*" )
		{
			this.throwError( [this.elem.fName] );
		} else {
			this.throwError( [len, this.elem.fName], 1 );
		}
	}
}
/*/>*/
/*< length basic *******************************************************************/
fValidate.prototype.length = function( len, maxLen )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var vlen = this.elem.value.length;
	len		= Math.abs( len );
	maxLen	= Math.abs( this.setArg( maxLen, Number.infinity ) );
	if ( len > maxLen )
	{
		this.devError( [len, maxLen, this.elem.name] );
		return;
	}
	if ( len > parseInt( vlen, 10 ) )
	{
		this.throwError( [this.elem.fName, len] );
	}	
	if ( vlen > maxLen )
	{
		this.throwError( [this.elem.fName, maxLen, vlen], 1 );
	}
}
/*/>*/
/*< alnum extended *******************************************************************/
fValidate.prototype.alnum = function( minLen, tCase, numbers, spaces, puncs )
{
	if ( this.typeMismatch( 'text' ) ) return;

	tCase = this.setArg( tCase, "a" );
	
	//alert( [minLen,tCase,numbers,spaces,puncs] );

	numbers = ( numbers == "true" || numbers == "1" );
	spaces = ( spaces == "true" || spaces == "1" );

	//alert( [minLen,tCase,numbers,spaces,puncs] );
		
	var okChars = "",
		arrE	= ['None','Any','No','No','Any'];

	if ( minLen != '*' )
	{
		minLen =  parseInt( minLen, 10 );
		arrE[0] = minLen;
	} else {
		minLen = 0;
	}

	switch( tCase.toUpperCase() )
	{
		case 'U':
			okChars += 'A-Z';
			arrE[1] =  'UPPER';
			break;
		case 'L':
			okChars += 'a-z';
			arrE[1] =  'lower';
			break;
		case 'C':
			okChars += 'A-Z][a-z';
			arrE[1] =  'Intial capital';
			minLen--;
			break;
		default:
			okChars += 'a-zA-Z';
			break;		
	}

	if ( numbers == true )
	{
		okChars += '0-9';
		arrE[2] =  'Yes';
	}
	if ( spaces == true )
	{
		okChars += ' ';
		arrE[3] =  'Yes';
	}
	if ( puncs == "any" )
	{
		arrE[4]  = "Any";
	}
	else if ( puncs == "none" )
	{
		arrE[4] = "None";
	}
	else 
	{
		puncs = puncs.replace( /pipe/g, "|" );
		okChars += puncs;
		arrE[4] =  puncs; //.toPattern().replace( /\\/g, "" );
	}
	var length = ( minLen != "*" )?
		"{" + minLen + ",}":
		"+";
	var regex = ( puncs == "any" ) ?
		new RegExp( "^([" + okChars + "]|[^a-zA-Z0-9\\s])" + length + "$" ):
		new RegExp( "^[" + okChars + "]" + length + "$" );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.value, this.elem.fName, arrE[0], arrE[1], arrE[2], arrE[3], arrE[4]] );
	}
}
/*/>*/
/*< equalto logical *******************************************************************/
fValidate.prototype.equalto = function( oName )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof oName == 'undefined' )
	{
		this.paramError( 'oName' );
	}
	var otherElem = this.form.elements[oName];
	if ( this.elem.value != otherElem.value )
	{
		this.throwError( [this.elem.fName,otherElem.fName] );			
	}
}
/*/>*/
/*< ssn extended *******************************************************************/
fValidate.prototype.ssn = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( !( /^\d{3}\-\d{2}\-\d{4}$/.test( this.elem.value ) ) )
		this.throwError();
}
/*/>*/
/*< select controls *******************************************************************/
fValidate.prototype.select = function()
{
	if ( this.typeMismatch( 's1' ) ) return;
	if ( this.elem.selectedIndex == 0 )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< selectm controls *******************************************************************/
fValidate.prototype.selectm = function( minS, maxS )
{
	if ( this.typeMismatch( 'sm' ) ) return;
	if ( typeof minS == 'undefined' )
	{
		this.paramError( 'minS' );
	}
	if ( maxS == 999 || maxS == '*' || typeof maxS == 'undefined' || maxS > this.elem.length ) maxS = this.elem.length;

	var count = 0;	
	for ( var opt, i = 0; ( opt = this.elem.options[i] ); i++ )
	{
		if ( opt.selected ) count++;
	}

	if ( count < minS || count > maxS )
	{
		this.throwError( [minS, maxS, this.elem.fName, count] );
	}
}
/*/>*/
/*< selecti controls *******************************************************************/
fValidate.prototype.selecti = function( indexes )
{
	
	if ( this.typeMismatch( 's1' ) ) return;
	if ( typeof indexes == 'undefined' )
	{
		this.paramError( 'indexes' );
		return;
	}
	indexes = indexes.split( "," );
	var selectOK = true;

	for ( var i = 0; i < indexes.length; i++ )
	{
		if ( this.elem.options[indexes[i]].selected )
		{
			selectOK = false;
			break;
		}
	}
	if ( !selectOK )
	{
		this.throwError( [this.elem.fName] );
	}
}
/*/>*/
/*< cazip international *******************************************************************/
fValidate.prototype.cazip = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z][0-9][A-Z] [0-9][A-Z][0-9]$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
fValidate.prototype.capost = fValidate.prototype.cazip;
/*/>*/
/*< ukpost international *******************************************************************/
fValidate.prototype.ukpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^[A-Z]{1,2}\d[\dA-Z] ?\d[A-Z]{2}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< germanpost international *******************************************************************/
fValidate.prototype.germanpost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:CH\-)\d{4}$/.test( elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< swisspost international *******************************************************************/
fValidate.prototype.swisspost = function()
{
	var elem = this.elem;
	if ( this.typeMismatch( 'text' ) ) return;
	elem.value = elem.value.toUpperCase();
	if ( !( /^(?:D\-)\d{5}$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< email web *******************************************************************/
fValidate.prototype.email = function( level )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof level == 'undefined' ) level = 0;
	var emailPatterns = [
		/.+@.+\..+$/i,
		/^\w.+@\w.+\.[a-z]+$/i,
		/^\w[-_a-z~.]+@\w[-_a-z~.]+\.[a-z]{2}[a-z]*$/i,
		/^\w[\w\d]+(\.[\w\d]+)*@\w[\w\d]+(\.[\w\d]+)*\.[a-z]{2,7}$/i
		];
	if ( ! emailPatterns[level].test( this.elem.value ) )
	{
		this.throwError();
	}	
}	
/*/>*/
/*< url web *******************************************************************/
fValidate.prototype.url = function( hosts, hostOptional, allowQS )
{
	if ( this.typeMismatch( 'text' ) ) return;

	this.setArg( hosts, "http" );
	
	var front = "^(?:(" + hosts.replace( /\,/g, "|" ) + ")\\:\\/\\/)";
	var end   = ( Boolean( allowQS ) == true ) ? "(\\?.*)?$" : "$";

	if ( Boolean( hostOptional ) == true ) front += "?";
	var regex = new RegExp( front + "([\\w\\d-]+\\.?)+" + end );
	
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
}	
/*/>*/
/*< ip web *******************************************************************/
fValidate.prototype.ip = function( portMin, portMax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	portMin = this.setArg( portMin, 0 );
	portMax = this.setArg( portMax, 99999 );
	if ( !( /^\d{1,3}(\.\d{1,3}){3}(:\d+)?$/.test( this.elem.value ) ) )
	{
		this.throwError();
	}
	else
	{
		var part, i = 0, parts = this.elem.value.split( /[.:]/ );
		while ( part = parts[i++] )
		{
			if ( i == 5 ) // Check port
			{
				if ( part < portMin || part > portMax )
				{
					this.throwError( [part, portMin, portMax], 1 );
				}
			}
			else if ( part < 0 || part > 255 )
			{
				this.throwError();
			}
		}
	}
}
/*/>*/
/*< decimal numbers *******************************************************************/
fValidate.prototype.decimal = function( lval, rval )
{
	if ( this.typeMismatch( 'text' ) ) return;
	var regex = '', elem = this.elem;
	if ( lval != '*' ) lval = parseInt( lval, 10 );
	if ( rval != '*' ) rval = parseInt( rval, 10 );
	
	if ( lval == 0 )
		regex = "^\\.[0-9]{" + rval + "}$";	
	else if ( lval == '*' )
		regex = "^[0-9]*\\.[0-9]{" + rval + "}$";
	else if ( rval == '*' )
		regex = "^[0-9]{" + lval + "}\\.[0-9]+$";
	else
		regex = "^[0-9]{" + lval + "}\\.[0-9]{" + rval + "}$";
		
	regex = new RegExp( regex );

	if ( !regex.test( elem.value ) )
	{
		this.throwError( [elem.value,elem.fName] );
	}	
}
/*/>*/
/*< decimalr numbers *******************************************************************/
fValidate.prototype.decimalr = function( lmin, lmax, rmin, rmax )
{
	if ( this.typeMismatch( 'text' ) ) return;
	lmin = ( lmin == '*' )? 0 : parseInt( lmin, 10 );
	lmax = ( lmax == '*' )? '': parseInt( lmax, 10 );
	rmin = ( rmin == '*' )? 0 : parseInt( rmin, 10 );
	rmax = ( rmax == '*' )? '': parseInt( rmax, 10 );
	var	decReg = "^[0-9]{"+lmin+","+lmax+"}\\.[0-9]{"+rmin+","+rmax+"}$"
	var regex = new RegExp(decReg);
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}
	return true;
}
/*/>*/
/*< zip extended *******************************************************************/
fValidate.prototype.zip = function( sep )
{
	if ( this.typeMismatch( 'text' ) ) return;
	sep = this.setArg( sep, "- " );
	var regex = new RegExp( "^[0-9]{5}(|[" + sep.toPattern() + "][0-9]{4})?$" );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError();
	}
}
/*/>*/
/*< phone extended *******************************************************************/
fValidate.prototype.phone = function( format )
{
	if ( this.typeMismatch( 'text' ) ) return;
	format       = this.setArg( format, 0 );
	var patterns = [
		/^(\(?\d\d\d\)?)?[ -]?\d\d\d[ -]?\d\d\d\d$/,	//	loose
		/^(\(\d\d\d\) )?\d\d\d[ -]\d\d\d\d$/			//	strict
		];
	if ( !patterns[format].test( this.elem.value ) )
	{
		if ( format == 1 )
		{
			this.throwError();
		} else {
			this.throwError( [], 1 );
		}
	}
}
/*/>*/
/*< date datetime *******************************************************************/
fValidate.prototype.date = function( formatStr, delim, code, specDate )
{
	if ( this.typeMismatch( 'text' ) ) return;
	if ( typeof formatStr == 'undefined' )
	{
		this.paramError( 'formatStr' );
		return;
	}

	delim = this.setArg( delim, "/" );

	var error	= [this.elem.fName, formatStr.replace( /\//g, delim )];
	var format  = formatStr.split( "/" );
	var compare = this.elem.value.split( delim );
	var order   = new Object();
	
	for ( var i = 0; i < format.length; i++ )
	{
		switch( format[i].charAt( 0 ).toLowerCase() )
		{
			case 'm' :
				order.months = i;
				break;
			case 'd' :
				order.days = i;
				break;
			case 'y' :
				order.years = i;
				break;
		}
	}
	var thisDate = new Date( compare[order.years], compare[order.months]-1, compare[order.days] );
	
	if ( isNaN( thisDate ) || thisDate.getDate() != compare[order.days] || thisDate.getMonth() != compare[order.months]-1 || thisDate.getFullYear().toString().length != formatStr.match( /y/g ).length )
	{
		this.throwError( error );
		return;
	}
	
	var compareElem = this.form.elements[specDate];
	if ( typeof compareElem != 'undefined' )
	{
		specDate = compareElem.validDate || compareElem.value;
	}
	var compareDate = ( specDate == 'today' )?
		new Date():
		new Date( specDate );
	compareDate.setHours(0);
	compareDate.setMinutes(0);
	compareDate.setSeconds(0);
	compareDate.setMilliseconds(0);
	
	var timeDiff = compareDate.getTime() - thisDate.getTime();
	var dateOk   = false;
	
	switch ( parseInt( code ) ) {
		case 1 :	// Before specDate
			dateOk	= Boolean( timeDiff > 0 );
			error	= 1;
			break;
		case 2 :	// Before or on specDate
			dateOk	= Boolean( ( timeDiff + 86400000 ) > 0 );
			error	= 2;
			break;
		case 3 :	// After specDate
			dateOk	= Boolean( timeDiff < 0 );
			error	= 3;
			break;
		case 4 :	// After or on specDate
			dateOk	= Boolean( ( timeDiff - 86400000 ) < 0 );
			error	= 4;
			break;
		default : dateOk = true;
		}
	if ( !dateOk )
	{
		this.throwError( [specDate], error );
	}
	this.elem.validDate = thisDate.toString();
}	
/*/>*/
/*< money ecommerce *******************************************************************/
fValidate.prototype.money = function( ds, grp, dml )
{
	if ( this.typeMismatch( 'text' ) ) return;
	
	ds  = ( ds == ' ' )  ? false : ds.toPattern();
	grp = ( grp == ' ' ) ? false : grp.toPattern();
	dml = ( dml == ' ' ) ? false : dml.toPattern();
	
	var moneySyntax, pattern;
	
	switch( true )
	{
		case Boolean( ds && grp && dml ):		// Dollar sign, grouping, and decimal
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})$";
			moneySyntax = ds + "XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && grp && !dml ):		// Dollar sign and grouping
			pattern		= "^" + ds + "(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax = "" + ds + "XX" + grp + "XXX";
			break;
		case Boolean( ds && !grp && dml ):		// Dollar sign and decimal
			pattern		="^" + ds + "[0-9]*(\\.[0-9]{2})$";
			moneySyntax ="" + ds + "XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && grp && dml ):		// Grouping and decimal
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})(" + dml + "[0-9]{2})?$";
			moneySyntax ="XX" + grp + "XXX" + dml + "XX";
			break;
		case Boolean( ds && !grp && !dml ):		// Dollar sign only
			pattern		="^" + ds + "[0-9]*$";
			moneySyntax ="" + ds + "XXXXX";
			break;
		case Boolean( !ds && grp && !dml ):		// Grouping only
			pattern		="^(?:(?:[0-9]{1,3}" + grp + ")(?:[0-9]{3}" + grp + ")*[0-9]{3}|[0-9]{1,3})$";
			moneySyntax ="XX" + grp + "XXX";
			break;
		case Boolean( !ds && !grp && dml ):		// Decimal only
			pattern		="^[0-9]*(" + dml + "[0-9]{2})$";
			moneySyntax ="XXXXX" + dml + "XX";
			break;
		case Boolean( !ds && !grp && !dml ):	// No params set, all special chars become optional
			pattern		="^.?(?:(?:[0-9]{1,3}.?)(?:[0-9]{3}.?)*[0-9]{3}|[0-9]{1,3})(.[0-9]{2})?$";
			moneySyntax ="[?]XX[?]XXX[?XX]";
	}
			
	var regex = new RegExp( pattern );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName, moneySyntax.replace( /\\/g, '' )] );
	}
}
/*/>*/
/*< checkbox controls *******************************************************************/
fValidate.prototype.checkbox = function( minC, maxC )
{
	if ( this.typeMismatch( 'cb' ) ) return;
	if ( typeof minC == 'undefined' )
	{
		this.paramError( 'minC' );
		return;
	}
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		var len   = this.elem.length;
		var count = 0;
		
		if ( maxC == 999 || maxC == '*' || typeof maxC == 'undefined' || maxC > this.elem.length )
		{
			maxC == len;
		}
		var i = len;
		while( i-- > 0 )
		{
			if ( this.elem[i].checked )
			{
				count++;
			}
		}
		if ( count < minC || count > maxC )
		{
			this.throwError( [minC, maxC, this.elem[0].fName, count] );
		}			
	}
}
/*/>*/
/*< radio controls *******************************************************************/
fValidate.prototype.radio = function()
{
	if ( this.typeMismatch( 'rg' ) ) return;
	if ( this.elem == this.form.elements[this.elem.name] && !this.elem.checked )
	{
		this.throwError( [this.elem.fName] );
	}
	else
	{
		this.elem = this.form.elements[this.elem.name];
		
		for ( var i = 0; i < this.elem.length; i++ )
		{
			if ( this.elem.item( i ).checked )
			{
				return;
			}
		}
		this.throwError( [this.elem[0].fName] );
	}
}
/*/>*/
/*< eitheror logical *******************************************************************/
fValidate.prototype.eitheror = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,		
		args    = arguments[1].split( arguments[0] );		

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount != 1 )
	{
		this.throwError( [fields.join( "\n\t-" )] );
	}
}
/*/>*/
/*< atleast logical *******************************************************************/
fValidate.prototype.atleast = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == undefined )
	{
		this.paramError( 'qty' );
		return;
	}
	if ( typeof arguments[1] == undefined )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[2] == undefined )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[2].split( arguments[1] );

	this.elem.fields = new Array();
	
	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount < arguments[0] )
	{
		this.throwError( [arguments[0], fields.join( "\n\t-" ), nbCount] );
	}
}
/*/>*/
/*< allornone logical *******************************************************************/
fValidate.prototype.allornone = function()
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	if ( typeof arguments[0] == 'undefined' )
	{
		this.paramError( 'delim' );
		return;
	}
	if ( typeof arguments[1] == 'undefined' )
	{
		this.paramError( 'fields' );
		return;
	}
	var arg, i  = 0,
		fields  = new Array(),
		field,
		nbCount = 0,
		args    = arguments[1].split( arguments[0] );
	
	this.elem.fields = new Array();

	while ( arg = args[i++] )
	{
		field = this.form.elements[arg];
		fields.push( field.fName );
		this.elem.fields.push( field );

		if ( !this.isBlank( arg ) )
		{
			nbCount++;
		}
	}
	if ( nbCount > 0 && nbCount < args.length )
	{
		this.throwError( [fields.join( "\n\t-" ), nbCount] );
	}
}
/*/>*/
/*< comparison logical *******************************************************************/
fValidate.prototype.comparison = function( field1, operator, field2 )
{
	if ( this.typeMismatch( 'hidden' ) ) return;
	var elem1	= this.form.elements[field1],
		elem2	= this.form.elements[field2],
		value1	= this.getValue( elem1 ),
		value2	= this.getValue( elem2 );
		i18n	= this.i18n.comparison;
		i		= -1;
	
	var operators =
	[
		['>',	i18n.gt],
		['<',	i18n.lt],
		['>=',	i18n.gte],
		['<=',	i18n.lte],
		['==',	i18n.eq],
		['!=',	i18n.neq]
	];
	while( operators[++i][0] != operator ){ }
	this.elem.fields = [elem1, elem2];
	if ( ! eval( value1 + operator + value2 ) )
	{
		this.throwError( [elem1.fName, operators[i][1], elem2.fName] );
	}
}
/*/>*/
/*< file controls *******************************************************************/
fValidate.prototype.file = function( extensions, cSens )
{
	if ( this.typeMismatch( 'file' ) ) return;
	if ( typeof extensions == 'undefined' )
	{
		this.paramError( 'extensions' );
		return;
	}
	cSens = Boolean( cSens ) ? "" : "i";
	var regex = new RegExp( "^.+\\.(" + extensions.replace( /,/g, "|" ) + ")$", cSens );
	if ( ! regex.test( this.elem.value ) )
	{
		this.throwError( [extensions.replace( /,/g, "\n" )] );
	}
}
/*/>*/
/*< custom special *******************************************************************/
fValidate.prototype.custom = function( flags, reverseTest )
{
	if ( this.typeMismatch( 'text' ) ) return;
	flags     = ( flags ) ? flags.replace( /[^gim]/ig ) : "";
	var regex = new RegExp( this.elem.getAttribute( this.config.pattern ), flags );
	if ( !regex.test( this.elem.value ) )
	{
		this.throwError( [this.elem.fName] );
	}	
}
/*/>*/
/*< cc ecommerce *******************************************************************/
fValidate.prototype.cc = function()
{
	if ( this.typeMismatch( 'text' ) ) return;
	var typeElem = this.form.elements[this.config.ccType];

	if ( !typeElem )
	{
		this.devError( 'noCCType' )
		return;
	}
	var ccType   = typeElem.options[typeElem.selectedIndex].value.toUpperCase();

	var types    = {
		'VISA'    : /^4\d{12}(\d{3})?$/,
		'MC'      : /^5[1-5]\d{14}$/,
		'DISC'    : /^6011\d{12}$/,
		'AMEX'    : /^3[4|7]\d{13}$/,        
		'DINERS'  : /^3[0|6|8]\d{12}$/,
		'ENROUTE' : /^2[014|149]\d{11}$/,
		'JCB'     : /^3[088|096|112|158|337|528]\d{12}$/,
		'SWITCH'  : /^(49030[2-9]|49033[5-9]|49110[1-2]|4911(7[4-9]|8[1-2])|4936[0-9]{2}|564182|6333[0-4][0-9]|6759[0-9]{2})\d{10}(\d{2,3})?$/,
		'DELTA'   : /^4(1373[3-7]|462[0-9]{2}|5397[8|9]|54313|5443[2-5]|54742|567(2[5-9]|3[0-9]|4[0-5])|658[3-7][0-9]|659(0[1-9]|[1-4][0-9]|50)|844[09|10]|909[6-7][0-9]|9218[1|2]|98824)\d{10}$/,
		'SOLO'    : /^(6334[5-9][0-9]|6767[0-9]{2})\d{10}(\d{2,3})?$/
		};
	if ( typeElem.validated == false && this.groupError == true ) return;
	if ( typeof types[ccType] == 'undefined' && typeElem.validated == false && this.groupError == false )
	{
		this.devError( [ccType] );
		return;
	}
	this.elem.value = this.elem.value.replace( /[^\d]/g, "" );
	if ( !types[ccType].test( this.elem.value ) || !this.elem.value.luhn() )
	{
		this.throwError( [this.elem.fName] );
	}
}

String.prototype.luhn = function()
{
	var i = this.length;
	var checkSum = "", digit;
	while ( digit = this.charAt( --i ) )
	{
		checkSum += ( i % 2 == 0 ) ? digit * 2 : digit;
	}
	checkSum = eval( checkSum.split('').join('+') );
	return ( checkSum % 10 == 0 );
}
/*/>*/
/*< ccDate ecommerce *******************************************************************/
fValidate.prototype.ccDate = function( month, year )
{
	if ( this.typeMismatch( 's1' ) ) return;
	year	= parseInt( this.getValue( this.form.elements[year] ), 10 ) + 2000;
	month	= parseInt( this.getValue( this.form.elements[month] ), 10 );

	var today	= new Date();
	var expDate = new Date( year, month )

	if ( expDate < today )
	{
		alert( ["Card Expired",today,expDate].join( "\n" ) );
	}
}


var dragapproved=false
var minrestore=0
var initialwidth,initialheight
var ie5=document.all&&document.getElementById
var ns6=document.getElementById&&!document.all

function iecompattest(){
return (!window.opera && document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

function drag_drop(e){
if (ie5&&dragapproved&&event.button==1){
document.getElementById("dwindow").style.left=tempx+event.clientX-offsetx+"px"
document.getElementById("dwindow").style.top=tempy+event.clientY-offsety+"px"
}
else if (ns6&&dragapproved){
document.getElementById("dwindow").style.left=tempx+e.clientX-offsetx+"px"
document.getElementById("dwindow").style.top=tempy+e.clientY-offsety+"px"
}
}

function initializedrag(e){
offsetx=ie5? event.clientX : e.clientX
offsety=ie5? event.clientY : e.clientY
document.getElementById("dwindowcontent").style.display="none" //extra
tempx=parseInt(document.getElementById("dwindow").style.left)
tempy=parseInt(document.getElementById("dwindow").style.top)

dragapproved=true
document.getElementById("dwindow").onmousemove=drag_drop
}

function loadwindow(url,width,height){
if (!ie5&&!ns6)
window.open(url,"","width=width,height=height,scrollbars=1")
else{
document.getElementById("dwindow").style.display=''
document.getElementById("dwindow").style.width=initialwidth=width+"px"
document.getElementById("dwindow").style.height=initialheight=height+"px"
document.getElementById("dwindow").style.left="30px"
document.getElementById("dwindow").style.top=ns6? window.pageYOffset*1+30+"px" : iecompattest().scrollTop*1+30+"px"
document.getElementById("cframe").src=url
}
}

function maximize(){
if (minrestore==0){
minrestore=1 //maximize window
document.getElementById("maxname").setAttribute("src","../system/client_images/icon_restore.gif")
document.getElementById("dwindow").style.width=ns6? window.innerWidth-20+"px" : iecompattest().clientWidth+"px"
document.getElementById("dwindow").style.height=ns6? window.innerHeight-20+"px" : iecompattest().clientHeight+"px"
}
else{
minrestore=0 //restore window
document.getElementById("maxname").setAttribute("src","../system/client_images/icon_max.gif")
document.getElementById("dwindow").style.width=initialwidth
document.getElementById("dwindow").style.height=initialheight
}
document.getElementById("dwindow").style.left=ns6? window.pageXOffset+"px" : iecompattest().scrollLeft+"px"
document.getElementById("dwindow").style.top=ns6? window.pageYOffset+"px" : iecompattest().scrollTop+"px"
}

function closeit(){
document.getElementById("dwindow").style.display="none"
}

function stopdrag(){
dragapproved=false;
document.getElementById("dwindow").onmousemove=null;
document.getElementById("dwindowcontent").style.display="" //extra
}

// Functions for tabs
function hasSupport() {

	if (typeof hasSupport.support != "undefined")
		return hasSupport.support;
	
	var ie55 = /msie 5\.[56789]/i.test( navigator.userAgent );
	
	hasSupport.support = ( typeof document.implementation != "undefined" &&
			document.implementation.hasFeature( "html", "1.0" ) || ie55 )
			
	// IE55 has a serious DOM1 bug... Patch it!
	if ( ie55 ) {
		document._getElementsByTagName = document.getElementsByTagName;
		document.getElementsByTagName = function ( sTagName ) {
			if ( sTagName == "*" )
				return document.all;
			else
				return document._getElementsByTagName( sTagName );
		};
	}

	return hasSupport.support;
}

function WebFXTabPane( el, bUseCookie ) {
	if ( !hasSupport() || el == null ) return;
	
	this.element = el;
	this.element.tabPane = this;
	this.pages = [];
	this.selectedIndex = null;
	this.useCookie = bUseCookie != null ? bUseCookie : true;
	
	// add class name tag to class name
	this.element.className = this.classNameTag + " " + this.element.className;
	
	// add tab row
	this.tabRow = document.createElement( "div" );
	this.tabRow.className = "tab-row";
	el.insertBefore( this.tabRow, el.firstChild );

	var tabIndex = 0;
	if ( this.useCookie ) {
		tabIndex = Number( WebFXTabPane.getCookie( "webfxtab_" + this.element.id ) );
		if ( isNaN( tabIndex ) )
			tabIndex = 0;
	}
	this.selectedIndex = tabIndex;
	
	// loop through child nodes and add them
	var cs = el.childNodes;
	var n;
	for (var i = 0; i < cs.length; i++) {
		if (cs[i].nodeType == 1 && cs[i].className == "tab-page") {
			this.addTabPage( cs[i] );
		}
	}
}

WebFXTabPane.prototype = {

	classNameTag:		"dynamic-tab-pane-control",

	setSelectedIndex:	function ( n ) {
		if (this.selectedIndex != n) {
			if (this.selectedIndex != null && this.pages[ this.selectedIndex ] != null )
				this.pages[ this.selectedIndex ].hide();
			this.selectedIndex = n;
			this.pages[ this.selectedIndex ].show();
			
			if ( this.useCookie )
				WebFXTabPane.setCookie( "webfxtab_" + this.element.id, n );	// session cookie
		}
	},
	
	getSelectedIndex:	function () {
		return this.selectedIndex;
	},
	
	addTabPage:	function ( oElement ) {
		if ( !hasSupport() ) return;
		
		if ( oElement.tabPage == this )	// already added
			return oElement.tabPage;
	
		var n = this.pages.length;
		var tp = this.pages[n] = new WebFXTabPage( oElement, this, n );
		tp.tabPane = this;
		
		// move the tab out of the box
		this.tabRow.appendChild( tp.tab );
				
		if ( n == this.selectedIndex )
			tp.show();
		else
			tp.hide();
			
		return tp;
	}	
};

// Cookie handling
WebFXTabPane.setCookie = function ( sName, sValue, nDays ) {
	var expires = "";
	if ( nDays ) {
		var d = new Date();
		d.setTime( d.getTime() + nDays * 24 * 60 * 60 * 1000 );
		expires = "; expires=" + d.toGMTString();
	}

	document.cookie = sName + "=" + sValue + expires + "; path=/";
};

WebFXTabPane.getCookie = function (sName) {
	var re = new RegExp( "(\;|^)[^;]*(" + sName + ")\=([^;]*)(;|$)" );
	var res = re.exec( document.cookie );
	return res != null ? res[3] : null;
};

WebFXTabPane.removeCookie = function ( name ) {
	setCookie( name, "", -1 );
};

function WebFXTabPage( el, tabPane, nIndex ) {
	if ( !hasSupport() || el == null ) return;
	
	this.element = el;
	this.element.tabPage = this;
	this.index = nIndex;
	
	var cs = el.childNodes;
	for (var i = 0; i < cs.length; i++) {
		if (cs[i].nodeType == 1 && cs[i].className == "tab") {
			this.tab = cs[i];
			break;
		}
	}
	
	// insert a tag around content to support keyboard navigation
	var a = document.createElement( "A" );
	a.href = "javascript:void 0;";
	while ( this.tab.hasChildNodes() )
		a.appendChild( this.tab.firstChild );
	this.tab.appendChild( a );
	
	// hook up events, using DOM0
	var oThis = this;
	this.tab.onclick = function () { oThis.select(); };
	this.tab.onmouseover = function () { WebFXTabPage.tabOver( oThis ); };
	this.tab.onmouseout = function () { WebFXTabPage.tabOut( oThis ); };
}

WebFXTabPage.prototype = {
	show:	function () {
		var el = this.tab;
		var s = el.className + " selected";
		s = s.replace(/ +/g, " ");
		el.className = s;
		
		this.element.style.display = "block";
	},

	hide:	function () {
		var el = this.tab;
		var s = el.className;
		s = s.replace(/ selected/g, "");
		el.className = s;

		this.element.style.display = "none";
	},
	
	select:	function () {
		this.tabPane.setSelectedIndex( this.index );
	}
};

WebFXTabPage.tabOver = function ( tabpage ) {
	var el = tabpage.tab;
	var s = el.className + " hover";
	s = s.replace(/ +/g, " ");
	el.className = s;
};

WebFXTabPage.tabOut = function ( tabpage ) {
	var el = tabpage.tab;
	var s = el.className;
	s = s.replace(/ hover/g, "");
	el.className = s;
};


// This function initializes all uninitialized tab panes and tab pages
function setupAllTabs() {
	if ( !hasSupport() ) return;

	var all = document.getElementsByTagName( "*" );
	var l = all.length;
	var tabPaneRe = /tab\-pane/;
	var tabPageRe = /tab\-page/;
	var cn, el;
	var parentTabPane;
	
	for ( var i = 0; i < l; i++ ) {
		el = all[i]
		cn = el.className;

		// no className
		if ( cn == "" ) continue;
		
		// uninitiated tab pane
		if ( tabPaneRe.test( cn ) && !el.tabPane )
			new WebFXTabPane( el );
	
		// unitiated tab page wit a valid tab pane parent
		else if ( tabPageRe.test( cn ) && !el.tabPage &&
					tabPaneRe.test( el.parentNode.className ) ) {
			el.parentNode.tabPane.addTabPage( el );			
		}
	}
}


// initialization hook up

// DOM2
if ( typeof window.addEventListener != "undefined" )
	window.addEventListener( "load", setupAllTabs, false );

// IE 
else if ( typeof window.attachEvent != "undefined" )
	window.attachEvent( "onload", setupAllTabs );

else {
	if ( window.onload != null ) {
		var oldOnload = window.onload;
		window.onload = function ( e ) {
			oldOnload( e );
			setupAllTabs();
		};
	}
	else 
		window.onload = setupAllTabs;
}

/**
* Function to create copies of objects which are
* normally passed around by references (Arrays for example)
*/
function arrayCopy(input)
{
	var output = new Array(input.length);

	for (i in input) {
		if (typeof(input[i]) == 'array') {
			output[i] = arrayCopy(input[i]);
		} else {
			output[i] = input[i];
		}
	}

	return output;
}

/**
* TreeMenu class
*/
	function TreeMenu(iconpath, myname, linkTarget, defaultClass, usePersistence, noTopLevelImages)
	{
		// Properties
		this.iconpath         = iconpath;
		this.myname           = myname;
		this.linkTarget       = linkTarget;
		this.defaultClass     = defaultClass;
		this.usePersistence   = usePersistence;
		this.noTopLevelImages = noTopLevelImages;
		this.n                = new Array();
		this.output           = '';

		this.nodeRefs       = new Array();
		this.branches       = new Array();
		this.branchStatus   = new Array();
		this.layerRelations = new Array();
		this.childParents   = new Array();
		this.cookieStatuses = new Array();

		this.preloadImages();
	}

/**
* Adds a node to the tree
*/
	TreeMenu.prototype.addItem = function (newNode)
	{
		newIndex = this.n.length;
		this.n[newIndex] = newNode;
		
		return this.n[newIndex];
	}

/**
* Preload images hack for Mozilla
*/
	TreeMenu.prototype.preloadImages = function ()
	{
		var plustop    = new Image; plustop.src    = this.iconpath + '/plustop.gif';
		var plusbottom = new Image; plusbottom.src = this.iconpath + '/plusbottom.gif';
		var plus       = new Image; plus.src       = this.iconpath + '/plus.gif';
	
		var minustop    = new Image; minustop.src    = this.iconpath + '/minustop.gif';
		var minusbottom = new Image; minusbottom.src = this.iconpath + '/minusbottom.gif';
		var minus       = new Image; minus.src       = this.iconpath + '/minus.gif';
	
		var branchtop    = new Image; branchtop.src    = this.iconpath + '/branchtop.gif';
		var branchbottom = new Image; branchbottom.src = this.iconpath + '/branchbottom.gif';
		var branch       = new Image; branch.src       = this.iconpath + '/branch.gif';
	
		var linebottom = new Image; linebottom.src = this.iconpath + '/linebottom.gif';
		var line       = new Image; line.src       = this.iconpath + '/line.gif';
	}

/**
* Main function that draws the menu and assigns it
* to the layer (or document.write()s it)
*/
	TreeMenu.prototype.drawMenu = function ()// OPTIONAL ARGS: nodes = [], level = [], prepend = '', expanded = false, visbility = 'inline', parentLayerID = null
	{
		/**
	    * Necessary variables
	    */
		var output        = '';
		var modifier      = '';
		var layerID       = '';
		var parentLayerID = '';
	
		/**
	    * Parse any optional arguments
	    */
		var nodes         = arguments[0] ? arguments[0] : this.n
		var level         = arguments[1] ? arguments[1] : [];
		var prepend       = arguments[2] ? arguments[2] : '';
		var expanded      = arguments[3] ? arguments[3] : false;
		var visibility    = arguments[4] ? arguments[4] : 'inline';
		var parentLayerID = arguments[5] ? arguments[5] : null;

		var currentlevel  = level.length;

		for (var i=0; i<nodes.length; i++) {
		
			level[currentlevel] = i+1;
			layerID = this.myname + '_' + 'node_' + this.implode('_', level);

			/**
            * Store this object in the nodeRefs array
            */
			this.nodeRefs[layerID] = nodes[i];

			/**
	        * Store the child/parent relationship
	        */
			this.childParents[layerID] = parentLayerID;
	
			/**
	        * Gif modifier
	        */
			if (i == 0 && parentLayerID == null) {
				modifier = nodes.length > 1 ? "top" : 'single';
			} else if(i == (nodes.length-1)) {
				modifier = "bottom";
			} else {
				modifier = "";
			}
	
			/**
	        * Single root branch is always expanded
	        */
			if (!this.doesMenu() || (parentLayerID == null && (nodes.length == 1 || this.noTopLevelImages))) {
				expanded = true;
	
			} else if (nodes[i].expanded) {
				expanded = true;
	
			} else {
				expanded = false;
			}
	
			/**
	        * Make sure visibility is correct based on parent status
	        */
			visibility =  this.checkParentVisibility(layerID) ? visibility : 'none';

			/**
	        * Setup branch status and build an indexed array
			* of branch layer ids
	        */
			if (nodes[i].n.length > 0) {
				this.branchStatus[layerID] = expanded;
				this.branches[this.branches.length] = layerID;
			}
	
			/**
	        * Setup toggle relationship
	        */
			if (!this.layerRelations[parentLayerID]) {
				this.layerRelations[parentLayerID] = new Array();
			}
			this.layerRelations[parentLayerID][this.layerRelations[parentLayerID].length] = layerID;
	
			/**
	        * Branch images
	        */
			var gifname  = nodes[i].n.length && this.doesMenu() && nodes[i].isDynamic ? (expanded ? 'minus' : 'plus') : 'branch';
			var iconName = expanded && nodes[i].expandedIcon ? nodes[i].expandedIcon : nodes[i].icon;
			var iconimg  = nodes[i].icon ? this.stringFormat('<img src="{0}/{1}" width="20" height="20" align="top" id="icon_{2}">', this.iconpath, iconName, layerID) : '';
			
			/**
			* Add event handlers
			*/
			var eventHandlers = "";
			for (j in nodes[i].events) {
				eventHandlers += this.stringFormat('{0}="{1}" ', j, nodes[i].events[j]);
			}

			/**
	        * Build the html to write to the document
			* IMPORTANT:
			* document.write()ing the string: '<div style="display:...' will screw up nn4.x
	        */
			var layerTag  = this.doesMenu() ? this.stringFormat('<div id="{0}" style="display: {1}" class="{2}">', layerID, visibility, (nodes[i].cssClass ? nodes[i].cssClass : this.defaultClass)) : this.stringFormat('<div class="{0}">', nodes[i].cssClass ? nodes[i].cssClass : this.defaultClass);
			var onMDown   = this.doesMenu() && nodes[i].n.length  && nodes[i].isDynamic ? this.stringFormat('onmousedown="{0}.toggleBranch(\'{1}\', true)" style="cursor: pointer; cursor: hand"', this.myname, layerID) : '';
			var imgTag    = this.stringFormat('<img src="{0}/{1}{2}.gif" width="20" height="20" align="top" border="0" name="img_{3}" {4}> ', this.iconpath, gifname, modifier, layerID, onMDown);
			var linkTarget= nodes[i].linkTarget ? nodes[i].linkTarget : this.linkTarget;
			var linkStart = nodes[i].link ? this.stringFormat('<a href="{0}" target="{1}">', nodes[i].link, linkTarget) : '';

			var linkEnd   = nodes[i].link ? '</a>' : '';

			this.output += this.stringFormat('{0}<nobr>{1}{2}{3} {4}<span {5}>{6}</span>{7}</nobr><br></div>',
			                  layerTag,
							  prepend,
			                  parentLayerID == null && (nodes.length == 1 || this.noTopLevelImages) ? '' : imgTag,
							  iconimg,
							  linkStart,
							  eventHandlers,
							  nodes[i].title,
							  linkEnd);

			/**
	        * Traverse sub nodes ?
	        */
			if (nodes[i].n.length) {
				/**
	            * Determine what to prepend. If there is only one root
				* node then the prepend to pass to children is nothing.
				* Otherwise it depends on where we are in the tree.
	            */
				if (parentLayerID == null && (nodes.length == 1 || this.noTopLevelImages)) {
					var newPrepend = '';
	
				} else if (i < (nodes.length - 1)) {
					var newPrepend = prepend + this.stringFormat('<img src="{0}/line.gif" width="20" height="20" align="top">', this.iconpath);
	
				} else {
					var newPrepend = prepend + this.stringFormat('<img src="{0}/linebottom.gif" width="20" height="20" align="top">', this.iconpath);
				}

				this.drawMenu(nodes[i].n,
				              arrayCopy(level),
				              newPrepend,
				              nodes[i].expanded,
				              expanded ? 'inline' : 'none',
				              layerID);
			}
		}
	}

/**
* Writes the output generated by drawMenu() to the page
*/
	TreeMenu.prototype.writeOutput = function ()
	{
		document.write(this.output);
	}

/**
* Toggles a branches visible status. Called from resetBranches()
* and also when a +/- graphic is clicked.
*/
	TreeMenu.prototype.toggleBranch = function (layerID, updateStatus) // OPTIONAL ARGS: fireEvents = true
	{
		var currentDisplay = this.getLayer(layerID).style.display;
		var newDisplay     = (this.branchStatus[layerID] && currentDisplay == 'inline') ? 'none' : 'inline';
		var fireEvents     = arguments[2] != null ? arguments[2] : true;

		for (var i=0; i<this.layerRelations[layerID].length; i++) {

			if (this.branchStatus[this.layerRelations[layerID][i]]) {
				this.toggleBranch(this.layerRelations[layerID][i], false);
			}
	
			this.getLayer(this.layerRelations[layerID][i]).style.display = newDisplay;
		}
	
		if (updateStatus) {
			this.branchStatus[layerID] = !this.branchStatus[layerID];
	
			/**
	        * Persistence
	        */
			if (this.doesPersistence() && !arguments[2] && this.usePersistence) {
				this.setExpandedStatusForCookie(layerID, this.branchStatus[layerID]);
			}

			/**
			* Fire custom events
			*/
			if (fireEvents) {
				nodeObject = this.nodeRefs[layerID];
	
				if (nodeObject.ontoggle != null) {
					eval(nodeObject.ontoggle);
				}
				
				if (newDisplay == 'none' && nodeObject.oncollapse != null) {
					eval(nodeObject.oncollapse);
				} else if (newDisplay == 'inline' && nodeObject.onexpand != null){
					eval(nodeObject.onexpand);
				}
			}

			// Swap image
			this.swapImage(layerID);
		}

		// Swap icon
		this.swapIcon(layerID);
	}

/**
* Swaps the plus/minus branch images
*/
	TreeMenu.prototype.swapImage = function (layerID)
	{
		var imgSrc = document.images['img_' + layerID].src;
	
		var re = /^(.*)(plus|minus)(bottom|top|single)?.gif$/
		if (matches = imgSrc.match(re)) {
	
			document.images['img_' + layerID].src = this.stringFormat('{0}{1}{2}{3}',
			                                                matches[1],
															matches[2] == 'plus' ? 'minus' : 'plus',
															matches[3] ? matches[3] : '',
															'.gif');
		}
	}

/**
* Swaps the icon for the expanded icon if one
* has been supplied.
*/
	TreeMenu.prototype.swapIcon = function (layerID)
	{
		if (document.images['icon_' + layerID]) {
			var imgSrc = document.images['icon_' + layerID].src;
	
			if (this.nodeRefs[layerID].icon && this.nodeRefs[layerID].expandedIcon) {
				var newSrc = (imgSrc.indexOf(this.nodeRefs[layerID].expandedIcon) == -1 ? this.nodeRefs[layerID].expandedIcon : this.nodeRefs[layerID].icon);
	
				document.images['icon_' + layerID].src = this.iconpath + '/' + newSrc;
			}
		}
	}

/**
* Can the browser handle the dynamic menu?
*/
	TreeMenu.prototype.doesMenu = function ()
	{
		return (is_ie4up || is_nav6up || is_gecko || is_opera7);
	}

/**
* Can the browser handle save the branch status
*/
	TreeMenu.prototype.doesPersistence = function ()
	{
		return (is_ie4up || is_gecko || is_nav6up || is_opera7);
	}

/**
* Returns the appropriate layer accessor
*/
	TreeMenu.prototype.getLayer = function (layerID)
	{
		if (is_ie4) {
			return document.all(layerID);
	
		} else if (document.getElementById(layerID)) {
			return document.getElementById(layerID);
	
		} else if (document.all && document.all(layerID)) {
			return document.all(layerID);
		}
	}

/**
* Save the status of the layer
*/
	TreeMenu.prototype.setExpandedStatusForCookie = function (layerID, expanded)
	{
		this.cookieStatuses[layerID] = expanded;
		this.saveCookie();
	}

/**
* Load the status of the layer
*/
	TreeMenu.prototype.getExpandedStatusFromCookie = function (layerID)
	{
		if (this.cookieStatuses[layerID]) {
			return this.cookieStatuses[layerID];
		}

		return false;
	}

/**
* Saves the cookie that holds which branches are expanded.
* Only saves the details of the branches which are expanded.
*/
	TreeMenu.prototype.saveCookie = function ()
	{
		var cookieString = new Array();

		for (var i in this.cookieStatuses) {
			if (this.cookieStatuses[i] == true) {
				cookieString[cookieString.length] = i;
			}
		}
		
		document.cookie = 'TreeMenuBranchStatus=' + cookieString.join(':');
	}

/**
* Reads cookie parses it for status info and
* stores that info in the class member.
*/
	TreeMenu.prototype.loadCookie = function ()
	{
		var cookie = document.cookie.split('; ');

		for (var i=0; i < cookie.length; i++) {
			var crumb = cookie[i].split('=');
			if ('TreeMenuBranchStatus' == crumb[0] && crumb[1]) {
				var expandedBranches = crumb[1].split(':');
				for (var j=0; j<expandedBranches.length; j++) {
					this.cookieStatuses[expandedBranches[j]] = true;
				}
			}
		}
	}

/**
* Reset branch status
*/
	TreeMenu.prototype.resetBranches = function ()
	{
		if (!this.doesPersistence()) {
			return false;
		}
		
		this.loadCookie();

		for (var i=0; i<this.branches.length; i++) {
			var status = this.getExpandedStatusFromCookie(this.branches[i]);
			// Only update if it's supposed to be expanded and it's not already
			if (status == true && this.branchStatus[this.branches[i]] != true) {
				if (this.checkParentVisibility(this.branches[i])) {
					this.toggleBranch(this.branches[i], true, false);
				} else {
					this.branchStatus[this.branches[i]] = true;
					this.swapImage(this.branches[i]);
				}
			}
		}
	}

/**
* Checks whether a branch should be open
* or not based on its parents' status
*/
	TreeMenu.prototype.checkParentVisibility = function (layerID)
	{
		if (this.in_array(this.childParents[layerID], this.branches)
		    && this.branchStatus[this.childParents[layerID]]
			&& this.checkParentVisibility(this.childParents[layerID]) ) {
			
			return true;
	
		} else if (this.childParents[layerID] == null) {
			return true;
		}
		
		return false;
	}

/**
* New C# style string formatter
*/
	TreeMenu.prototype.stringFormat = function (strInput)
	{
		var idx = 0;
	
		for (var i=1; i<arguments.length; i++) {
			while ((idx = strInput.indexOf('{' + (i - 1) + '}', idx)) != -1) {
				strInput = strInput.substring(0, idx) + arguments[i] + strInput.substr(idx + 3);
			}
		}
		
		return strInput;
	}

/**
* Also much adored, the PHP implode() function
*/
	TreeMenu.prototype.implode = function (seperator, input)
	{
		var output = '';
	
		for (var i=0; i<input.length; i++) {
			if (i == 0) {
				output += input[i];
			} else {
				output += seperator + input[i];
			}
		}
		
		return output;
	}

/**
* Aah, all the old favourites are coming out...
*/
	TreeMenu.prototype.in_array = function (item, arr)
	{
		for (var i=0; i<arr.length; i++) {
			if (arr[i] == item) {
				return true;
			}
		}
	
		return false;
	}

/**
* TreeNode Class
*/
	function TreeNode(title, icon, link, expanded, isDynamic, cssClass, linkTarget, expandedIcon)
	{
		this.title        = title;
		this.icon         = icon;
		this.expandedIcon = expandedIcon;
		this.link         = link;
		this.expanded     = expanded;
		this.isDynamic    = isDynamic;
		this.cssClass     = cssClass;
		this.linkTarget   = linkTarget;
		this.n            = new Array();
		this.events       = new Array();
		this.handlers     = null;
		this.oncollapse   = null;
		this.onexpand     = null;
		this.ontoggle     = null;
	}

/**
* Adds a node to an already existing node
*/
	TreeNode.prototype.addItem = function (newNode)
	{
		newIndex = this.n.length;
		this.n[newIndex] = newNode;
		
		return this.n[newIndex];
	}

/**
* Sets an event for this particular node
*/
	TreeNode.prototype.setEvent = function (eventName, eventHandler)
	{
		switch (eventName.toLowerCase()) {
			case 'onexpand':
				this.onexpand = eventHandler;
				break;

			case 'oncollapse':
				this.oncollapse = eventHandler;
				break;

			case 'ontoggle':
				this.ontoggle = eventHandler;
				break;

			default:
				this.events[eventName] = eventHandler;
		}
	}

/**
* That's the end of the tree classes. What follows is
* the browser detection code.
*/
	

//<!--
// Ultimate client-side JavaScript client sniff. Version 3.03
// (C) Netscape Communications 1999-2001.  Permission granted to reuse and distribute.
// Revised 17 May 99 to add is_nav5up and is_ie5up (see below).
// Revised 20 Dec 00 to add is_gecko and change is_nav5up to is_nav6up
//                      also added support for IE5.5 Opera4&5 HotJava3 AOLTV
// Revised 22 Feb 01 to correct Javascript Detection for IE 5.x, Opera 4,
//                      correct Opera 5 detection
//                      add support for winME and win2k
//                      synch with browser-type-oo.js
// Revised 26 Mar 01 to correct Opera detection
// Revised 02 Oct 01 to add IE6 detection

// Everything you always wanted to know about your JavaScript client
// but were afraid to ask. Creates "is_" variables indicating:
// (1) browser vendor:
//     is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV
// (2) browser version number:
//     is_major (integer indicating major version number: 2, 3, 4 ...)
//     is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
// (3) browser vendor AND major version number
//     is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,
//     is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,
//     is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up
// (4) JavaScript version number:
//     is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
// (5) OS platform and version:
//     is_win, is_win16, is_win32, is_win31, is_win95, is_winnt, is_win98, is_winme, is_win2k
//     is_os2
//     is_mac, is_mac68k, is_macppc
//     is_unix
//     is_sun, is_sun4, is_sun5, is_suni86
//     is_irix, is_irix5, is_irix6
//     is_hpux, is_hpux9, is_hpux10
//     is_aix, is_aix1, is_aix2, is_aix3, is_aix4
//     is_linux, is_sco, is_unixware, is_mpras, is_reliant
//     is_dec, is_sinix, is_freebsd, is_bsd
//     is_vms
//
// See http://www.it97.de/JavaScript/JS_tutorial/bstat/navobj.html and
// http://www.it97.de/JavaScript/JS_tutorial/bstat/Browseraol.html
// for detailed lists of userAgent strings.
//
// Note: you don't want your Nav4 or IE4 code to "turn off" or
// stop working when new versions of browsers are released, so
// in conditional code forks, use is_ie5up ("IE 5.0 or greater")
// is_opera5up ("Opera 5.0 or greater") instead of is_ie5 or is_opera5
// to check version in code which you want to work on future
// versions.

/**
* Severly curtailed all this as only certain elements
* are required by TreeMenu, specifically:
*  o is_ie4up
*  o is_nav6up
*  o is_gecko
*/

    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();

    // *** BROWSER VERSION ***
    // Note: On IE5, these return 4, so use is_ie5up to detect IE5.
    var is_major = parseInt(navigator.appVersion);
    var is_minor = parseFloat(navigator.appVersion);

    // Note: Opera and WebTV spoof Navigator.  We do strict client detection.
    // If you want to allow spoofing, take out the tests for opera and webtv.
    var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
                && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
                && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
    var is_nav6up = (is_nav && (is_major >= 5));
    var is_gecko = (agt.indexOf('gecko') != -1);


    var is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
    var is_ie4    = (is_ie && (is_major == 4) && (agt.indexOf("msie 4")!=-1) );
    var is_ie4up  = (is_ie && (is_major >= 4));
	
	var is_opera  = (agt.indexOf("opera") != -1);
	var is_opera7 = (is_opera && is_major >= 7) || agt.indexOf("opera 7") != -1;

	// Patch from Harald Fielker
    if (agt.indexOf('konqueror') != -1) {
        var is_nav    = false;
        var is_nav6up = false;
        var is_gecko  = false;
        var is_ie     = true;
        var is_ie4    = true;
        var is_ie4up  = true;
    }
