/*
---------------------------------------------------------------------------
			syntax of functions using the error object
---------------------------------------------------------------------------

		oErrMsg.initErrMsgs ();

		[call desired functions]

		if (oErrMsg.errMsgAdded == true) {
			oErrMsg.dispErrMsgs();
			oErrMsg.focusFirst();
			return false;
		}
		else {
			return true;
		}

*/

function ErrorMsgObj () {

	this.errMsgArray = new Array();
	this.errFieldArray = new Array();

	function errMsgsInit () {

		if (this.errMsgIndex > 0) {
			for (var n = 0; n < this.errMsgIndex; ++n) {
				var thisErr = document.getElementById("oErrMsg_"+this.errFieldArray[n].name);
				if (thisErr==undefined) thisErr = document.getElementById("oErrMsg_"+this.errFieldArray[n][0].name); //radio buttons
				while (thisErr.firstChild) {
					thisErr.removeChild(thisErr.firstChild);
				}
			}
		}

		this.errMsgArray.length = this.errMsgIndex = 0;
		this.errFieldArray.length = this.errMsgIndex = 0;
		this.errMsgAdded = false;
	}

	function errorMsgAdd (msg) {
		this.errMsgArray [this.errMsgIndex] = '' + msg + '';
		this.errMsgAdded = true;
	}

	function setErrorField(errField) {
		this.errFieldArray[this.errMsgIndex] = errField;
		if (this.errMsgArray.length == 1) this.errField = errField;
		this.errMsgIndex++;
	}

	function alertErrMsg () {
		for (var n = 0; n < this.errMsgIndex; ++n) {

			var newElement; var newTextNode;
			var thisErr = document.getElementById("oErrMsg_"+this.errFieldArray[n].name);
			if (thisErr==undefined) thisErr = document.getElementById("oErrMsg_"+this.errFieldArray[n][0].name); //radio buttons

			//newElement = document.createElement("label"); //can't put HTML in a createTextNode
			//newTextNode = document.createTextNode('\u00a0'); //&nbsp;
			//newElement.appendChild(newTextNode);
			//thisErr.appendChild(newElement);

			newTextNode = document.createTextNode(" * "+this.errMsgArray[n]);
			thisErr.appendChild(newTextNode);

			newElement = document.createElement("br");
			thisErr.appendChild(newElement);

			thisErr.style.padding = '0 0 5px 0';

		}
	}

	function setFocusOnFirstError() {
		var theField = this.errField;
		var eIndex = this.elementIndex(theField);
		if (eIndex > -1) var fieldType = theField.form.elements[eIndex].type;
		if (fieldType != "hidden" && fieldType != undefined) theField.focus();
	}

	function getElementIndex(obj) {
		var theform = obj.form;
		if (typeof(theform) != "undefined") {
			for (var i=0; i<theform.elements.length; i++) {
				if (obj.name == theform.elements[i].name) return i;
			}
		}
		return -1;
	}

	//declare object's functions to outbound names
    ErrorMsgObj.prototype.initErrMsgs = errMsgsInit;
    ErrorMsgObj.prototype.addErrorMsg = errorMsgAdd;
    ErrorMsgObj.prototype.dispErrMsgs = alertErrMsg;
	ErrorMsgObj.prototype.setError = setErrorField;
	ErrorMsgObj.prototype.focusFirst = setFocusOnFirstError;
	ErrorMsgObj.prototype.elementIndex = getElementIndex;

}

//---------------------------------------------------------------------------

var oErrMsg = new ErrorMsgObj();

//==========================================

function chkEmptyFld (fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		if (fld.value.length == 0) {
			oErrMsg.addErrorMsg ('You have not filled in the \'' + nam + '\'.');
			oErrMsg.setError(fld);
			return;
		}
		else if (fld.value == null) {
			oErrMsg.addErrorMsg ('You have not filled in the \'' + nam + '\'.');
			oErrMsg.setError(fld);
			return;
		}
		else {
			for (var i=0; i<fld.value.length; i++) {
				var ch = fld.value.charAt(i);
				if (ch != ' ' && ch != '\t') {
					break;
				}
				else {
					if ((i + 1) == fld.value.length) {
						oErrMsg.addErrorMsg ('You have not filled in the \'' + nam + '\'.');
						oErrMsg.setError(fld);
						break;
					}
				}
			}
		}
	}
}

