/**
 * Validate: Check inputs before submit
 *
 * @copyright    2008 AZPixels
 * @version      2.0
 * @date         2008-01-21
 * @author       Brad Westfall <brad@azpixels.com>
 * @edit-date    2008-12-07
 * @edit-author  Brad Westfall <brad@azpixels.com>
 *
 */


/********************************
* Form Fill                     *
*********************************/

function form_fill(form_name) {

	// Get the form object
	fm = eval("document." + form_name);

	for (i = 0; i < form_fill_names.length; i++) {

		// Get Element Information
		element = eval("fm." + form_fill_names[i]);
		element_value = form_fill_values[i];

		// If the element exists
		if (element) {

			// Get the element type
			element_type = element.type

			// Undefined means probably a radio button sequence
			if (element_type == undefined) {

				// Find the radio button that matches our value
				for (j = 0; j < element.length; j++) {
					if (element[j].value == element_value) {element[j].checked = true} else {element[j].checked = false}
				}

			} else {

				// Set the value of the element type
				switch (element_type) {
					case "file":
						break;
					case "checkbox":
						if (element_value == element.value) {element.checked = true} else {element.checked = false}
						break;
					default:
						element.value = element_value;
						break;
				}

			}

		}

	}

}



/********************************
* Validate Form                 *
*********************************/

function validate(fm, error_color) {
	err = validate_form(fm, error_color);
	return form_is_good(err);
}


/** This function determines if the form can submit ********************/

function form_is_good(err) {

	// If the error string has a value
	if (err != "") {

		// Locate the notice div tag if available
		if (document.getElementById('notice')) {

			// Get notice div tag
			div_notice = document.getElementById('notice');

			// Break apart error message
			parts = err.split("\r\n");

			// Start error message string
			error_messages = "";

			// Loop error messages and build error message string
			for (i = 0; i < parts.length; i++) {
				if (parts[i] != "") {
					error_messages += "<span>" + parts[i] + "</span>";
				}
			}

			// Place message into the notice
			div_notice.innerHTML = "<p>" + error_messages + "</p>";

			// Change the notice classes
			div_notice.className = "notice notice-error";

			// Make the notice visible
			div_notice.style.display = 'block';

		} else {
			alert(err);
		}

		return false;

	} else {
		return true;
	}

}


/** This function checks every element in a form for errors ********************/

// The CLASS attribute of the form element is used to hold validation parameters as follows
// [title=]constraint|constraint|constraint_arg1,arg2

function validate_form(fm, error_color) {

	// Initial Variables
	var required_good = true;
	var form_elements = fm.elements;
	var err = "";
	var element_constraints = ""

	// Loop Form Elements
	for (i=0; i < form_elements.length; i++) {

		// Reset Element Variables
		element = form_elements[i];
		element_label = document.getElementById('lab_' + element.id);
		element_good = true;
		element_err = "";
		is_date = false;

		// Constraints
		if (document.getElementById('v_' + element.id)) {
			element_constraints = document.getElementById('v_' + element.id).innerHTML;
		} else {
			element_constraints = "";
		}

		// If the element has a constraints
		if (element_constraints != "") {

			// Cutt out excess white space for values that arent files
			if (element.type != 'file') {
				element.value = chop(element.value);
			}

			// Determine the title of the element and its constraints
			if (element_constraints.indexOf('=') == -1) {
				title = "";
				constraints = element_constraints.split('|');
			} else {
				title_constraints = element_constraints.split('=');
				title = title_constraints[0];
				constraints = title_constraints[1].split('|');
			}

			// Get Element Value
			val = element.value;

			// Loop Constraints
			for(j = 0; j < constraints.length; j++) {

				if (constraints[j] != "") {

					// Get the elements constraints, and arguments
					constraint_part = constraints[j].split('_');
					constraint = constraint_part[0];
					args = constraint_part[1];

					// If the element is a date
					// The 'required' constraint must go after the 'date' constraint for this to work
					if (constraint == "date") {

						is_date = true;

						// If the value of the element is unchanged
						if (val == 'MM/DD/YYYY') {

							// Reset to simulate null values
							val = "";
							element.value = "";

						} else {

							// Adjust date value to proper format
							element.value = make_good_date(val);

						}

					}


					// If the constraint is for Required
					if (constraint.toLowerCase() == "required") {

						// If the elment does not have a value
						if (!has_value(val)) {
							required_good = false;
							element_good = false
						}

						// If the element is a date and is empty, then the form will not submit
						// so we should set the date back to its default
						if (is_date && val == "") {
							element.value = "MM/DD/YYYY"
						}

					} else {

						// The value may or may not be optional but here we check to see if it is valid
						// if the value is present
						if (val != "") {

							// Check to see if this value matches with our constraint
							element_err = check_value(constraint, args, val, title);

							// Append errors to our main list of errors
							if (element_err != "") {
								err += element_err;
								element_good = false;
							}

						}

					}

				}


			} // End Loop Constraint


			// Since were dont looping the constraints of this element we will change the label color accordingly

			// Colorize Label
			highlight_label(element, element_good, error_color);

		}
	}

	// If any element triggered this variable then we stop the submit proccess
	if (required_good == false) {
		err = "You must fill out all required fields.\r\n" + err
	}

	// Return the form errors or NULL
	return err;
}


