function fV_validate(formObj, confirmFlag, buttonStr) {
 fV_errorStr="";

 for (i=0; i<formObj.elements.length; i++) {
  type= formObj.elements[i].type;
  if ( type=="text" || type=="textarea" || type=="select" || type=="password" ) { //checkbox, radio?

   labelObj= document.getElementById("vId_" +formObj.elements[i].name);
   
   if (labelObj) {
    labelObj.className= labelObj.className.replace(new RegExp("\s*errorLabel\\b"), ""); //clear errorLabel

    if (type=="text" || type=="textarea") formObj.elements[i].value= a_trim(formObj.elements[i].value); //trim strings //modifying data here!
    inputStr= formObj.elements[i].value;

    //be careful what text goes inside the label
    //all class names like "v_required", "v_number", etc. are used as flags, as text they cannot ever appear "by accident"
    //should never be a problem, but need to note this
    labelStr= labelObj.innerHTML;

    if (labelStr.indexOf("v_required")>0) {
     minimumRequired= 1;
     classStr= labelStr.match(new RegExp("v_requiredMin_[0-9]*") );
     if (classStr) {
      classStr= classStr +""; //turn to string
      minimumRequired= classStr.match(new RegExp("[0-9]+") );
      if (minimumRequired<1) minimumRequired=1;
     }
     if (inputStr.length<minimumRequired) addErrorStr( "be " +((minimumRequired<=1) ? "filled out" : "at least " +minimumRequired +" char") );
    }

    if (inputStr!="") {

     if (labelStr.indexOf("v_number")>0) {
      if (isNaN(inputStr)) addErrorStr("be a number");
     }

     if (labelStr.indexOf("v_zipCode")>0) {
      re= /(^\d{5}$)|(^\d{5}-\d{4}$)/;
      if (!re.exec(inputStr)) addErrorStr("have a Zip Code format");
     }

     if (labelStr.indexOf("v_phoneNumber")>0) {
      re= /^(((\(\d{3}\))\s?)|(\d{3}[-\/\.\s]))\d{3}[-\/\.\s]\d{4}$/;
      if (!re.exec(inputStr)) addErrorStr("have a Phone Number format");
     }

     if (labelStr.indexOf("v_email")>0) {
      re= /^([a-zA-Z0-9_\-])+(\.([a-zA-Z0-9_\-])+)*@((\[(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5])))\.(((([0-1])?([0-9])?[0-9])|(2[0-4][0-9])|(2[0-5][0-5]))\]))|((([a-zA-Z0-9])+(([\-])+([a-zA-Z0-9])+)*\.)+([a-zA-Z])+(([\-])+([a-zA-Z0-9])+)*))$/;
      if (!re.exec(inputStr)) addErrorStr("have an Email Address format"); //re from Myle Ott
     }

     if (labelStr.indexOf("v_custom")>0) {
      errorStr= fV_customValidation(formObj.elements[i]);
      if (errorStr) addErrorStr(errorStr);
     }

    } //not empty

   } //labelObj
  } //type
 } //iterate

 OK= false;
 if (!buttonStr) buttonStr= "SUBMIT";
 if (fV_errorStr) {
  alert("Form validation errors:\n\n" +fV_errorStr +"\nPlease correct, then click " +buttonStr +" again.");
 } else if (confirmFlag) {
  OK= confirm(buttonStr +" this form?");
 } else {
  OK= true;
 }
 return OK;

 function addErrorStr(errorStr) {
  str= a_trim(labelStr.substr(0,labelStr.indexOf("<")));
  fV_errorStr+= "[" +str +"] must " +errorStr;
  fV_errorStr+= (inputStr) ? (". Your value: " +inputStr) : ".";
  fV_errorStr+= "\n";
  if (labelObj.className.indexOf(" errorLabel")<0) labelObj.className+= " errorLabel"; //mark errorLabel
 }

}




function fV_customValidation(inputObj) {
 return null; //placeholder
}

