<!--
/*
  -------------------------------------------------------------------------------
 |  The content of this file constitutes Licensed Code.                          |
 |  Copyright (C) 2005-2007 Azalea Technology, LLC. All rights reserved.         |
 |-------------------------------------------------------------------------------|
 |  Unauthorized removal of this notice is considered a violation of the         |
 |  license agreement under which this Code may be used. This work is protected  |
 |  under United States copyright law and the similar law(s) of other countries  |
 |  under which such as work is afforded legal protection, and upon conviction   |
 |  of such a violation in a court of applicable jurisdiction, such person(s)    |
 |  may be subject to the maximum allowable penalty as permitted under such law. |
 |-------------------------------------------------------------------------------|
 |  You acknowledge and agree that information presented to you through this     |
 |  site (the "Web Site") is protected by all applicable copyrights, trademarks, |
 |  service marks, patents or other proprietary rights and laws, and by virtue   |
 |  of accessing the Web Site, except as expressly authorized by the Azalea      |
 |  Technology, LLC., you agree not to modify, rent, lease, loan, sell,          |
 |  distribute, store, or create derivative works based on the Web Site, in      |
 |  whole or in part.                                                            |
  -------------------------------------------------------------------------------|
 |  Decrypting or otherwise decoding the following programming language code is  |
 |  strictly prohibited except as expressly authorized by Azalea Technology,     |
 |  LLC. Upon conviction of such a violation in a court of applicable            |
 |  jurisdiction, such person(s) may be subject to the maximum allowable penalty |
 |  as permitted under such law.                                                 |
  -------------------------------------------------------------------------------
      Purpose: Form-independent form validation
   Programmer: B. Roberts
               Azalea Technology, LLC.
               P.O. Box 131150
               Tyler, TX 75713-1150
               903-581-4448
  -------------------------------------------------------------------------------
*/

