function fnemail(user,host,cuser,chost,sbj,tag) {
    eml= "<A href=mailto:" + user +"@" + host;
    if ((cuser!=="")||(sbj!=="")) eml=eml + "?";
    if (cuser!=="") eml=eml + "CC=" + cuser + "@" + chost;
    if ((cuser!=="")&&(sbj!=="")) eml=eml + "&";
    if (sbj!=="") eml=eml + "Subject=" + sbj;
    eml=eml + ">";
    (tag=="")? eml=eml + user +"@" + host: eml=eml + " " + tag;
    eml=eml + "</A>";
    document.write(eml);
}
    
function getElementWithId(id) {
    var obj = null;
    if(document.getElementById){
        /* Prefer the widely supported W3C DOM method, if
           available:-
        */
        obj = document.getElementById(id);
    }else if(document.all){
        /* Branch to use document.all on document.all only
           browsers. Requires that IDs are unique to the page
           and do not coincide with NAME attributes on other
           elements:-
        */
        obj = document.all[id];
    }
    /* If no appropriate element retrieval mechanism exists on
       this browser this function always returns null:-
    */
    return obj;
}

    function DoSubmitGET(url) {
      document.forms[0].action = url
      document.forms[0].method = "GET"
      document.forms[0].submit()
    }


    function DoSubmitPOST(url) {
      document.forms[0].action = url
      document.forms[0].method = "POST"
      document.forms[0].submit()
    }


      function LTrim(str) {
	      for (var i=0; str.charAt(i)==" "; i++);
	      return str.substring(i,str.length);
	      }

      function RTrim(str) {
	      for (var i=str.length-1; str.charAt(i)==" "; i--);
	      return str.substring(0,i+1);
	      }

      function Trim(str) {
	      return LTrim(RTrim(str));
	      }

      function isInteger(val) {
	      for (var i=0; i < val.length; i++) {
		      if (!isDigit(val.charAt(i))) { return false; }
		      }
	      return true;
	      }
      	
      function isDigit(num) {
	      var string="1234567890";
	      if (string.indexOf(num) != -1) {
		      return true;
		      }
	      return false;
	      }



// ******  
// ******  Hand-Dandy All-Purpose Form Validation Code (yeah, it's in there!)
// ******  

// Debug setting.  If true, will show badly formed validation strings
var Debug = true;

// Global validation vars
var Error = false;	
var fieldError = false;	
var alertStr = "";
var alertHeader = "";	

var emailexp = /^[a-z][a-z_0-9\-\.]+@[a-z_0-9\.\-]+\.[a-z]{2,3}$/i
var phoneexp =  /^\d{10}$/
var rate =  /\%$/
var nospacesexp =  /\s+/
var zipcode = /^((\d{5}-\d{4})|(\d{5})|([A-Z]\d[A-Z]\s\d[A-Z]\d))$/
var datePat = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{2,4})$/;

//var URL = /^(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._\?\,\'\/\\\+&amp;%\$#\=~])*[^\.\,\)\(\s]$/

// Mulit-input validation global vars
var  CCName = "";	
var  CCType = "";	
var  CCNumber = 0;	
var  CCExpYear = "";	
var  CCExpMonth = "";	
var  CCNumberLoc = -1;	
var  CCMonthLoc = -1;	


// ******  Validation functions

function validateEmail(str) {	
	return emailexp.test(str)
}

function validatePercent(str) {	
	return rate.test(str)
}

function validateZipCode(str) {	
return zipcode.test(str);
}

function validateURL(str) {	
//	return URL.test(str)
return true;
}

function validateColor(str) {	
//	return URL.test(str)
return true;
}

function validatePhone(str) {
	return phoneexp.test(str)
}

function validateNoSpaces(str) {
//  return nospacesexp.test(str);
  if (nospacesexp.test(str)) {
    return true;
  } else {
    return false;
  }  
}

