function checkRequired(obj) {
	var save_id = $(obj).attr("id");
	var tableObj = $("#"+save_id.substr(5)+"_form table");
	var missing = 0;
	
	$(tableObj).find("td.required").each(function(){
		var fieldsObj = $(this).parent().find(".fields");
		var type = getValidationType(fieldsObj);
		
          switch(type){
               case "checkbox": case "radio":
     			var count = 0;
     			
                    $(fieldsObj).find("input:checked").each(function(){
     				count++;
     			});
                    
     			if (count == 0)
     				missing++;
                         
                    break;
               case "zip_code":
     			if ($(fieldsObj).find("input[class='zip_code5']").val() == "")
     				missing++;
                    break;
               case "phone":
               	if (
				$(fieldsObj).find("input[class='phone1']").val() == "" ||
				$(fieldsObj).find("input[class='phone2']").val() == "" ||
				$(fieldsObj).find("input[class='phone3']").val() == ""
				)
				missing++;
                    break;
               case "text": default:
     			if ($(fieldsObj).find("input").val() == "")
     				missing++;
                    break;
               case "select":
               	if ($(fieldsObj).find("select").val() == "X" || 
                        $(fieldsObj).find("select").val() == "")
                         missing++;
                    break;
               
               case "textarea":
               	if ($(fieldsObj).find("textarea").val() == "")
                         missing++;
                    break;
                    
               case "bullet_list":
               	if ($(fieldsObj).find("div").length == 1)
                         missing++;
                    break;
          }
	});
	
	if (missing > 0) {
		alert("One or more required fields has not been completed. All required fields must be completed before proceeding.");
		return true;
	}
	
     return false;
}

function getValidationType(obj) {
	var type = "";
	
	if ($(obj).find("input[type='checkbox']").length > 0)
		type = "checkbox";
	if ($(obj).find("input[type='radio']").length > 0)
		type = "radio";
	if ($(obj).find("input[type='text']").length > 0) {
		if ($(obj).find("input").hasClass("zip_code5"))
			type = "zip_code";
		else if ($(obj).find("input").hasClass("phone1"))
			type = "phone";
		else
			type = "text";
	}
	if ($(obj).find("select").length > 0)
		type = "select";
	if ($(obj).find("textarea").length > 0)
		type = "textarea";
	if ($(obj).hasClass("bullet_list"))
		type = "bullet_list";
	
	return type;
}
/*   @name     isValidEmail        - Validates an Email Address            
     @param    string emailAddr
     @return   bool
     @notes
*/
function isValidEmail(emailAddr) {
     var re = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@"+                       
                         "([a-z0-9\-\.])+.([A-Z]{2}|aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|ac|ad|ae|af|ag|at|ai|alam|an|ao|aq|ar|as|at|auaw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bs|bt|bw|by|bz|ca|cc|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|pw|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|dt|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)", "g");
     return re.test(emailAddr);
}

/*   @name     isValidDate       - Validates a Date         
     @param    string date
     @return   bool
     @notes
*/
function isValidDate(date) {
     var re = new RegExp("^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}$", "i");
     
     if (!re.test(date))
          re = new RegExp("^[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}$", "i");
     return re.test(date);
}
          
function isValidURL(url) {
     var re = new RegExp("^(http:\/\/)?[A-Za-z0-9\.-]{3,}\.[A-Za-z]{3}", "g");
     return re.test(url);
}

function isValidPhone(phoneNumber){
     regexStr = /^\([0-9]{3}\)\s[0-9]{3}\-[0-9]{4}(\sx[0-9]+)?/;
     var re = new RegExp(regexStr);
     
     if(!re.test(phoneNumber)){
          re = new RegExp("^[0-9]{10}$", "g");
     }
     
     return re.test(phoneNumber);
}

function isValidZipCode(zipCode, len){
     var re = new RegExp("^[0-9]{5}(\-[0-9]{4})?$", "g");
     
     if(len){
          re = new RegExp("^[0-9]{"+len+"}$", "g");
     }
     return re.test(zipCode);
}