//==========================================

function chkEmptyFldSpecial (fld) {
	if (fld) {	//Check that the field exists on the form first
		if (fld.value.length == 0) {
			oErrMsg.addErrorMsg ('you must fill in one of the above phone numbers');
			oErrMsg.setError(fld);
			return;
		}
		else if (fld.value == null) {
			oErrMsg.addErrorMsg ('you must fill in one of the above phone numbers');
			oErrMsg.setError(fld);
			return;
		}
		else {
			for (var i=0; i<fld.value.length; i++) {
				var ch = fld.value.charAt(i);
				if (ch != ' ' && ch != '\t') {
					break;
				}
				else {
					if ((i + 1) == fld.value.length) {
						oErrMsg.addErrorMsg ('you must fill in one of the above phone numbers');
						oErrMsg.setError(fld);
						break;
					}
				}
			}
		}
	}
}

//==========================================

function chkCheckbox(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		if (!fld.checked) {
			oErrMsg.addErrorMsg ('Please confirm \'' + nam + '\'.');
			oErrMsg.setError(fld);
			return;
		}
	}
}
//==========================================

function chkSelect (fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		if (fld.value == '') {
			oErrMsg.addErrorMsg ('Please make a selection above.');
			oErrMsg.setError(fld);
			return;
		}
	}
}

//==========================================

function chkPassword (fld1, nam1)
{
	var fieldVal = fld1.value;

	//check for existence of numbers
	var numArray=fieldVal.match(/[0-9]/g);
	var alphaArray=fieldVal.match(/[A-Z,a-z]/g);

	if (numArray==null || alphaArray==null)
	{
		oErrMsg.addErrorMsg ("The " + nam1 + " must contain letters (a-z) and numbers (0-9).");
		oErrMsg.setError(fld1);
	}

	if (fieldVal.length < 5)
	{
		oErrMsg.addErrorMsg ("The " + nam1 + " must be 5 characters or more in length.");
		oErrMsg.setError(fld1);
	}
}

//==========================================

function chkCompare (fld1, val1, nam1, val2, nam2, op) {
	if (!eval("'" + val1 + "'" + op + "'" + val2 + "'")) {
		var msg='';
		switch (op) {
			case '<':
				msg = 'be less than';
				break;
			case '<=':
				msg = 'be less than or equal to';
				break;
			case '>':
				msg = 'be greater than';
				break;
			case '>=':
				msg = 'be greater than or equal to';
				break;
			case '==':
				msg = 'be equal to';
				break;
			case '!=':
				msg = 'not be equal to';
				break;
			default:
				msg = op;
				break;
		}
		oErrMsg.addErrorMsg ('The \'' + nam1 + '\' must ' + msg + ' the \'' + nam2 + '\'.');
		oErrMsg.setError(fld1);
		return;
	}
}

//==========================================

function chkValidDate(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		var dateStr = fld.value;
		if (chkDate(dateStr)) {
			return true;
		}
		else {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' field is formatted incorrectly');
			oErrMsg.setError(fld);
			return false;
		}
	}
}

//---------------------------------------------------------------------------

function chkDate (fld) {
	if (fld) {	//Check that the field exists on the form first
		var datePat = /^(\d{4})(\/|-)(\d{1,2})(\/|-)(\d{1,2})$/;
		var matchArray = fld.match(datePat); // is the format ok?
	
		if (matchArray == null) return false;
	
		 // parse date into variables
		year = matchArray[1];
		month = matchArray[3];
		day = matchArray[5];
	
		if (month < 1 || month > 12) return false;
	
		if (day < 1 || day > 31) return false;
	
		if ((month==4 || month==6 || month==9 || month==11) && day==31) return false;
	
		if (month == 2) { // check for february 29th
			var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
			if (day > 29 || (day==29 && !isleap)) return false;
		}
	return true;
	}
}