// Unobtrusive implementation
// Do everything in this one anonymous function to avoid cluttering the global namespace
(function(){

	function validate_form(form_obj){

		// Check to make sure the target form exists
		if(!form_obj){
			alert("FORM ERROR: The form supplied does not exist. Please check the form name.");
			return false;
		}

		// Check to makes sure elements array of the target form exists
		if(!form_obj.elements){
			alert("FORM ERROR: The elements array of the form supplied could not be referenced. Please check the form name.");
			return false;
		}

		// Set the status of client-side javascript to "enabled" so that server-side formmail program will accept submission
		// Using this technique eliminates 99.9% of all Web form spam by forcing client-side javascript validation to take place
		if(form_obj._config_javascript_status){
			form_obj._config_javascript_status.value = "enabled";
		}

		// Define some variables to be used throughout the program
		var x = form_obj.elements;
		var message = "";
		var errors = 0;
		var valid;
		var displayname, validate, expectedformat, required, visualcue, setcase, errormsg;
		var dependentcondition, dependenterror;
		var suppress_warnings = false;
		var form_action;
		var file_extension_delimiter_location;
		var server_side_lang = null;

		// Get form validation configuration options
		if(form_obj._config_javascript_suppress_warnings){
			if(form_obj._config_javascript_suppress_warnings.value=="true") suppress_warnings = true;
			else suppress_warnings = false;
		}
		else suppress_warnings = false;

		// Check to see what server-side language is being used to process the form (e.g. PHP, ASP, ASPX, JSP, etc.) as this has an impact on
		// some server side behavior as it relates to check box and radio button groups
		form_action = form_obj.action;
		file_extension_delimiter_location = form_action.lastIndexOf(".");
		if(file_extension_delimiter_location != -1){
			server_side_lang = form_action.substr(file_extension_delimiter_location+1);
			server_side_lang = server_side_lang.toLowerCase();
		}
		else server_side_lang = "unknown";

		// Construct the beginning or header of the error message
		var heading;
			heading  = "Form Validation Error Message\n\n";
			heading += "Your information cannot be sent because of the \n";
			heading += "following errors. Please correct these errors \n";
			heading += "and try again. \n";
			heading += "_______________________________________________\n";

		// Read custom FORM tag attribute _locksubmit to determine if submit button should be locked
		// when form is submitted
		locksubmit = form_obj.getAttribute("_locksubmit");

		if(locksubmit != "" && locksubmit != null){
			locksubmit = locksubmit.toLowerCase();

			switch(locksubmit){
				case "true":
				case "yes":
				case "1":
				case "lock":
					// Determine the text label of the submit button on the form
					var button_text = "";
					if(form_obj.Submit){
						button_text = form_obj.Submit.value;
					}
					else if(form_obj._Submit){
						button_text = form_obj._Submit.value;
					}
					else if(form_obj._submit){
						button_text = form_obj._submit.value;
					}
					else{
						if(!suppress_warnings) alert("WARNING: The value of the name attribute of the submit button for your form should be \"Submit\", \"_Submit\" or \"_submit\".\nPlease check the value of the submit button name attribute.\nYou can suppress this warning using one of the configuration options available with this form validator.\nUse this option: _config_javascript_suppress_warnings");
					}
					if(isSpace(button_text)) button_text = "Submit";
					locksubmit = true;
					break;
				default:
					locksubmit = false;
					break;
			}
		}
		else{
			locksubmit = false;
		}

		// Lock the submit button on the form to prevent double submission
		if(locksubmit) toggleFormButtonLock(form_obj,true,"Processing...");

		// Loop through the elements array of the form and process the form using each element's custom attributes as directives for the element
		for(var i = 0; i < x.length; i++){
			validate = x[i].getAttribute("_validate");

			// Check to see if element should be validated
			if(validate){
				if(validate=="true") validate = true;
				else validate = false;
			}

			if(validate){

				// Collect the custom attributes
				displayname = x[i].getAttribute("_displayname");
				expectedformat = x[i].getAttribute("_expectedformat");
				visualcue = x[i].getAttribute("_visualcue");
				required = x[i].getAttribute("_required");
				setcase = x[i].getAttribute("_setcase");
				errormsg = x[i].getAttribute("_errormsg");
				dependentcondition = x[i].getAttribute("_dependentcondition");
				dependenterror = x[i].getAttribute("_dependenterror");

				// Check to see if the element should be cued visual in the event of an error
				if(visualcue){
					if(visualcue=="true") visualcue = true;
					else visualcue = false;
				}

				// Check to see if element should be considered a required field
				if(required){
					if(required=="true") required = true;
					else required = false;
				}

				// Determine the type of form element being processed
				switch(x[i].type){
					case "text":
					case "textarea":
					case "file":
					case "password":
					case "hidden":

						// Check the expected format for an acceptable value to the program
						if(expectedformat != "" && expectedformat != null){

							// Force attribute value to lowercase before checking value
							expectedformat = expectedformat.toLowerCase();

							switch(expectedformat){
								case "numeric":
								case "alphanumeric":
									break;

								case "string":
								case "text":
									expectedformat = "string";
									break;

								case "email":
								case "email address":
									expectedformat = "email";
									break;

								case "phone":
								case "phone number":
								case "telephone":
								case "telephone number":
									expectedformat = "phone";
									break;

								case "zip":
								case "zip code":
								case "postal code":
									expectedformat = "zip";
									break;

								case "dob":
								case "date of birth":
								case "birthday":
									expectedformat = "dob";
									break;

								case "date":
									expectedformat = "date";
									break;

								case "currency":
								case "money":
								case "usd":
									expectedformat = "currency";
									break;

								default:
									expectedformat = "string";
									break;
							}
						}
						else{
							expectedformat = "string";
						}

						// Validate the data according to the expected format
						switch(expectedformat){

							case "string":
								if(required) valid = !isSpace(x[i].value);
								else valid = true;

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Missing response for " + displayname;
									}
								}
								break;

							case "email":
								if(required) valid = validEmail(x[i].value);
								else valid = isSpace(x[i].value) ? true : validEmail(x[i].value);

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname;
									}
								}
								break;

							case "phone":
								if(required) valid = validTelephoneNumber(x[i].value);
								else valid = isSpace(x[i].value) ? true : validTelephoneNumber(x[i].value);

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname;
									}
								}
								break;

							case "zip":
								if(required) valid = isValidPostalCode("United States",x[i].value);
								else valid = isSpace(x[i].value) ? true : isValidPostalCode("United States",x[i].value);

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname;
									}
								}
								break;

							case "date":
								if(required) valid = validDate(x[i].value);
								else valid = isSpace(x[i].value) ? true : validDate(x[i].value);

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname;
									}
								}
								break;

							case "currency":
								if(required) valid = !isNaN(parseFloat(x[i].value));
								else valid = isSpace(x[i].value) ? true : !isNaN(parseFloat(x[i].value));

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname + "; follow this format: 0.00";
									}
								}
								break;

							case "dea number":
								if(required) valid = isValidDeaNumber(x[i].value);
								else valid = isSpace(x[i].value) ? true : isValidDeaNumber(x[i].value);

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Invalid or missing response for " + displayname;
									}
								}
								break;

							default:
								if(required) valid = !isSpace(x[i].value);
								else valid = true;

								if(!valid){
									errors++;
									if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
									else{
										if(!displayname) displayname = x[i].name;
										message += "\n(" + (errors) + ") Missing response for " + displayname;
									}
								}
								break;
						}

						// Check to make sure input is an expected value
						if(setcase != "" && setcase != null){

							// Force attribute value to lowercase before checking value
							setcase = setcase.toLowerCase();

							switch(setcase){
								case "u":
								case "uc":
								case "up":
								case "upper":
								case "uppercase":
								case "upper case":
									setcase = "upper";
									break;

								case "l":
								case "lc":
								case "low":
								case "lower":
								case "lowercase":
								case "lower case":
									setcase = "lower";
									break;

								case "p":
								case "pc":
								case "proper":
								case "propercase":
								case "proper case":
									setcase = "proper";
									break;

								default:
									setcase = "none";
									break;
							}
						}
						else{
							setcase = "none";
						}

						// Transform case if directive given to do so
						switch(setcase){
							case "upper":
								x[i].value = x[i].value.toUpperCase();
								break;
							case "lower":
								x[i].value = x[i].value.toLowerCase();
								break;
							case "proper":
								x[i].value = toProperCase(x[i].value);
								break;
						}

						// Trim additional space if need from element value
						if(x[i].value&&!isSpace(x[i].value)) x[i].value = trim(x[i].value);

						// Visually cue element as necessary and requested
						if(visualcue){
							try{
								if(!valid) set_class_name(x[i].id,"textbox_error");
								else set_class_name(x[i].id,"textbox");
							}
							catch(e){
								alert("FORM ERROR: field \"" + x[i].name + "\" does not have a corresponding id tag. Please check the form.");
							}
						}

						// Assign focus and select text in form element as needed
						try{
							if(!valid){
								x[i].focus();
								x[i].select();
							}
						}
						catch(e){
							// do nothing
						}

						break;

					case "checkbox":
						var checkbox_obj;
						var checkbox_name = x[i].name;

						// Determine whether this checkbox is part of a group or a single checkbox
						// If part of a group, identify the group object (array); otherwise select the single object
						if(eval("form_obj."+checkbox_name)) checkbox_obj = eval("form_obj."+checkbox_name);
						else checkbox_obj = x[i];

						//alert(checkbox_obj.length);

						if(required) valid = option_checked(checkbox_obj);
						else valid = true;

						if(!valid){
							errors++;
							if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
							else{
								if(!displayname) displayname = checkbox_obj.name;
								message += "\n(" + (errors) + ") You must select at least one option from " + displayname;
							}
						}
						break;

					case "radio":
						var radio_obj;
						var radio_name = x[i].name;

						// Determine whether this radio button is part of a group or a single radio button
						// If part of a group, identify the group object (array); otherwise select the single object
						if(eval("form_obj."+radio_name)) radio_obj = eval("form_obj."+radio_name);
						else radio_obj = x[i];

						if(required) valid = option_checked(radio_obj);
						else valid = true;

						if(!valid){
							errors++;
							if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
							else{
								if(!displayname) displayname = radio_obj.name;
								message += "\n(" + (errors) + ") You must select an option from " + displayname;
							}
						}
						break;

					case "select-one":
						if(required) valid = !isSpace(x[i].value);
						else valid = true;

						if(!valid){
							errors++;
							if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
							else{
								if(!displayname) displayname = x[i].name;
								message += "\n(" + (errors) + ") You must select an option from " + displayname;
							}
						}
						break;

					case "select-multiple":
						if(required) valid = !isSpace(x[i].value);
						else valid = true;

						if(!valid){
							errors++;
							if(errormsg) message += "\n(" + (errors) + ") " + errormsg;
							else{
								if(!displayname) displayname = x[i].name;
								message += "\n(" + (errors) + ") You must select at least one option from " + displayname;
							}
						}
						break;

					default:
						// this HTML element unknown and will not be validated
						break;

				}

				// This portion of the code executes some conditional expression(s) using the eval function in order to perform
				// conditional validation and execute other necessary javascript code
				if(dependentcondition){
					try{
						valid = eval(dependentcondition);
					}
					catch(e){
						valid = false;
					}
	
					if(valid){
						errors++;
						if(dependenterror) message += "\n(" + (errors) + ") " + dependenterror;
						else{
							if(!displayname) displayname = x[i].name;
							message += "\n(" + (errors) + ") There is a problem with " + displayname;
						}
					}
				}
			}
		}

		if(errors>0){
			// Set the status of client-side javascript to "disabled"  because there was an error in the form
			// Using this technique eliminates 99.9% of all Web form spam by forcing client-side javascript validation to take place
			if(form_obj._config_javascript_status) form_obj._config_javascript_status.value = "disabled";

			// Build the error message
			message = heading + message;
			message += "\n\n" + errors + " error";
			if(errors>1) message += "s";
			message += " detected";

			// Display the error message
			alert(message);

			// Unlock the form's submit button
			if(locksubmit) toggleFormButtonLock(form_obj,false,button_text);

			return false;
		}
		else if(errors<=0){
			if(form_obj.Email||form_obj.x_email){

				// Standard HTML forms use an email address field called "Email" and the checkout form uses an email
				// address field called "x_email" per the documentation on Authorize.Net's payment gateway.  This code
				// check to see which email field is being used
				var use_this_email_address;
				if(form_obj.Email) use_this_email_address = form_obj.Email.value;
				else use_this_email_address = form_obj.x_email.value;

				message  = "Reply-to Email Address Confirmation\n";
				message += "_______________________________________________\n\n";
				message += "Please confirm that:\n\n";
				message +=  use_this_email_address + " \n\n";
				message += "is your correct email address. Please note that\n";
				message += "this email address MUST be able to receive\n";
				message += "incoming internet email. Enter only ONE email\n";
				message += "address.\n\n";
				message += "Thank you,\n"+_ORG_FULL_NAME+"\n";
				message += "_______________________________________________\n\n";

				if(confirm(message)){

					// If PHP is the server-side language, loop through the elements array of the form and rename any checkbox or radio button groups
					// to use the PHP group naming convention  "[]"
					if(server_side_lang=="php"){
						for (var i=0;i<x.length;i++){
							if( ( x[i].type == "checkbox" || x[i].type == "radio") && x[i].name.lastIndexOf("[]") == -1){
								x[i].name = x[i].name+"[]";
							}
						}
					}

					return true;
				}
				else{

					// If PHP is the server-side language, loop through the elements array of the form and rename any checkbox or radio button groups that
					// are using the PHP group naming convention so that JavaScript can handle validation without errors
					if(server_side_lang=="php"){
						for (var i=0;i<x.length;i++){
							if( ( x[i].type == "checkbox" || x[i].type == "radio") && x[i].name.lastIndexOf("[]") != -1){
								x[i].name = x[i].name.substr(0,x[i].name.length-2);
							}
						}
					}

					if(locksubmit) toggleFormButtonLock(form_obj,false,button_text);
					return false;
				}
			}
			else{
				if(!suppress_warnings) alert("WARNING: The form supplied does not contain a commonly required form element named \"Email\". Please check the form.\nYou can suppress this warning using one of the configuration options available with this form validator.\nUse this option: _config_javascript_suppress_warnings");
			}
		}
	}

	// Assign appropriate "onsubmit" event handler for all forms within the document requiring validation
	function validate_form_initialize(){
		// Local variables
		var d = document;
		var validate = null;

		// Loop through all the forms within the document
		for(var x = 0; d.forms[x]; x++){

				// Get the value of custom, non-standard FORM tag attribute named _validate
				validate = d.forms[x].getAttribute("_validate");

				// Check _validate attribute value to see if event handler should be added to form
				if(validate != "" && validate != null){
					validate = validate.toLowerCase();

					switch(validate){
						case "true":
						case "yes":
						case "1":
						case "validate":
							d.forms[x].onsubmit = function(){ return validate_form(this); };
							break;
					}
				}

		}
	}

	// Add initialization to onload event handler (execute after document is loaded)
	Handler.add(window, "load", function(){ validate_form_initialize(); });

})();

//-->