function isValidPrice(price){
     var re = new RegExp("^[0-9]+.[0-9]{2}$", "g");
     return re.test(price);
}

//Use Regular Expressions to check if our time is in the correct format
function isValidTime(time){
     var re = new RegExp("^[0-1]?[0-9]{1}:[0-5]{1}[0-9]{1}(\s[ap]{1}[m]{1})*", "i");
     return re.test(time);
}

function isValidText(txt){
     var re = new RegExp("^[A-Za-z ]+$", "g");
     return re.test(txt);
}

function isValidTextHyphens(txt){
     var re = new RegExp("^[A-Za-z\- ]+$", "g");
     return re.test(txt);
}

function isValidTextNospaces(txt){
     var re = new RegExp("^[A-Za-z]+$", "g");
     return re.test(txt);
}

function isValidNumber(num){
     var re = new RegExp("^[0-9]+(.[0-9]+)?$", "g");
     return re.test(num);
}

function isValidAlphaNum(str){
     var re = new RegExp("^[A-Za-z0-9 ]+$", "g");
     return re.test(str);
}

function isValidAlphaNumNospaces(str){
     var re = new RegExp("^[A-Za-z0-9]+$", "g");
     return re.test(str);
}

function isValidCreditCard(str){
     var re = new RegExp("^[0-9]{15,16}$", "g");
     return re.test(str);
}

function isNumberFree(str){
     /* here we check to see if the string does contain numbers
        and just negate the answer */
     var re = new RegExp("[0-9]+","g");
     
     return !(re.test(str));
}