//==========================================

function chkValidEmail(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		var emailStr = fld.value;
		if (chkEmailAddress(emailStr)) {
			return true;
		}
		else {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' field is formatted incorrectly');
			oErrMsg.setError(fld);
			return false;
		}
	}
}

//---------------------------------------------------------------------------

function chkEmailAddress(emailStr) {

	if (emailStr.length == 0 || emailStr == null) return false;

	var checkTLD=1;

	// http://www.iana.org/gtld/gtld.htm
	// knownDomsPat is a list of known domain suffixes larger than 2 characters in length
	var knownDomsPat=/^(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel)$/;

	var emailPat=/^(.+)@(.+)$/;
	var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
	var validChars="\[^\\s" + specialChars + "\]";
	var quotedUser="(\"[^\"]*\")";
	var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
	var atom=validChars + '+';
	var word="(" + atom + "|" + quotedUser + ")";
	var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
	var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
	var matchArray=emailStr.match(emailPat);

	if (matchArray==null) return false;

	var user=matchArray[1];
	var domain=matchArray[2];

	for (i=0; i<user.length; i++) {
		if (user.charCodeAt(i)>127) return false;
	}
	for (i=0; i<domain.length; i++) {
		if (domain.charCodeAt(i)>127) return false;
	}

	if (user.match(userPat)==null) return false;

	var IPArray=domain.match(ipDomainPat);
	if (IPArray!=null) {
		for (var i=1;i<=4;i++) {
			if (IPArray[i]>255) return false;
		}
	}

	var atomPat=new RegExp("^" + atom + "$");
	var domArr=domain.split(".");
	var len=domArr.length;
	for (i=0;i<len;i++) {
		if (domArr[i].search(atomPat)==-1) return false;
	}

	if (checkTLD && domArr[len-1].length!=2 && domArr[len-1].search(knownDomsPat)==-1) return false;

	if (len<2) return false;

	return true;
}

//==========================================

function chkValidPostal(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		var postal = fld.value;
		postal = postal.toUpperCase();
		var ch = postal.charAt(3);
	
		if (postal.length < 6 || postal.length > 7) {
			oErrMsg.addErrorMsg('The \''+nam+'\' is not in a valid format (X9X9X9 or X9X 9X9)');
			oErrMsg.setError(fld);
			return;
		}
		else if (postal.length == 7) {
			var ch = postal.charAt(3);
			if (ch == ' ') {
				postal = postal.substring(0,3) + postal.substring(4);
			}
			else {
				oErrMsg.addErrorMsg('The \''+nam+'\' is not in a valid format (X9X9X9 or X9X 9X9)');
				oErrMsg.setError(fld)
				return;
			}
		}
	
		for (var i = 0; i<postal.length; i++) {
			var ch = postal.charAt(i);
			if (i == 0 || i == 2 || i == 4) {
				if (ch < 'A' || ch > 'Z') {
					// it is not a letter
					oErrMsg.addErrorMsg ('The \''+nam+'\' is not in a valid format (X9X9X9 or X9X 9X9)');
					oErrMsg.setError(fld)
					return;
				}
			}
			else if (i == 1 || i == 3 || i == 5) {
				if (ch < '0' || ch > '9') {
					// it is not a number
					oErrMsg.addErrorMsg ('The \''+nam+'\' is not in a valid format (X9X9X9 or X9X X9X)');
					oErrMsg.setError(fld)
					return;
				}
			}
		}
	fld.value = postal;
	}
}

//==========================================

function chkRadio(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		var radio_choice = false;
	
		if (fld.length == undefined) {
			if (fld.checked) radio_choice = true;
		}
		else {
			for (var counter=0; counter < fld.length; counter++) {
				if (fld[counter].checked) radio_choice = true;
			}
		}
	
		if (!radio_choice) {
			oErrMsg.addErrorMsg ('The \''+nam+'\' intention has not been selected.');
			oErrMsg.setError(fld);
			return;
		}
	}
}

//==========================================

