/* ------------------------------------------------------------
 * PROJECT        : FHSC Interface Standard
 * FILENAME       : jqformsblur.js
 * ------------------------------------------------------------
 * DATE CREATED   : 11 Sep 2008
 * LAST UPDATED   : 25 Sep 2008
 * ------------------------------------------------------------
 * AUTHOR(S)      : Kevin Scholl (http://www.ksscholl.com/)
 * ------------------------------------------------------------ */

/* ------------------------------------------------------------
 * JQUERY PLUGINS
 * ------------------------------------------------------------ */

// toggle default value and coloring on form field focus/blur
// usage: $("#elementID").toggleActive(settings);
jQuery.fn.toggleActive = function(settings) {
	settings = jQuery.extend({
		focusBG   : "#F6F6F6",
		focusFG   : "#000",
		blurBG    : "#FFF",
		blurFG    : "#333",
		toggleVal :  false
		}, settings);
	this.each(function() {
		$(this)
		  .css("border","1px solid #7F9DB9")
			.focus(function() {
				$(this).css({ backgroundColor: settings.focusBG, color: settings.focusFG });
				if (settings.toggleVal == true && this.value == this.defaultValue && this.value != "http://") {
					this.value = "";
					}
				})
			.blur(function() {
				$(this).css({ backgroundColor: settings.blurBG, color: settings.blurFG });
				if (settings.toggleVal == true && this.value == "") {
					this.value = this.defaultValue;
					}
				});
		if ($(this).is("select"))
		  $(this).css("padding","1px")
		});
	};

// attaches a character counter to each textarea element in the jQuery object
// usage: $("#elementID").charCounter(max, settings);
// copyright (c) 2007 Tom Deater (http://www.tomdeater.com)
// minor alterations Kevin Scholl (http://www.ksscholl.com)
jQuery.fn.charCounter = function(max, settings) {
	max = max || 255;
	settings = $.extend({
		container: "<span style=\"display: block\">",
		classname: "example",
		format: "(%1 / " + max + " characters left)",
		pulse: true
		}, settings);
	var p;
	
	function count(el, container) {
		el = $(el);
		if (el.val().length > max) {
			el.val(el.val().substring(0, max));
			if (settings.pulse && !p) {
				pulse(container, true);
				};
			};
		container.html(settings.format.replace(/%1/, (max - el.val().length)));
		};
	
	function pulse(el, again) {
		if (p) {
			window.clearTimeout(p);
			p = null;
			};
		el.animate({ opacity: 0.1 }, 100, function() {
			$(this).animate({ opacity: 1.0 }, 100);
			});
		if (again) {
			p = window.setTimeout(function() { pulse(el) }, 200);
			};
		};
	
	return this.each(function() {
		var container = (!settings.container.match(/^<.+>$/)) 
			? $(settings.container) 
			: $(settings.container)
				.insertAfter(this)
				.addClass(settings.classname);
		$(this)
			.bind("keydown", function() { count(this, container); })
			.bind("keypress", function() { count(this, container); })
			.bind("keyup", function() { count(this, container); })
			.bind("focus", function() { count(this, container); })
			.bind("mouseover", function() { count(this, container); })
			.bind("mouseout", function() { count(this, container); })
			.bind("paste", function() { 
				var me = this;
				setTimeout(function() { count(me, container); }, 10);
				});
		if (this.addEventListener) {
			this.addEventListener('input', function() { count(this, container); }, false);
			};
		count(this, container);
		});
	
	};		

/* ------------------------------------------------------------
 * 2 COLUMN FORMS
 * ------------------------------------------------------------ */

// toggle user option links
function toggleEditSave(thisLink) {
	$(thisLink)
	  .html($(thisLink).html() == "Edit Info" ? "Save App" : "Edit Info")
	  .attr("class",$(thisLink).attr("class") == "linkEdit" ? "linkSave" : "linkEdit");
	}
function toggleOptionalFields(thisLink) {
	$(thisLink)
	  .html($(thisLink).html() == "Hide Optional Fields" ? "Show Optional Fields" : "Hide Optional Fields")
		.parents("fieldset")
		  .find("ol:not(.actionBtns)")
			.find("li:not(:has(label.required))").toggle();
	}

/* ------------------------------------------------------------
 * FORM OPTIONS
 * ------------------------------------------------------------ */

function selectOption(selBox,textBox){
	var selBoxID = $(selBox).attr("id");
  $("#" + textBox).attr("value",$("#" + selBoxID + " :selected").text());
	}