/*   @name     validateForm        - Validates all the fields within a form
*    @param    object formObj      - the form as a javascript object
*    @return   bool 
*    @notes
          1st Attempt
*    @Todo
*/
function validateForm(formObj){
     var isValidForm = true;
     trackChanges = false;
     
     // Remove all validation error messages before continuing
     $(".validatorErrorMessage").remove();
     
     // Begin validation
     $(formObj).find(":input").each(function(){
          /* Objective:
               Here we loop through each of the form field looking 
               for certain classes which inform us as to how to validate
               the form field. 
          */

          // Remove the classes that specifiy that additional action is needed
          $(this).removeClass("checkedInvalid checkedMissing messageFail checkedMissing messageSuccess");
                    
          //Get the remaining classes to search through
          var frmElmClasses = $(this).attr("class").split(" ");
          
          // Get the value to validate
          var inputValue    = getInputValue($(this));

          // A field is required if it has the class req
          var isRequired = ($(this).hasClass("req"))? true : false;
          
          //Assume it is valid until proven otherwise
          var isValid = true;
          
          for(var i = 0; i < frmElmClasses.length; i++){
               switch(frmElmClasses[i]){
                    default:
                         continue;
                         break;
                    case "number":  
                         isValid = isValidNumber(inputValue);
                         break;
                    case "properName":
                         isValid = isNumberFree(inputValue);
                         break;
                    case "text":
                         isValid = isValidText(inputValue);
                         break;
                    case "textNospaces":
                         isValid = isValidTextNospaces(inputValue);
                         break;
                    case "textNumber":
                         isValid = isValidAlphaNum(inputValue);
                         break;
                    case "textNumberNospaces":
                         isValid = isValidAlphaNumNospaces(inputValue);
                         break;
                    case "blob":
                         isValid = !inputValue.empty();
                         break;
                    case "phone": case "newPhone":
                         isValid = isValidPhone(inputValue);
                         break;
                    case "email":
                         isValid = isValidEmail(inputValue);
                         break;
                    case "website":
                         isValid = isValidURL(inputValue);
                         break;
                    case "date":
                         isValid = isValidDate(inputValue);
                         break;
                    case "time":
                         isValid = isValidTime(inputValue);
                         break;
                    case "creditcard":
                         isValid = isValidCreditCard(inputValue);
                         break;                                   
                    case "req":
                         isRequired = true;
                         break;
                    case "price":
                         isValid = isValidPrice(inputValue);
                         break;
                    case "zip_code5": case "zip_code4":
                         isValid = isValidZipCode(inputValue,frmElmClasses[i][8]);
                         break;
               }
          }

          // Reset TEXTAREA styling
          if ($(this)[0].tagName.toLowerCase() == "textarea") {
               $(this).parent().find(".mceEditor iframe").css("border", "0px");
               $(this).parent().find(".mceEditor iframe").contents().find("body").css("background-color", "#FFF");
          }

          if(!isValid){
               if(isRequired){
                    $(this).addClass("checkedInvalid messageFail");
                    
                    if(inputValue.empty()){
                         $(this).addClass("checkedMissing");
                         $(this).removeClass("checkedInvalid");
                    }
                    
                    if (!$(this).parent().hasClass("messageFailCheckbox")) {
                         $(this).parent().append(getErrorMessage($(this),frmElmClasses));
                    } else {
                         $(this).parent().parent().append(getErrorMessage($(this),frmElmClasses));
                    }
                    
                    // This must occur after the previous append() statement
                    if ($(this).attr("type") == "checkbox" || $(this).attr("type") == "radio") {
                         if (!$(this).parent().hasClass("messageFailCheckbox"))
                              $(this).wrap('<div class="messageFailCheckbox"></div>');
                    }
                    
                    // REMOVE Here for debugging
                    // console.log($(this).attr("id") + " fail validiation with value "+ inputValue);
                    
                    isValidForm = false;
               }else{
                    if(!inputValue.empty()){
                         $(this).addClass("checkedInvalid messageFail");
                         
                         if (!$(this).parent().hasClass("messageFailCheckbox")) {
                              $(this).parent().append(getErrorMessage($(this),frmElmClasses));
                         } else {
                              $(this).parent().parent().append(getErrorMessage($(this),frmElmClasses));
                         }
                         
                         // This must occur after the previous append() statement
                         if ($(this).attr("type") == "checkbox" || $(this).attr("type") == "radio") {
                              if (!$(this).parent().hasClass("messageFailCheckbox"))
                                   $(this).wrap('<div class="messageFailCheckbox"></div>');
                         }
                         
                         // REMOVE Here for debugging
                         // console.log($(this).attr("id") + " fail validiation with value "+ inputValue);
                         // End of removal
                         
                         isValidForm = false;
                    }else{
                         $(this).addClass("messageSuccess");
                    }
               }
          }else{
               // now check for required field not being empty
               if(isRequired){
                    // check for required field being empty
                    if(inputValue.empty()){
                         $(this).addClass("checkedInvalid messageFail");
                         
                         if (!$(this).parent().hasClass("messageFailCheckbox")) {
                              $(this).parent().append(getErrorMessage($(this),frmElmClasses));
                         } else {
                              $(this).parent().parent().append(getErrorMessage($(this),frmElmClasses));
                         }
                         
                         // This must occur after the previous append() statement
                         if ($(this).attr("type") == "checkbox" || $(this).attr("type") == "radio") {
                              if (!$(this).parent().hasClass("messageFailCheckbox"))
                                   $(this).wrap('<div class="messageFailCheckbox"></div>');
                         }
                         
                         // REMOVE Here for debugging
                         // console.log($(this).attr("id") + " fail validiation with value "+ inputValue);
                         // End of removal
                         
                         isValidForm = false;
                    }else{
                         $(this).addClass("messageSuccess");
                    }
               }else
                    $(this).addClass("messageSuccess");
          }
     });
     // REMOVE Here for debugging
     // console.log("Validation Test Passed:"+ isValidForm);
     
     return isValidForm;
}

function getInputValue(formElm){
     var val = "";

     switch($(formElm).attr("type")){
          case "textarea": 
               val = $(formElm).val();
               break;
          case "select-multiple":
               val = "";
               break;
          case "select-one":
               if($(formElm).hasClass("clickToList")){
                    $(formElm).find("option").each(function() {
                         //Add comma if needed
                         if(!val.empty())
                              val += ","
                              
                         // Add the value;
                         if(!$(this).val().empty())
                              val += $(this).val(); 
                    });
               }else{
                    val = $(formElm).val();
               }
               break;
          case "text": case "password":
               val = $(formElm).val();
               break;
          case "checkbox": case "radio":
               var elmName = $(formElm).attr("name");
               
               if(!elmName.empty()){
                    $("input[name='"+ elmName +"']:checked").each(function(){
                         if(!val.empty())
                              val += "-";

                         if($(this).val() != "")
                              val += $(this).val();
                    });
               } else {
                    val = ($(formElm).is(':checked'))? $(formElm).val() : "";
               }
               
               break;
          default:
               break;
     }
     
     //console.log($(formElm).attr("ID") + " has a value of "+ val);
     return val.trim();
}