function validateCreditCard( fontStyle, showErrors) {

  var length = CCNumber.length;			//perform card specific length and prefix tests
  var CardNumberError = "";
  
  switch( CCType ) {
    case 'American Express':
      if( length != 15 ) { CardNumberError = CCType;}
      var prefix = parseInt( CCNumber.substring(0,2));
      if( prefix != 34 && prefix != 37 ) {CardNumberError = CCType; }
      break;

    case 'Discover':
      if( length != 16 ) { CardNumberError = CCType;}
      var prefix = parseInt( CCNumber.substring(0,4));
      if( prefix != 6011 ) { CardNumberError = CCType;}
      break;
    case 'Master Card':
      if( length != 16 ) { CardNumberError = CCType;}
      var prefix = parseInt( CCNumber.substring(0,2));
      if( prefix < 51 || prefix > 55 ) { CardNumberError = CCType;}
      break;
    case 'Visa':
      if(  length != 16 && length != 13 ) { CardNumberError = CCType;}
      var prefix = parseInt( CCNumber.substring(0,1));
      if( prefix != 4 ) { CardNumberError = CCType;}
      break;
  }
      
  if ("" != CardNumberError) {
    AddError(CCNumberLoc,"Please enter a valid " + CCType + " number.", fontStyle, showErrors);      
  }

  if( !mod10( CCNumber ) ) { 		// run the check digit algorithm
    AddError(CCNumberLoc,"Please enter a valid credit card number.", fontStyle, showErrors);      
  }
  if( expired( CCExpMonth, CCExpYear ) ) {							// check if entered date is already expired.
    AddError(CCMonthLoc,"The expiration date you have entered would make the credit card invalid.", fontStyle, showErrors);      
  }

}

// ******  Misc functions


function mod10( cardNumber ) { // LUHN Formula for validation of credit card numbers.
	var ar = new Array( cardNumber.length );
	var i = 0,sum = 0;


  for( i = 0; i < cardNumber.length; ++i ) {
    ar[i] = parseInt(cardNumber.charAt(i));
  }
  for( i = ar.length -2; i >= 0; i-=2 ) { // you have to start from the right, and work back.
    ar[i] *= 2;							 // every second digit starting with the right most (check digit)
    if( ar[i] > 9 ) ar[i]-=9;			 // will be doubled, and summed with the skipped digits.
  }										 // if the double digit is > 9, ADD those individual digits together 


  for( i = 0; i < ar.length; ++i ) {
    sum += ar[i];						 // if the sum is divisible by 10 mod10 succeeds
  }
  return (((sum%10)==0)?true:false);	 	
}


function expired( month, year ) {
  var now = new Date();							// this function is designed to be Y2K compliant.
  var expiresIn = new Date(year,month,0,0,0);		// create an expired on date object with valid thru expiration date
  expiresIn.setMonth(expiresIn.getMonth()+1);		// adjust the month, to first day, hour, minute & second of expired month
  if( now.getTime() < expiresIn.getTime() ) return false;
  return true;									// then we get the miliseconds, and do a long integer comparison
}


function CRLF () {
	return String.fromCharCode(10) + String.fromCharCode(13);
}

function TAB(howMany) {
	var tempStr
	for (count = 0; count < howMany; count++) {
		tempStr = tempStr & String.fromCharCode(9);
	}
}
function StripChars(ItemsToStrip, str) {
	returnString = "";
	for (i = 0; i < str.length; i++) {  
		var c = str.charAt(i);
        	if (ItemsToStrip.indexOf(c) == -1) returnString += c;       	 	 
	}
	return returnString;
}

function AllSpace(str) {   //Makes String Blank if noting but spaces
	for (i=0; i < str.length; i++) {
		if (str.charAt(i) != " ") {
			return str;
		}
	}
	return "";
}

function SetDec(str, places) { //chops decimal places to max number of places	
	if (isNaN(str)) {
		return str;
	}
	if (str.indexOf(".") != -1) {
	    if (places > 0) {
		str = str.substring(0, eval(str.indexOf(".")) + eval(places) + eval(1));
	    } else {
		str = str.substring(0, str.indexOf("."));
	    }
	}
	return str;
}


function isDate(dateStr) {
  var matchArray = dateStr.match(datePat);
  if (matchArray == null) return false;
  month = matchArray[1];
  day = matchArray[3];
  year = matchArray[5];
  if (month < 1 || month > 12) return false;
  if (day < 1 || day > 31) return false;
  if ((month==4 || month==6 || month==9 || month==11) && day==31) return false;
  if (month == 2) {
    var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
    if (day > 29 || (day==29 && !isleap)) return false;
  }
  return true;
} 

function stripNonDigits(str) {
	return str.replace(/[^0-9]/g,"")
}

function AddError(x, ErrMsg, fontStyle,showErrors) {

	alertStr = alertStr + ErrMsg + CRLF();
	if (showErrors == true) {
		getElementWithID(form.elements[x].name + 'Error').innerHTML = "<font  style='" + fontStyle + "'>" + ErrMsg + "</font>";
// BJR changed to not use document.all
//		document.all[form.elements[x].name + 'Error'].innerHTML = "<font  style='" + fontStyle + "'>" + ErrMsg + "</font>";
	}
	Error = true;
	fieldError = true;
}