function addOption(textBox,selBox){
	newOpt  = $("#" + textBox).attr("value");
	if (newOpt)
		// $("#" + selBox).prepend('<option value="' + newOpt + '">' + newOpt + '</option>'); // add to beginning of list
		$("#" + selBox).append('<option value="' + newOpt + '">' + newOpt + '</option>'); // add to end of list
	else {
	  alert("Please enter a new value to transfer...");
		$("#" + textBox).focus();
		}
	}

function removeOption(selBox){
	$("#" + selBox + " :selected").remove();
	}

function moveOption(selSrc,selDst){
  // if at least one option is selected...
  if ($('#' + selSrc)[0].selectedIndex != -1)
	  $('#' + selSrc + ' :selected').remove().appendTo('#' + selDst);
	// ...and if not, alert the user to select one
	else
	  alert("Please select an option from a list.");
	}
	
function moveAllOptions(selSrc,selDst){
	for (i = 0; i < $('#' + selSrc)[0].options.length; i++) {
	  $('#' + selSrc)[0].options[i].selected = "selected";
	  }
  moveOption(selSrc,selDst);
  }

function arrangeOption(selSrc,dir){
  var selList = $('#' + selSrc)[0];
	var selOption = selList.selectedIndex;
	if (selOption < 0)
	  alert("Please select an item in the list.");
	else {
		if(dir == "up" && selOption == 0)
			alert("Already at the top!");
		if(dir == "down" && selOption == selList.options.length - 1)
			alert("Already at the bottom!");
		var toMoveC = selList.options[selOption];
		var optC = new Option(toMoveC.text,toMoveC.value,false,false);
		if(dir == "up" && selOption > 0) {
			var toMoveP = selList.options[selOption - 1];
			var optP = new Option(toMoveP.text,toMoveP.value,false,false);
			selList.options[selOption] = optP;
			selList.options[selOption - 1] = optC;
			selList.selectedIndex = selOption - 1;
			}
		if(dir == "down" && selOption < selList.options.length - 1) {
			var toMoveN = selList.options[selOption + 1];
			var optN = new Option(toMoveN.text,toMoveN.value,false,false);
			selList.options[selOption] = optN;
			selList.options[selOption + 1] = optC;
			selList.selectedIndex = selOption + 1;
			}
		}
	}

/* ------------------------------------------------------------
 * FORM VALIDATION
 * ------------------------------------------------------------ */

var HAS_ERRORS   = false;
var HAS_WARNINGS = false;
	
function jqResetForm(frm) {
	$(":text, :password, textarea, select").css("borderColor","#7F9DB9");
	$("#vMessages p").remove();
	$("span.msgLevelError, span.msgLevelWarn").remove();
	$("label.valid").removeClass("valid");
	$("fieldset *").removeClass("errorRow warningRow");
	HAS_ERRORS   = false;
  HAS_WARNINGS = false;
	}

function displayError(foo, theMsg) {
	removeValid(foo);
	$(foo).parent().addClass("errorRow").append("<span class=\"msgLevelError\">" + theMsg + "</span>");
	$(foo).siblings("input").not(".noValidation").css("borderColor","#C33");
	HAS_ERRORS = true;
	}

function displayWarning(foo, theMsg) {
	removeValid(foo);
	$(foo).parent().addClass("warningRow").append("<span class=\"msgLevelWarn\">" + theMsg + "</span>");
	$(foo).siblings("input").css("borderColor","#FF8E00");
	HAS_WARNINGS = true;	
	}

function displayValid(foo) {
	$(foo).parent().removeClass("errorRow warningRow");
	$(foo).siblings("input").css("borderColor","#7F9DB9");
	$(foo).siblings("span.msgLevelError, span.msgLevelWarn").remove();
	$(foo).addClass("valid");
	}
	
function removeValid(foo) {
	$(foo).parent().removeClass("errorRow warningRow");
	$(foo).siblings("input").css("borderColor","#7F9DB9");
	$(foo).siblings("span.msgLevelError, span.msgLevelWarn").remove();
	$(foo).removeClass("valid");
	}

function validateRadio(foo) {
	rGrpName  = $(foo).attr("name");
	rGrpValue = $("input[name='" + rGrpName + "']:checked").val();
	if (rGrpValue == "" || rGrpValue == null)
		displayError($(foo).siblings("label"),"ERROR: Required field(s).");
	else
		displayValid($(foo).siblings("label"));
	}

function validateRequired(foo) {
	if ($(foo).val() == "" || $(foo).val() == null) {
		removeValid($(foo).siblings("label"));
		displayError($(foo).siblings("label"),"ERROR: Required field(s).");
		}
	else
		displayValid($(foo).siblings("label"));
	}
	