function returnMatches(parsePattern, searchString) {
	var matchArray=searchString.match(parsePattern);
	if (matchArray==null) return false;
	var newStr = '';
	for (i=0; i<matchArray.length; i++) {
		newStr += matchArray[i];
	}
	return newStr;
}

//==========================================

function chk10DigitPhone(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		var phone = returnMatches(/[0-9]/gi, fld.value);
		if (!phone) {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' must have 10 numeric digits.');
			oErrMsg.setError(fld);
			return;
		}
		fld.value = phone;
		if (phone.length < 10 || phone.length > 10) {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' must have 10 numeric digits.');
			oErrMsg.setError(fld);
			return;
		}
	}
}

//==========================================

function chk10DigitPhoneOptional(fld, nam) {
	if (fld) {	//Check that the field exists on the form first
		if (fld.value == '') return;
		var phone = returnMatches(/[0-9]/gi, fld.value);
		if (!phone) {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' must have 10 numeric digits.');
			oErrMsg.setError(fld);
			return;
		}
		fld.value = phone;
		if (phone.length < 10 || phone.length > 10) {
			oErrMsg.addErrorMsg ('The \'' + nam + '\' must have 10 numeric digits.');
			oErrMsg.setError(fld);
			return;
		}
	}
}

//==========================================

	var ccErrorNo = 0;
	var ccErrors = new Array();

	ccErrors [0] = "Unknown Credit Card Type.";
	ccErrors [1] = "No Credit Card Number was provided.";
	ccErrors [2] = "The Credit Card Number is in an invalid format.";
	ccErrors [3] = "The Credit Card Number is invalid.";
	ccErrors [4] = "The Credit Card Number has an inappropriate number of digits.";
	ccErrors [5] = "The Credit Card has expired.";

function checkCreditCard (cardnumber, cardname, month, year) {

  var cards = new Array();

  cards [0] = {name: "Visa",
               length: "13,16",
               prefixes: "4",
               checkdigit: true};
  cards [1] = {name: "MasterCard",
               length: "16",
               prefixes: "51,52,53,54,55",
               checkdigit: true};
  cards [2] = {name: "Diners Club",
               length: "14,",
               prefixes: "300,301,302,303,304,305,36,38",
               checkdigit: true};
  cards [3] = {name: "CarteBlanche",
               length: "14",
               prefixes: "300,301,302,303,304,305,36,38",
               checkdigit: true};
  cards [4] = {name: "American Express",
               length: "15",
               prefixes: "34,37",
               checkdigit: true};
  cards [5] = {name: "Discover",
               length: "16",
               prefixes: "6011",
               checkdigit: true};
  cards [6] = {name: "JCB",
               length: "15,16",
               prefixes: "3,1800,2131",
               checkdigit: true};
  cards [7] = {name: "Enroute",
               length: "15",
               prefixes: "2014,2149",
               checkdigit: true};

	var cardType = -1;
	for (var i=0; i<cards.length; i++) {
		if (cardname.toLowerCase() == cards[i].name.toLowerCase()) {
			cardType = i;
			break;
		}
	}

	if (cardType == -1) {
		ccErrorNo = 0;
		return false;
	}

	if (cardnumber.length == 0)  {
		ccErrorNo = 1;
		return false;
	}

	// Check that the number is numeric, although we do permit a space to occur
	// every four digits.
	var cardNo = cardnumber
	var cardexp = /^([0-9]{4})\s?([0-9]{4})\s?([0-9]{4})\s?([0-9]{1,4})$/;
	if (!cardexp.exec(cardNo))  {
		ccErrorNo = 2;
		return false;
	}

	// Now remove any spaces from the credit card number
	cardexp.exec(cardNo);
	cardNo = RegExp.$1 + RegExp.$2 + RegExp.$3 + RegExp.$4;

	// Now check the modulus 10 check digit - if required
	if (cards[cardType].checkdigit) {
		var checksum = 0;                                  // running checksum total
		var mychar = "";                                   // next char to process
		var j = 1;                                         // takes value of 1 or 2

		// Process each digit one by one starting at the right
		var calc;
		for (i = cardNo.length - 1; i >= 0; i--) {

			// Extract the next digit and multiply by 1 or 2 on alternative digits.
			calc = Number(cardNo.charAt(i)) * j;

			// If the result is in two digits add 1 to the checksum total
			if (calc > 9) {
				checksum = checksum + 1;
				calc = calc - 10;
			}

			// Add the units element to the checksum total
			checksum = checksum + calc;

			// Switch the value of j
			if (j ==1) {j = 2} else {j = 1};
		}

		// All done - if checksum is divisible by 10, it is a valid modulus 10.
		// If not, report an error.
		if (checksum % 10 != 0)  {
			ccErrorNo = 3;
			return false;
		}
	}

	// The following are the card-specific checks we undertake.
	var LengthValid = false;
	var PrefixValid = false;
	var undefined;

	// We use these for holding the valid lengths and prefixes of a card type
	var prefix = new Array ();
	var lengths = new Array ();

	// Load an array with the valid prefixes for this card
	prefix = cards[cardType].prefixes.split(",");

	// Now see if any of them match what we have in the card number
	for (i=0; i<prefix.length; i++) {
		var exp = new RegExp ("^" + prefix[i]);
		if (exp.test (cardNo)) PrefixValid = true;
	}

	// If it isn't a valid prefix there's no point at looking at the length
	if (!PrefixValid) {
		ccErrorNo = 3;
		return false;
	}

	// See if the length is valid for this card
	lengths = cards[cardType].length.split(",");
	for (j=0; j<lengths.length; j++) {
		if (cardNo.length == lengths[j]) LengthValid = true;
	}

	// See if all is OK by seeing if the length was valid. We only check the
	// length if all else was hunky dory.
	if (!LengthValid) {
		ccErrorNo = 4;
		return false;
	};

	// Now check the expiry date
	if (isNaN(parseInt(year)) || isNaN(parseInt(month))) {
		ccErrorNo = 5;
		return false;
	}

	today = new Date();

	if (year <= today.getFullYear()) {
		if (month < (today.getMonth()+1)) {
			ccErrorNo = 5;
			return false;
		}
	}

	// The credit card is in the required format.
	return true;
}

