/*	see validate_test.js for an example	SETUP FOR FORM VALIDATION		1. include this script in your page	2. add onsubmit="return validate('formname',validate_settings)" to every form you wish to validate	3. create a validate_settings variable in the page to specify which things to check for	AVAILABLE SUBFUNCTIONS		not_blank -- make sure a field has something in it, or that a menu is set (the value of the "unset" option of menus should be -1 for this to work)	not_blank_menu -- make sure one element of a popup menu is selected (preferred over not_blank for menus)	not_blank_radio -- make sure one element of a radio button is selected	not_blank_checkbox -- make sure one element of a checkbox is selected	not_zero -- for numeric values, make sure the value is not zero	no_letters -- require that a field contain no letters (punctuation is okay)	no_numbers -- require that a field contain no numbers (punctuation is okay)	no_punctuation -- require that a field contain no punctuation	some_caps -- encourage proper capitalization	allowed -- specify which characters are allowed in the field			   allowed_1234\. allows only the numbers 1, 2, 3, 4 and a dot			   (actually, Netscape doesn't like slashes, even when escaped -- can we work around this in a future version?)	length -- check for a length range or list of possible lengths (counts letters and numbers only)			  also counts the length of a checkbox array			  length_6 requires 6 characters, length_1-12 requires between 1 and 12 characters, length_1|3|5 requires 1, 3, or 5 characters	email_characters -- check for various requirements of a valid email address	credit_card -- check for the proper lengths and required characters of each type of credit card (ignore punctuation)		      	   this assumes a field named card_type is also present on the form	taxexempt_format -- check if the value has a valid tax exempt ID number format (Exxxx-xxxx-xx)	SSN_format -- check if the value has a valid social security number format (xxx-xx-xxxx)			REGULAR EXPRESSION SYMBOLS USED IN THE SUBFUNCTIONS	\w matches alphanumeric, including "_".	\W matches non-alphanumeric (i.e., punctuation) 	\b matches word boundaries	\B matches non-boundaries 	\s matches whitespace	\S matches non-whitespace 	\d matches numeric	\D matches non-numeric 			VERSION HISTORY		01/19/02 - Initial development	10/21/02 - Added not_blank_menu, not_blank_radio, and not_blank_checkbox subfunctions; made card type switch not case-sensitive; added a setting to allow card_type to be a popup menu or a radio button	11/11/02 - Fixed get_checkbox_value and get_menu_value, added get_menu_text, tweaked focus on not_blank_menu to avoid errors		TO DO - make length count checkbox arrays*/// offer a few site-wide settings	var card_type_style = "menu"; // possible values are menu and radio// parse the validate settings and trigger all the other functions	function validate(form_name, validate_settings) {		validate_report = "";		field_name_focus = "";				fields_count = validate_settings.length / 3;		for (i=0; i<fields_count; i++) {			field_name = validate_settings[i*3];			field_label = validate_settings[(i*3)+1];			field_settings = validate_settings[(i*3)+2];									if (field_settings.indexOf("not_blank_menu") != -1) {				field_value = get_menu_value(form_name, field_name);			} else if (field_settings.indexOf("not_blank_radio") != -1) {				field_value = get_radio_value(form_name, field_name);			} else if (field_settings.indexOf("not_blank_checkbox") != -1) {				field_value = get_checkbox_value(form_name, field_name);			} else {				eval("field_value = document."+form_name+"."+field_name+".value");			}																										// strip quotes from the field_value; is there any other way to keep the following lines from breaking?			field_value = field_value.replace(/(["'])/g,"\\$1");						field_settings = field_settings.replace(/,\s+/g,",");			field_settings = field_settings.split(",");			settings_count = field_settings.length;									for (j=0; j<settings_count; j++) {				function_name = field_settings[j];								// don't bother checking if the field is blank (unless we're checking not_blank!)				if ((function_name.indexOf("not_blank") != -1)||((field_value.replace(/\s/g,"") != "")&&(field_value.replace(/\s/g,"") != "-1"))) {					if (function_name.indexOf("length_") == 0) {						// do some special parsing for the length function						length_settings = function_name.substr(7,function_name.length)						eval("lengthx('"+field_value+"','"+length_settings+"')");					} else if (function_name.indexOf("allowed_") == 0) {						// do some special parsing for the allowed function						allowed_characters = function_name.substr(8,function_name.length)						eval("allowed('"+field_value+"','"+allowed_characters+"')");					} else if (function_name.indexOf("credit_card") == 0) {						// send the card_type value to the credit_card function						//eval("card_type = document."+form_name+".card_type.options[document."+form_name+".card_type.selectedIndex].text");						if (card_type_style == "menu") {							card_type = get_menu_text(form_name, "card_type");						} else {							// for this to return user-friendly results, you need to set your card IDs to words rather than numbers;							// this isn't a problem with menus because there you can have an ID (option.value) -and- a human-readable name (option.text)							card_type = get_radio_value(form_name, "card_type");						}						eval("credit_card('"+field_value+"','"+card_type+"')");					} else {						eval(function_name+"('"+field_value+"')");					}								}			}		}				if (validate_report == "") {			return true;		} else {			alert(validate_report);			if (field_name_focus) { eval("document."+form_name+"."+field_name_focus+".focus()"); }			return false;		}	}	// make sure a field has something in it, or that a menu is set (the value of the "unset" option of menus should be -1 for this to work)	function not_blank(field_value) {		field_value = field_value.replace(/\s/g,"");		if ((field_value == "")||(field_value == "-1")) { // we could take out the -1 but for backwards compatibility with popup menus			validate_report += field_label + " needs a value\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// make sure one element of a popup menu is selected	function not_blank_menu(field_value) {		field_value = field_value.replace(/\s/g,"");		if ((field_value == "")||(field_value == "-1")) {			validate_report += field_label + " needs a value\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// make sure one element of a radio button is selected	function not_blank_radio(field_value) {		field_value = field_value.replace(/\s/g,"");		if (field_value == "") {			validate_report += field_label + " needs a value\n";			if (! field_name_focus) { field_name_focus = field_name + "[0]"; }		}	}// make sure one element of a checkbox is selected	function not_blank_checkbox(field_value) {		field_value = field_value.replace(/\s/g,"");		if (field_value == "") {			validate_report += field_label + " needs a value\n";			if (! field_name_focus) { field_name_focus = field_name + "[0]"; }		}	}// for numeric values, make sure the value is not zero		function not_zero(field_value) {		field_value = parseFloat(field_value);		if (field_value == 0) {			validate_report += field_label + " needs a value\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// require that a field contain no letters (punctuation is okay)	function no_letters(field_value) {		field_value_compare = field_value.replace(/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]/g,""); // remove all letters		if (field_value.length != field_value_compare.length) {			validate_report += field_label + " should only contain numbers\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// require that a field contain no numbers (punctuation is okay)	function no_numbers(field_value) {		field_value_compare = field_value.replace(/\d/g,""); // remove all numbers		if (field_value.length != field_value_compare.length) {			validate_report += field_label + " should not contain numbers\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// require that a field contain no punctuation	function no_punctuation(field_value) {		field_value_compare = field_value.replace(/\W/g,""); // remove all punctuation, except underscores		field_value_compare = field_value.replace(/_/g,""); // remove underscores		if (field_value.length != field_value_compare.length) {			validate_report += field_label + " should not contain numbers\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// encourage proper capitalization	function some_caps(field_value) {		field_value_compare = field_value.replace(/[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]/g,"");		if (field_value_compare.length < field_value.length) { // don't bother checking if there aren't any letters			field_value_compare = field_value.toLowerCase(); // change to all lowercase			if (field_value == field_value_compare) {				validate_report += "Please use normal capitalization in "+field_label+" and elsewhere\n";				if (! field_name_focus) { field_name_focus = field_name; }			}		}	}// specify which characters are allowed in a field// allowed_1234\. allows only the numbers 1, 2, 3, 4 and a dot	function allowed(field_value,allowed_characters) {		eval("field_value = field_value.replace(/["+allowed_characters+"]/g,'');")		if (field_value != "") {			validate_report += field_label + " can't contain the characters '" + field_value + "'\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// check for a length range or list of possible lengths (counts letters and numbers only)// also counts the length of a checkbox array// length_6 requires 6 characters, length_1-12 requires between 1 and 12 characters, length_1|3|5 requires 1, 3, or 5 characters	function lengthx(field_value,length_settings) {		field_value = field_value.replace(/\W/g,""); // ignore punctuation		if (length_settings.indexOf("-") != -1) {			length_settings = length_settings.split("-");			min = parseInt(length_settings[0]);			max = parseInt(length_settings[1]);			if ((field_value.length < min)||(field_value.length > max)) {				validate_report += field_label + " should be between "+min+" and "+max+" characters long\n";				if (! field_name_focus) { field_name_focus = field_name; }			}		} else if (length_settings.indexOf("|") != -1) {			length_settings = length_settings.split("|");			success = 0;			oks = "";			for (k=0; k<length_settings.length; k++) {				ok = parseInt(length_settings[k]);				if (field_value.length == ok) {					success = 1;					break;				}				if (k < length_settings.length - 1) {					if (length_settings.length > 2) {						oks += ok + ", ";					} else {						oks += ok + " ";					}				} else {					oks += "or " + ok;				}			}			if (success == 0) {				validate_report += field_label + " should be "+oks+" characters long\n";				if (! field_name_focus) { field_name_focus = field_name; }			}		} else {			ok = parseInt(length_settings)			if (field_value.length != ok) {				validate_report = field_label + " should be "+ok+" characters long\n";				if (! field_name_focus) { field_name_focus = field_name; }			}		}	}// check for various requirements of a valid email address	function email_characters(field_value) {					// checks for legal characters (@-._aZ09), characters that can't start the address,		// characters that can't be together, only one @ symbol, legal characters after the @ (aZ09.-)		check_general = /[^@\-\.\w_]|^[_@\.\-]|[@\._\-]{2}|(@)[^@]*\1|@[\w\-.]{1,}_/;				// checks for at least one a-Z or 0-9 between the @ and the .		check_domain = /@[\w\-]{1,}\./;				// checks for two-, three- or four- character TLD (e.g. .de, .com, .info)		check_TLD = /\.[a-zA-Z]{2,4}$/;		if (((field_value.search(check_general) != -1)||(field_value.search(check_domain)) == -1)||(field_value.search(check_TLD) == -1)) {			validate_report += field_label + " does not contain a valid email address\n";			if (! field_name_focus) { field_name_focus = field_name; }		}		}// check for the proper lengths and required characters of each type of credit card (ignore punctuation)// this assumes a field named card_type is also present on the form	function credit_card(field_value,card_type) {		if (card_type.indexOf("...") == -1) {			field_value = field_value.replace(/[^\d]/g,"");  // remove all but numbers			success = 1;			switch (card_type.substr(0,3).toLowerCase()) {				case "vis" :					// Visa: 16 or 13 digits long, first digit is 4					if (!((field_value.length == 16)||(field_value.length == 13))||!(parseInt(field_value.substr(0,1)) == 4)) {						success = 0;					}					break;				case "mas" :					// Mastercard: 16 digits long, first digit is 5, second digit is between 1 and 5 inclusive					if (!(field_value.length == 16)||!((parseInt(field_value.substr(0,1)) == 5)&&(parseInt(field_value.substr(1,1)) >= 1)&&(parseInt(field_value.substr(1,1)) <= 5))) {						success = 0;					}					break;				case "dis" :					// Discover: 16 digits long, first four digits are 6011					if (!(field_value.length == 16)||!(parseInt(field_value.substr(0,4)) == 6011)) {						success = 0;					}					break;				case "ame" :					// American Express: 15 digits long, first digit is 3, second digit is 4 or 7					if (!(field_value.length == 15)||!((parseInt(field_value.substr(0,1)) == 3)&&((parseInt(field_value.substr(1,1)) == 4)||(parseInt(field_value.substr(1,1)) == 7)))) {						success = 0;					}					break;				case "din" :					// Diner's Club: 14 digits long, first digit is 3, second digit is 0, 6, or 8					if (!(field_value.length == 14)||!((parseInt(field_value.substr(0,1)) == 3)&&((parseInt(field_value.substr(1,1)) == 0)||(parseInt(field_value.substr(1,1)) == 6)||(parseInt(field_value.substr(1,1)) == 8)))) {						success = 0;					}					break;				case "car" :					// Carte Blanche: 14 digits long, first digit is 3, second digit is 0, 6, or 8					if (!(field_value.length == 14)||!((parseInt(field_value.substr(0,1)) == 3)&&((parseInt(field_value.substr(1,1)) == 0)||(parseInt(field_value.substr(1,1)) == 6)||(parseInt(field_value.substr(1,1)) == 8)))) {						success = 0;					}					break;				case "enr" :					// EnRoute: 15 digits long, first four digits are 2014 or 2149					if (!(field_value.length == 15)||!((parseInt(field_value.substr(0,4)) == 2014)||(parseInt(field_value.substr(0,4)) == 2149))) {						success = 0;					}					break;				case "jcb" :					// EnRoute: 16 digits long, first four digits are 3088, 3096, 3112, 3158, 3337, or 3528					if (!(field_value.length == 16)||!((parseInt(field_value.substr(0,4)) == 3088)||(parseInt(field_value.substr(0,4)) == 3096)||(parseInt(field_value.substr(0,4)) == 3112)||(parseInt(field_value.substr(0,4)) == 3158)||(parseInt(field_value.substr(0,4)) == 3337)||(parseInt(field_value.substr(0,4)) == 3528))) {						success = 0;					}					break;				default : 					validate_report += card_type + " is not a valid credit card type\n";					break;			}			if (! success) {				validate_report += field_label + " is not a valid "+card_type+" number\n";				if (! field_name_focus) { field_name_focus = field_name; }			}		} else {			validate_report += field_label + " needs an associated card type\n";		}	}// check if the value has a valid tax exempt ID number format (Exxxx-xxxx-xx)	function taxexempt_format(field_value) {		field_value = field_value.replace(/E\d{4}-\d{4}-\d{2}/,"okay");		if (field_value != "okay") {			validate_report += field_label + " is not a valid tax exempt ID\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}// check if the value has a valid social security number format (xxx-xx-xxxx)	function SSN_format(field_value) {		field_value = field_value.replace(/\d{3}-\d{2}-\d{4}/,"okay");		if (field_value != "okay") {			validate_report += field_label + " is not a valid SSN\n";			if (! field_name_focus) { field_name_focus = field_name; }		}	}	// return the texts of the selected menu items	function get_menu_text(form_name, field_name) {		eval("this_element = document."+form_name+"."+field_name+".options");		selected_texts = new Array();		for (k=0; k<this_element.length; k++) {			if (this_element[k].selected) {				//selected_texts.push(this_element[k].text); // why doesn't this line work? ("object doesn't support...")				selected_texts[selected_texts.length] = this_element[k].text;			}		}		selected_texts = selected_texts.join(",");		return selected_texts;	}// return the values of the selected menu items (not_blank works on some, but not all, browsers, so this is safer)	function get_menu_value(form_name, field_name) {		eval("this_element = document."+form_name+"."+field_name+".options");		selected_values = new Array();		for (k=0; k<this_element.length; k++) {			if (this_element[k].selected) {				//selected_values.push(this_element[k].value); // why doesn't this line work? ("object doesn't support...")				selected_values[selected_values.length] = this_element[k].value;			}		}		selected_values = selected_values.join(",");		return selected_values;	}// return the value of the selected radio button	function get_radio_value(form_name, field_name) {		eval("this_element = document."+form_name+"."+field_name);		for (k=0; k<this_element.length; k++) {			if (this_element[k].checked) {				selected_value = this_element[k].value;				return selected_value;			}		}		return "";	}// return the values of the selected checkboxes as a comma-delimited list	function get_checkbox_value(form_name, field_name) {		eval("this_element = document."+form_name+"."+field_name);		selected_values = new Array();		for (k=0; k<this_element.length; k++) {			if (this_element[k].checked) {				//selected_values.push(this_element[k].value); // why isn't this line working? ("object doesn't support...")				selected_values[selected_values.length] = this_element[k].value;			}		}		selected_values = selected_values.join(",");		return selected_values;	}/*	would this be a better way to format the validate_settings variable?		validate_settings = "				name: not_blank, letters_only;				phone: not_blank, numbers_only;				email: not_blank, email;				card_number: not_blank, numbers_only;			"*/