function validateDate(lbl,dateFormat) {
	var dt = $(lbl).siblings("input").val();
	if (dt != "")	{ // if data is entered, check validity and formatting
		switch (dateFormat) {
			case "mm-dd-yyyy":  // format mm-dd-yyyy, ex. 02-06-2008
				datereg = /[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/;
				break;
			case "m/d/y":  // format m/d/y, ex. 2/6/08
				datereg = /[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2}$/;
				break;
			case "m-d-y":  // format m-d-y, ex. 2-6-08
				datereg = /[0-9]{1,2}\-[0-9]{1,2}\-[0-9]{2}$/;
				break;
			default:       // format mm/dd/yyyy, ex. 02/06/2008
				datereg = /[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/;
				break;
			}
		if (!datereg.exec(dt)) {
			displayWarning(lbl,"Date must be formatted as " + dateFormat + ".");
			}
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	}

function validateEmail(lbl) {
	var emailLegal   = /[\s\(\)\<\>\,\;\:\\\/\"\[\]]/;
	var emailValid   = /^.+@.+\..{2,}$/;
	var curr_eml = $(lbl).siblings("input").val();
	var prev_eml = curr_eml;
	var prev_lbl = $(lbl).parent().prev().find("label").html();
	if (prev_lbl.indexOf("Email") != -1 || prev_lbl.indexOf("E-mail") != -1)
		prev_eml   = $(lbl).parent().prev().find("input").val();	
	if (curr_eml != "")	{ // if data is entered, check validity and formatting
		$(lbl).siblings("span.msgLevelError, span.msgLevelWarn").remove();
		if (emailLegal.exec(curr_eml)) // check for illegal characters
			displayWarning(lbl,"E-mail address contains illegal character(s).");
		else if (!emailValid.exec(curr_eml)) // check for proper formatting
			displayWarning(lbl,"E-mail address must be of valid format.");
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	if (   $(lbl).hasClass("valid") 
			&& $(lbl).parent().prev().find("label").hasClass("valid") 
			&& curr_eml != prev_eml) // check that emails match
		displayError(lbl,"ERROR: E-mail entries must match.");
	}

function validatePassword(lbl,passMin) {
	var curr_pw  = $(lbl).siblings("input").val();
	var prev_pw  = curr_pw;
	var prev_lbl = $(lbl).parent().prev().find("label").html();
	if (prev_lbl.indexOf("Password") != -1)
		prev_pw    = $(lbl).parent().prev().find("input").val();	
	if (curr_pw != "")	{ // if data is entered, check validity and formatting
		$(lbl).siblings("span.msgLevelError, span.msgLevelWarn").remove();
		if (curr_pw.length < passMin) // check password length
			displayWarning(lbl,"Password must be at least " + passMin + " characters.");
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	if (   $(lbl).hasClass("valid") 
			&& $(lbl).parent().prev().find("label").hasClass("valid") 
			&& curr_pw != prev_pw) // check that passwords match
		displayError(lbl,"ERROR: Password entries must match.");
	}

function validateSSN(lbl) {
	var ssn = "" 
		+ $(lbl).parent().children("input")[0].value 
		+ $(lbl).parent().children("input")[1].value 
		+ $(lbl).parent().children("input")[2].value;
	// populate (optional) hidden field with concatenated data
	if ($(lbl).parent().children("input")[3])
		$(lbl).parent().children("input")[3].value = ssn;
	if (ssn != "") {
		if (ssn.length != 9 || isNaN(ssn))
			displayWarning(lbl,"SSN must contain 9 numbers.");
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	}

function validateTelFax(lbl) {
	var num = "" 
		+ $(lbl).parent().children("input")[0].value 
		+ $(lbl).parent().children("input")[1].value 
		+ $(lbl).parent().children("input")[2].value;
	var num2 = num + $(lbl).parent().children("input")[3].value;
	// populate (optional) hidden field with concatenated data
	if ($(lbl).parent().children("input")[4])
		$(lbl).parent().children("input")[4].value = num2;
	if (num != "") {
		if (isNaN(num))
			displayWarning(lbl,"Number cannot contain alpha character(s).");
		else if (num.length != 10)
			displayWarning(lbl,"Number must be at least 10 digits (incl. area code).");
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	}

function validateZIP(lbl) {
	var zip = "" 
		+ $(lbl).parent().children("input")[0].value 
		+ $(lbl).parent().children("input")[1].value;
	// populate (optional) hidden field with concatenated data
	if ($(lbl).parent().children("input")[2])
		$(lbl).parent().children("input")[2].value = zip;
	if (zip != "") {
		if (isNaN(zip))
			displayWarning(lbl,"Zip/Postal Code cannot contain alpha character(s).");
		else if (zip.length != 5 && zip.length != 9)
			displayWarning(lbl,"Zip/Postal Code must contain 5 or 9 numbers.");
		else
			displayValid(lbl);
		}
	else if (!$(lbl).hasClass("required"))
		removeValid(lbl);
	}

// validate fields before submitting, display any errors/warnings
// usage: $("#elementID").jqValidateForm(settings);
jQuery.fn.jqValidate = function(settings) {
	settings = jQuery.extend({
		validateAt   : "both", // "blur" | "submit" | "both"
		dFormat      : "mm/dd/yyyy",
		passMin      :  8,
		msg_error    : "Please address the errors noted below...",
		msg_warning  : "Please address the warnings noted below..."
		}, settings);

	var MSG_ERROR    = "<p class=\"systemMessage msgLevelError\">" + settings.msg_error + "</p>";
	var MSG_WARNING  = "<p class=\"systemMessage msgLevelWarn\">" + settings.msg_warning + "</p>";
	
	$(":file, :password, :text, textarea").blur(function(){
		$(this).val($.trim($(this).val()));
		});

	// CHECK FIELDS DURING DATA ENTRY
	
	if (settings.validateAt == "blur" || settings.validateAt == "both") {

		// verify that required fields have data
		$("label.required").each(function() {
			$(this).siblings(":radio").blur(function(){
				validateRadio(this);
				});
			$(this).siblings(":file, :password, :text, select, textarea").not(".noValidation").blur(function(){
				validateRequired(this);
				});
			});
		
		// verify formatting
		$("label:contains('Date'), label:contains('DOB')").each(function() {
			$(this).siblings("input").blur(function() {
				validateDate($(this).siblings("label"),settings.dFormat);
				});
			});
		$("label:contains('Email'), label:contains('E-mail')").each(function() {
			$(this).siblings("input").blur(function() {
				validateEmail($(this).siblings("label"));
				});
			});
		$("label:contains('Password')").each(function() {
			$(this).siblings("input").blur(function() {
				validatePassword($(this).siblings("label"),settings.passMin);
				});
			});
		$("label:contains('Social Security'), label:contains('SSN')").each(function() {
			$(this).siblings("input").blur(function() {
				validateSSN($(this).siblings("label"));
				});
			});
		$("label:contains('Telephone'), label:contains('Phone'), label:contains('Facsimile'), label:contains('Fax')").each(function() {
			$(this).siblings("input").blur(function() {
				validateTelFax($(this).siblings("label"));
				});
			});
		$("label:contains('Zip'), label:contains('ZIP'), label:contains('Postal')").each(function() {
			$(this).siblings("input").blur(function() {
				validateZIP($(this).siblings("label"));
				});
			});

		}

	// CHECK FIELDS ON FORM SUBMIT

	if (settings.validateAt == "submit" || settings.validateAt == "both") {

		this.submit(function() {
	
			// trim spaces from beginning and end of free-entry field values
			$(this).find(":file, :password, :text, textarea").each(function(){	
				$(this).val($.trim($(this).val()));
				});
	
			// reset all error messages and indications
			jqResetForm($(this).attr("id"));
	
			// verify that required fields have data
			$("label.required").each(function() {
				$(this).siblings(":radio").each(function(){
					validateRadio(this);
					});
				$(this).siblings(":file, :password, :text, select, textarea").not(".noValidation").each(function(){
					validateRequired(this);
					});
				});
	
			// verify formatting
			$("label:contains('Date'), label:contains('DOB')").each(function() {
				if ( $(this).siblings().is("input") ) validateDate(this,settings.dFormat);
				});
			$("label:contains('Email'), label:contains('E-mail')").each(function() {
				if ( $(this).siblings().is("input, select, textarea") ) validateEmail(this);
				});
			$("label:contains('Password')").each(function() {
				if ( $(this).siblings().is("input") ) validatePassword(this,settings.passMin);
				});
			$("label:contains('Social Security'), label:contains('SSN')").each(function() {
				if ( $(this).siblings().is("input") ) validateSSN(this);
				});
			$("label:contains('Telephone'), label:contains('Phone'), label:contains('Facsimile'), label:contains('Fax')").each(function() {
				if ( $(this).siblings().is("input") ) validateTelFax(this);
				});
			$("label:contains('Zip'), label:contains('ZIP'), label:contains('Postal')").each(function() {
				if ( $(this).siblings().is("input") ) validateZIP(this);
				});
	
			// submit form or display errors
			if (!HAS_ERRORS && !HAS_WARNINGS) {
				alert("Validation PASSED!"); return false;
				// return true;
				}
			else {
				if (HAS_ERRORS)
					$("#vMessages").append(MSG_ERROR);
				if (HAS_WARNINGS)
					$("#vMessages").append(MSG_WARNING);
				window.scrollTo(0,0);
				// alert("Validation FAILED!");
				return false;
				}
				
			});
		}
  };