// ******  Main Validation function called from form tag

function checkform(form, errColor, startColor, showAlert, showErrors, fontStyle, separator, callUserCheckform) {

		var paramName = "";
		var ErrMsg = "";
		var ThisType = "";
		var temp = "";
		var temp2 = "";
		var formElems = new Object();
		var gotOne = false;
		var oneFilled = false;
		var oneBlank = false;

		if (separator == null) {
			separator = false;
		}

		Error = false;	
		fieldError = false;	
		alertStr = "";
		alertHeader = "";	

		CCType = "";	
		CCName = "";	
		CCNumber = 0;	
		CCExpYear = "";	
		CCExpMonth = "";	
		CCNumberLoc = -1;	
		CCMonthLoc = -1;	

		alertHeader = "There were some problems with the inputs you provided." + CRLF() ;		
		alertHeader = alertHeader  + "Please fix the following items,  and try again. " + CRLF() + CRLF();		

		if (callUserCheckform != null)  {
		// Call User supplied validation functions.  User function must call AddError
			UserCheckform(form)
		}

		// Create hash list of form elements
		for (y=0; y < form.elements.length; y++ ) {	
			formElems[form.elements[y].name] = form.elements[y].value;
		}

		for (x=0; x < form.elements.length; x++ ) {	
  		fieldError = false;   
			if (form.elements[x].type == "text" || form.elements[x].type == "checkbox" || form.elements[x].type == "radio" || form.elements[x].type == "select-one" || form.elements[x].type == "password"  || form.elements[x].type == "textarea") {

				if (showErrors == true) {
    			getElementWithID(form.elements[x].name + 'Error').innerHTML = "";
				}		
		    
				// Work on all form variables that have validation input

				form.elements[x].value = AllSpace(form.elements[x].value);
		    
				// Can have multiple validations on the same field
				for (z=1; z < 5; z++ ) {	      
					if (x+z < form.length && form.elements[x+z].name.charAt(0) != "@") {
						z = 100;
					} else {
						paramStr = form.elements[x+z].name.substring(1, form.elements[x+z].name.length);
						params = null;
						params = paramStr.split(separator);
	  		    

						if (Debug == true) {
							// Need some code here to detect a malformed validation string
//							alert(params[0] + ":" + params[1] + ":" + params[2] + ":" + params[3] + ":")
						}
						// Can put the validated field proper name in the 4th spot, or just use the defined name
						paramName = params[3];
						if (paramName == null) {
							paramName = params[2];
						} 

						if (params[8] != null) {
							backColor = params[8];
						} else {
							backColor = startColor;
						} 
	      		
						if (params[7] != null && AllSpace(params[7]) != "" ) {
							defaultValue = params[7];
						} else {
							defaultValue = "";
						}
	      		
						// Check for blank/no blank requirements and set default values
						if (params[1] == "NoBlank") {
					    if (form.elements[x].type=="radio"||form.elements[x].type=="checkbox") {
							  if (!form.elements[x]) {
							    if (!form.elements[x].checked) {
        			      AddError(x,paramName + " must be selected.", fontStyle, showErrors);
						      }
						    } else {
						      if (Trim(form.elements[x].value) == "" && defaultValue == "") {
        			      AddError(x,"The " + paramName + " field must not be blank.", fontStyle, showErrors);

						      } else if (params[1] == "NoBlank" && Trim(form.elements[x].value) == "" && defaultValue != "") {
							      form.elements[x].value = defaultValue;
						      }
                }	  			    
                }	  			    
            }	  			    
				    
						// For group functions, the fields to check are in params[1] and separated by pipes.  
						// The custom description for the group of fields is in the last element of params[1]
						if (params[0] == "NoBlankGroup" ) {
							temp = params[2];
							args = temp.split("|")
							gotOne = false;

							if (form.elements[args[0]].type=="radio"||form.elements[args[0]].type=="checkbox") {
							  for (y=0; y < args.length; y++ ) {								  
								  if (form.elements[args[y]]) {
								    if (form.elements[args[y]].checked) {
									    gotOne = true;
								    }		      
							  }
							  }
							  typeMsg="items must be selected" 
							} else {
							  for (y=0; y < args.length; y++ ) {								  
								  if (Trim(formElems[args[y]]) != "") {
									  gotOne = true;
								  }		      
							  }							
							  typeMsg="fields must be filled in" 
							}

							if (gotOne != true) {
          			AddError(x,"At least one of the following " + typeMsg + ":"  + CRLF() + "    " + paramName, fontStyle, showErrors);		      
							}

						} else if (params[0] == "OnlyOneInGroup" ) {
							temp = params[2];
							args = temp.split("|")
							gotOne = false;
							for (y=0; y < args.length; y++ ) {	
								if (Trim(formElems[args[y]]) != "") {
									if (gotOne) {
              			AddError(x,"Only one of the following fields can be filled in at a time:"  + CRLF() + "    " + paramName, fontStyle, showErrors);		      
              			y = args.length;
									} else {
  									gotOne = true;		          
									}
								}		      
							}

						} else if (params[0] == "AllOrNoneGroup" ) {
							oneFilled = false;
							oneBlank = false;
							temp = params[2];
							args = temp.split("|")
							gotOne = false;
							for (y=0; y < args.length; y++ ) {	
								if (Trim(formElems[args[y]]) == "") {
									oneBlank = true;
								} else {
									oneFilled = true;
								}		      
							}
							if (oneFilled && oneBlank ) {
          			AddError(x,"Either all or none of the following fields must be filled in: "  + CRLF() + "    " + paramName, fontStyle, showErrors);		      
							}
	  		    
						// Checks to make sure the chosen select list value isn't the default value
						} else if (params[0] == "select" && form.elements[x].value == params[1]  && params[1] != "Blank" ) {
        			AddError(x,"Select a value for the " + paramName + " field.", fontStyle, showErrors);

						} else if (params[0] == "email") {
							if (!validateEmail(form.elements[x].value) && form.elements[x].value != "") {				
        				AddError(x,"The " + paramName + " field does not contain a vaild email address.", fontStyle, showErrors);
							} 
				    } else if (params[0] == "zipcode") {
					    if (!validateZipCode(form.elements[x].value) && form.elements[x].value != "") {				
		        	  AddError(x,"The " + paramName + " field does not contain a vaild US or Canadian Zip Code.", fontStyle, showErrors);
					    } 
						} else if (params[0] == "url") {
							if (!validateURL(form.elements[x].value) && form.elements[x].value != "") {				
        				AddError(x,"The " + paramName + " field does not contain a vaild URL.", fontStyle, showErrors);
							} 
						} else if (params[0] == "maxchars") {
							temp = AllSpace(form.elements[x].value);
							if (temp != "") {				
								var start = params[1];
								temp2 = temp.substr(start,temp.length);
								temp = AllSpace(temp2);
								if (temp != "") {				
		      				AddError(x,"The " + paramName + " field contains more than " + start + " characters.", fontStyle, showErrors);
		      			}
							} 
						} else if (params[0] == "color") {
							if (!validateColor(form.elements[x].value) && form.elements[x].value != "") {				
        				AddError(x,"The " + paramName + " field does not contain a vaild color value.", fontStyle, showErrors);
							} 
						} else if (params[0] == "percent") {
							temp = StripChars("%", form.elements[x].value);
							if (isNaN(temp)) {
        				AddError(x,"The " + paramName + " field does not contain a number for the percentage value.", fontStyle, showErrors);
							} else {
								if (eval(temp) < 0 || eval(temp) > 100) {
    							AddError(x,"The " + paramName + " percentage value must be between 0 and 100." , fontStyle, showErrors);
								}	else {
  								temp = Trim(form.elements[x].value);
									if (!validatePercent(temp) && form.elements[x].value != "") {				
        						AddError(x,"The " + paramName + " field does not contain a percent sign.", fontStyle, showErrors);
									}
								} 
							}
						} else if ((params[0] == "number" || params[0] == "numbermin" || params[0] == "numbermax" || params[0] == "numberrange" || params[0] == "numberonly") && form.elements[x].value != "") {
							if (params[0] == "number") {
  							temp2 = " does not contain a numeric value."
  							temp =StripChars("$,%", form.elements[x].value)
  						} else {
  							temp2 = " contains a non-numeric character."
  							temp = form.elements[x].value  		      
  						}
							if (params[4] != null) {
								form.elements[x].value = SetDec(form.elements[x].value, params[4]);	
							}
							if (isNaN(temp)) {
        				AddError(x,"The " + paramName + temp2, fontStyle, showErrors);
							} else {
								if (params[5] != null) {
									if (eval(temp) < eval(params[5])) {
        						AddError(x,"The " + paramName + " must be greater than " + params[6], fontStyle, showErrors);
									}
								}
								if (params[6] != null) {
									if (eval(temp) > eval(params[6])) {
        						AddError(x,"The " + paramName + " must be less than " + params[6], fontStyle, showErrors);
									}
								}
							}    			
						} else if (params[0] == "age" && form.elements[x].value != "") {    			
							form.elements[x].value = SetDec(form.elements[x].value,0);
							if (eval(form.elements[x].value) < 0 || eval(form.elements[x].value) > 120) {
    						AddError(x,"The " + paramName + " doesn't appear to be a valid age." , fontStyle, showErrors);
							}			
						} else if (params[0] == "date" && form.elements[x].value != "") {
							if (form.elements[x].value != "") {
  							if (!isDate(form.elements[x].value)) {
    							AddError(x,"The " + paramName + " field is not a valid date." , fontStyle, showErrors);
								} else { 
                  var matchArray = form.elements[x].value.match(datePat);
                  month = Number(matchArray[1]);
                  day = Number(matchArray[3]);
                  year = matchArray[5];
							    if (year.length <= 2) {
								    year = eval(year) + eval(2000);				
							    }	
							    tempDate=eval(month) + "/" + eval(day) + "/" + year;
								  if (params[5] != null && Date.parse(String(params[5])) > Date.parse(tempDate)) {
    							  AddError(x,"The " + paramName + " date is too early." , fontStyle, showErrors);
  							  } else if (params[6] != null && Date.parse(String(params[6])) < Date.parse(String(tempDate))) {
    							  AddError(x,"The " + paramName + " date is too late." , fontStyle, showErrors);
								  } else {
   								  form.elements[x].value = tempDate;
								  }
								}
							}			    
						} else if (params[0] == "phone" && form.elements[x].value != "") {
							form.elements[x].value = stripNonDigits(form.elements[x].value)
							if (validatePhone(form.elements[x].value)) {
			    					tempP = form.elements[x].value	
			    					form.elements[x].value = "(" + tempP.substring(0, 3) + ") " + tempP.substring(3,6) + "-" + tempP.substring(6, 10)
							} else {
								AddError(x,"The " + paramName + " field is invalid.  Please include the full phone number including area code.", fontStyle, showErrors);
							}			    
						} else if (params[0] == "nospaces" && form.elements[x].value != "") {    			
							if (validateNoSpaces(form.elements[x].value)) { 
								AddError(x,"The " + paramName + " field may not contain spaces.", fontStyle, showErrors);
							}			
						}

    				// collect inputs for multi-input functions to validate
						else if (params[0] == "CCNumber" ) { CCNumber = StripChars("-",form.elements[x].value) ; CCNumberLoc = x;}
						else if (params[0] == "CCName" ) { CCName = form.elements[x].value }
						else if (params[0] == "CCType" ) { CCType = form.elements[x].value ; CCTypeLoc = x;}
						else if (params[0] == "CCExpYear" ) { CCExpYear = form.elements[x].value ; }
						else if (params[0] == "CCExpMonth" ) { CCExpMonth = form.elements[x].value ;}

						if (fieldError == true) {
							form.elements[x].style.background = errColor;
  					} else {
							form.elements[x].style.background = backColor;
						} 
					}
				}	
			}
		}
	    
		// Run any functions after all form elements processed   
		// Don't include CCType in the following check as the variable can also be used to indicate general payment method  (like a personal check)
		if ((CCName != "") || (CCNumber != 0) || (CCExpYear != "") || (CCExpMonth != "")) {
			if (CCName == "")  {
				AddError(x,"The credit card Name field is missing.", fontStyle, showErrors);
			}	else {
				if (CCNumber == 0)  {
					AddError(x,"The credit card Number field is missing.", fontStyle, showErrors);
				} else {	
					if (CCType == "")  {
						AddError(x,"The credit card Type field is missing.", fontStyle, showErrors);
					}	else {
						if (CCExpYear == "")  {
							AddError(x,"The credit card Expiration Year field is missing.", fontStyle, showErrors);
						}	else {
							if (CCExpMonth == "") {
								AddError(x,"The credit card Expiration Month field is missing.", fontStyle, showErrors);
							}	else {
								validateCreditCard( fontStyle, showErrors) ;
							}
						}
					}
				}
			}
		}
	  
		if (Error == true) {
			if (showAlert == true) {
				alert (alertHeader + alertStr);
			} else {
				alert (alertHeader);	
			}
			return false;
		}
}


// *********************************************************************************