/** Highlight Labels ********************/

function highlight_label(element, element_good, error_color) {
	element_label = document.getElementById('lab_'+element.id)
	if (element_label != undefined) {
		if (!element_good) {
			if (!error_color) {
				var error_color = '#A32A1D';
			}
			element_label.style.backgroundColor = error_color;
			element_label.style.color = 'white';
		} else {
			//Defaults
			element_label.style.backgroundColor = '';
			element_label.style.color = '';
		}
	}
}



/********************************
* Check Form Values             *
*********************************/

/** Route constraints and values to appropriate functions with check_value ********************/

function check_value(constraint, args, val, val_title) {

	// Initial Variables
	constraint = constraint.toLowerCase();
	err = ""

	// Switch Constraint Validators
	switch (constraint) {

		// Regular Expression Validators

		case 'ca-postal':
			exp = /^[a-zA-Z0-9]{3} [a-zA-Z0-9]{3}$/;
			e_msg = 'Invalid Canadian Postal Code. Only letters and numbers are allowed in the format ### ###';
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'date':
			exp = /^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/;
			e_msg = "Invalid Date, Example: MM/DD/YYYY";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'domain':
			if (val.substr(0,4) == "www.") {
				return val_title + "Invalid Domain, Please dont use the www. in the domain, Example: yoursite.com";
			}
			exp = /^[\.a-zA-Z0-9-]+\.[a-zA-Z\.]{2,5}$/;
			e_msg = "Invalid Domain, Example: yoursite.com";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'email':
			exp = /^([a-zA-Z_0-9\-\.]+)@([a-zA-Z_0-9\.\-]+)\.[a-zA-Z\.]{2,5}$/;
			e_msg = "Invalid Email";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'english':
			exp = /^[\040-\176]+$/;
			e_msg = "Invalid Characters. Only standard English characters punctuation marks are allowed";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'no-tags':
			exp = /^[^<>]+$/;
			e_msg = "Invalid Text, This item doesnt allow for characters < and >";
			err = validate_regexp(val, val_title, exp, e_msg);
			break

		case 'number':
			exp = /^[0-9]+$/;
			e_msg = "Invalid Number, Must use digits 0-9 only";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'password':
			exp = /^[a-zA-Z0-9_-]{6,20}$/;
			e_msg = "Invalid Password, Must be between 6 and 20 characters and only numbers, letters, and some special characters";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'percent':
			exp = /^\.[0-9]{1,2}$/;
			e_msg = "Invalid Percent";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'phone':
			exp = /^([0-9]{3})\-([0-9]{3})\-([0-9]{4})$/;
			e_msg = "Invalid Phone, Example: 555-555-5555";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'price':
			exp = /^[0-9]*(\.[0-9]{1,2})?$/;
			e_msg = "Invalid Price, Must use digits and decimal only - no dollar sign allowed";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		case 'url':
			if (val.substr(0,4).toLowerCase() != "http") {
				return val_title + "Invalid URL. Must start with http or https";
			}
			exp = /^(http:\/\/|https:\/\/)+[\.a-zA-Z0-9-]+\.[a-zA-Z\.]{2,5}[\S]*?$/;
			e_msg = "Invalid URL";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;;

		case 'us-zip':
			exp = /^([0-9]{5})$/;
			e_msg = "Invalid Zip, Must be five digits only";
			err = validate_regexp(val, val_title, exp, e_msg);
			break;

		// Custom Validators

		case 'compare':
			err = validate_compare(val, args);
			break;

		case 'video':
			err = validate_file_type(val, val_title, 'video')
			break;

		case 'audio':
			err = validate_file_type(val, val_title, 'audio')
			break;

		case 'image':
			err = validate_file_type(val, val_title, 'image')
			break;

	}

	return err;

}


/** Check Value Against Regular Expression ********************/

function validate_regexp(val, val_title, exp, e_msg) {


	// If were going to incorporate the title into the error message
	if (val_title != "") {
		val_title = val_title + " - ";
	}

	// Test value against expression
	if (!exp.test(val)) {
		return val_title + e_msg + "\r\n";
	} else {
		return "";
	}

}


/** Check Value Against Another Value ********************/

function validate_compare(val, args) {

	// For the compare constraint, the first argument is the custom message
	// and the second argument is the element to be compared to
	argument = args.split(',');
	message = argument[0];
	compare_element_name = argument[1];

	// Get the element we are comparing to
	compare_element = document.getElementsByName(compare_element_name);

	// If the values do not match
	if (val != compare_element[0].value) {
		return message + "\r\n";
	} else {
		return "";
	}
}


/** Check Value Against Extensions (Files Only) ********************/