//---------------------------------------------------------------------------
/*
function chkValidCC(fld, fldType, month, year) {
	if (!checkCreditCard(fld.value, fldType.value, month.value, year.value)) {
		oErrMsg.addErrorMsg (ccErrors[ccErrorNo]);
		oErrMsg.setError(fld);
		return;
	}
}
*/

function chkValidCC(fld, fldType, month, year) {
	if (fld) {	//Check that the field exists on the form first
		if (!checkCreditCard(fld.value, fldType.value, month.value, year.value)) {
			oErrMsg.addErrorMsg (ccErrors[ccErrorNo]);
			oErrMsg.setError(fld);
			return;
		}
		chkEmptyFld (document.frmForm.regCCName, 'Name on Credit Card');
	}
}

//==========================================

function dateUpdate(fld) {
	var overall_id = fld.name.substr(2,fld.name.length-2);
	var year_id = document.getElementById('y_'+overall_id).value;
	var month_id = document.getElementById('m_'+overall_id).value;
	var day_id = document.getElementById('d_'+overall_id).value;
	var bdate = year_id+'/'+month_id+'/'+day_id;
	document.getElementById(overall_id).value = bdate;
}

//==========================================

	function chkOptionQuantity(frm, fldName, nam)
	{
		var fldValue = '';

		if (document[frm][fldName].length==undefined) {
			fldValue = document[frm][fldName].value;
		}
		else {
			if (document[frm][fldName][0].type=='radio') {
				//radio
				for (var i=0; i<document[frm][fldName].length; i++)  {
					if (document[frm][fldName][i].checked) fldValue=document[frm][fldName][i].value;
				}
			}
			else {
				//dropdown
				fldValue = document[frm][fldName].value;
			}
		}

		return getViaAjax('showAjaxErrMsg', frm, fldName, '\''+nam+' - '+fldValue+'\' is no longer available.', 'reg_option_quantity', fldName, fldValue);

	}

//==========================================