function getIdentifier(obj){
     if($(obj).attr("name") != ""){
          return $(obj).attr("name");
     }
     
     if($(obj).attr("id") != ""){
          return $(obj).attr("id");
     }
         
     return $(obj).attr("type");
}

function getErrorMessage(obj,classes) {
     // Initialize error message string
     var error_message = new Array();
     
     // Why didn't this field validate? Check classes for this.
     var invalid = false;
     var missing = false;
     if ($(obj).hasClass("checkedInvalid")) {
          invalid = true;
     }
     if ($(obj).hasClass("checkedMissing")) {
          missing = true;
     }
     
     // Add message text to the error_message array
     var n = -1;
     for(var i = 0; i < classes.length; i++){
          switch(classes[i]){
               default:
                    continue;
                    break;
               case "number":  
                    if (invalid) error_message[error_message.length+1] = 'Please enter only numbers 0 through 9.';
                    break;
               case "properName":
                    if (invalid) error_message[error_message.length+1] = 'This field may not contain numbers.';
                    break;
               case "text":
                    if (invalid) error_message[error_message.length+1] = 'Please enter only letters A through Z.';
                    break;
               case "textNospaces":
                    if (invalid) error_message[error_message.length+1] = 'Please enter only letters A through Z with no spaces.';
                    break;
               case "textNumber":
                    if (invalid) error_message[error_message.length+1] = 'Please enter only alpha-numeric characters.';
                    break;
               case "textNumberNospaces":
                    if (invalid) error_message[error_message.length+1] = 'Please enter only alpha-numeric characters with no spaces.';
                    break;
               case "blob":
                    // Blobs validate
                    break;
               case "newPhone":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted phone number (i.e. (952) 555-0000 x0000).';
                    break;
               case "phone1": case "phone2": case "phone3":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted phone number (i.e. 952-555-0000).';
                    break;
               case "email":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted email address (i.e. help@wellclicks.com).';
                    break;
               case "website":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted website address, including the "http://". (i.e. http://www.wellclicks.com).';
                    break;
               case "date":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted date (i.e. 3/10/2009 or 2009-03-10).';
                    break;
               case "time":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted time value (i.e. 8:15am).';
                    break;
               case "creditcard":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted credit card number with no spaces (i.e. 1234567890123456).';
                    break;                                   
               case "req":
                    if (missing) error_message[error_message.length+1] = 'This field is required.';
                    break;
               case "price":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted dollar amount (i.e. 19.75).';
                    break;
               case "phone4":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted phone extension (i.e. 5555).';
                    break;
               case "zip_code5": case "zip_code4":
                    if (invalid) error_message[error_message.length+1] = 'Please enter a properly formatted zip code (i.e. 55387-1234).';
                    break;
          }
     }
     
     // Don't repeat error messages!
     $(obj).parent().parent().find(".validatorErrorMessage p").each(function() { // Make sure to ascend "two" levels in the DOM tree
          for (i=0; i<error_message.length; i++) {
               if (error_message[i]) {
                    if (!error_message[i].empty()) {
                         if ($(this).html() == error_message[i]) {
                              error_message[i] = "";
                         }
                    }
               }
          }
     });
     
     // Assemble error message HTML
     var html = '<div class="validatorErrorMessage">';
     for (i=0; i<error_message.length; i++) {
          if (error_message[i]) {
               if (!error_message[i].empty()) {
                    html += '<p>';
                    html += error_message[i];
                    html += '</p>';
               }
          }
     }
     html += '</div>';
     
     // Return HTML
     return html;
}