function validate_file_type(val, val_title, filetype) {

	// If were going to incorporate the title into the error message
	if (val_title != "") {
		val_title = val_title + " - ";
	}

	// Switch our possible file groups
	// Make an array of possible extentions
	switch (filetype) {

		case 'video':
			var valid_ext_types = new Array('asf', 'avi', 'flv', 'mov', 'mp4', 'mpg', 'mpeg', 'ogg', 'wmv');
			break;

		case 'audio':
			var valid_ext_types = new Array('aiff', 'mp3', 'ogg', 'wma', 'wav');
			break;

		case 'image':
			var valid_ext_types = new Array('bmp', 'eps', 'gif', 'jpg', 'jpeg', 'pcd', 'pdf', 'png', 'tif', 'tiff');
			break;

	}

	// Get Extension of File
	filename_parts = val.split('.');
	extension = filename_parts.pop();

	// Assume bad extension until a good one is found
	is_valid_ext = false

	// Loop all of our valid extension types
	for (k in valid_ext_types) {

		// If the extension is in our valid list
		if (extension.toLowerCase() == valid_ext_types[k]) {
			is_valid_ext = true;
		}

	}

	// Return
	if (is_valid_ext) {
		return '';
	} else {

		// Make a string of valid extensions
		types_list = valid_ext_types.join(', ');

		// Return error message
		return val_title + 'Invalid File, valid file types are ' + types_list + "\r\n";

	}

}


/********************************
* Character Count               *
*********************************/

// Since JS and PHP handle new line character differently, this function will correct a body of
// text to be more like php's evaluation of counting characters
function fix_newlines_textarea(val) {

	// Adjust newlines so can do correct character counting for MySQL. MySQL counts a newline as 2 characters.
	if (val.indexOf('\r\n')!=-1) {

		// Return - this is IE on windows. Puts both characters for a newline, just what MySQL does. No need to alter
		return val;

	} else if (val.indexOf('\r')!=-1) {

		// This is IE on a Mac. Need to add the line feed
		val = val.replace ( /\r/g, "\r\n" );

	} else if (val.indexOf('\n')!=-1) {

		// This is Firefox on any platform. Need to add carriage return
		val = val.replace ( /\n/g, "\r\n" );

	} else {

		// Return - no newlines in the textarea
  		return val;

  	}

  // Return
  return val;

}


// Correct the value of a field that exceeds the max size
function char_count_correct(obj, max_chars) {

	my_text = fix_newlines_textarea(document.getElementById(obj.id).value);

	if (my_text.length > max_chars) {
		alert("This field may only have " + max_chars + " characters")
		document.getElementById(obj.id).value = my_text.substr(0, max_chars)
	}

	document.getElementById('chars_'+obj.id).className = "form-char-count-off";

}


// Report the character count as typed
function report_char_count(obj, max_chars) {

	num_chars = fix_newlines_textarea(document.getElementById(obj.id).value).length

	if (num_chars < max_chars) {
		document.getElementById('chars_'+obj.id).innerHTML = num_chars + "/" + max_chars + " Characters."
	} else {
		document.getElementById('chars_'+obj.id).innerHTML = "<font color='red'>" + num_chars + "/" + max_chars + " Characters.</font>"
	}

	document.getElementById('chars_'+obj.id).className = "form-char-count-on";

}


/********************************
* Form Date Functions           *
*********************************/

// If date has the default then clear
function date_clear(element) {
	if (element.value == "MM/DD/YYYY") {
		element.value = "";
	}
}

// Refill the date field with the default or corrected date
function date_fill(element) {
	if (element.value == "") {
		element.value = "MM/DD/YYYY";
	} else {
		element.value = make_good_date(element.value)
	}
}

// Turns a date into the format we want
function make_good_date(val) {

	//Replace other common delimiters with forward slash
	val = val.replace(/[-\.]/g,"\/")


	//If no delimiters were used, put some in
	num_exp = /^([0-9]{8})$/;

	if (num_exp.test(val)) {
		val = val.substr(0,2) + "/" + val.substr(2,2) + "/" + val.substr(4,4)
	}


	//If no leading zeros were used, put some in
	parts = val.split("/")

	// Make sure there is something in each index of the parts array
	if(parts[0] == undefined || parts[1] == undefined || parts[2] == undefined) {
		return val;
	}

	if (parts[0].length == 1) {
		parts[0] = "0" + parts[0]
	}

	if (parts[1].length == 1) {
		parts[1] = "0" + parts[1]
	}

	val = parts[0] + "/" + parts[1] + "/" + parts[2]



	// Return a nice date
	return val

}


/********************************
* Helper Functions              *
*********************************/

// Check to see if a value is null
function has_value(val) {

	if (val == "") {
		return false;
	} else {
		return true;
	}
}


// Truncate white space at the end/beginning of text
function chop(val){
	var tmp = ""
	var val_length = val.length;
	var val_length_minus_1 = val.length - 1;
	var i
	for (i = 0; i < val_length; i++) {
    		if (val.charAt(i) != ' ') {
			tmp += val.charAt(i)
		} else {
			if (tmp.length > 0) {
				if (val.charAt(i+1) != ' ' && i != val_length_minus_1) {
					tmp += val.charAt(i)
				}
			}
		}
	}

	return tmp
}