/* JavaScript Document - Form validator - _dev

   --COMMENTS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

	  7Sep09 EL Trap situation where date does not exist on the form, i.e. is undefined at this point.
              This happens when all open and waiting list session dates have
               passed and no placeholder is defined.
	 03Nov08 DY Add bilingual alert message support, language is decided by <INPUT type="hidden" name="lang">
	            lang=0 is Enlgish
							lang=1 is French
	  9Sep08 EL In hasValue, test for a select that has been replaced by a hidden
               and apply the proper test.
	            In hasValue, test for a radio that has been replaced by a hidden
               and apply the proper test.
	            Make otherOrg required if organization is "other".
	  1Sep08 EL New optional field homeaddress.
	  5Jun08 EL Add TEXTAREA to the set of testable object types.
	  4Jun08 EL hasValue alert if the object type is not known.
	 28May08 DY Add email address validation support
	 26May08 EL Support list of fields not to check as second argument to _CF_checkmyform
	             This has the effect of making the field optional.
	            Support both single- and multiple-option radio and checkbox options for
	             RADIO and CHECKBOX in _CF_hasValue
	            Use try/catch to avoid hanging on checking for fields that don't exist.
							 . Applied to 
								 . participated
								 . participation_option
								 . payment_option
							 Copy this technique for new fields that may not exist in later
							  versions of the form.
							 If you want the field to exist with a default or always-the-same,
							  but non-empty, value set it up as a hidden field in the form.

*/

var firstnameAlert = new Array("First Name is required","Votre prénom est requis")
var lastnameAlert = new Array("Last Name is required","Votre nom de famille est requis")
var positionAlert = new Array("Please indicate position, title or role in the organization","Merci d'indiquer votre position à l'école")
var subOrgAlert = new Array("School is required","L'école est requise")
var orgAlert = new Array("Please select Board or 'Other'","Sélectionner Conseil scolaire ou 'Autre', s'il vous plaît")
var otherOrgAlert = new Array("Please enter a Board name","Entrez un nom de conseil")
var homeaddAlert = new Array("Please enter a home mailing address","Entrez l'adresse postale de votre domicile")
var EmailAlert = new Array("E-mail is required","Le courriel est requis")
var EmailErrorAlert = new Array("Invalid Email address, please check your E-mail address again.","Adresse de courriel invalide, Merci de revérifier votre adresse de courriel")
var ophoneAlert=new Array("Office Phone is required","Numéro de téléphone (lieu de travail) est requis")
var hphoneAlert=new Array("Home Phone is required","Numéro de téléphone (domicile) est requis")
var participatedAlert=new Array("please indicate whether you have participated in a web conference before.","Veuillez indiquer si vous avez déjà participé à une webconférence.")
var partOptionAlert=new Array("Please choose your participation option","Choisissez votre option de participation")
var payOptionAlert=new Array("Please choose your payment method","Choisissez votre moyen de paiement")
var dateAlert = new Array("please choose a date","Merci de choisir une date")
var dateUndefinedAlert = new Array("Please select a date. If no dates are listed registration is not possible at this time.","please choose a datef")
var dateIIAlert = new Array("please choose a PART II date","please choose a PART II datef")

function _CF_onError(form_object, input_object, object_value, error_message)
{
	alert(error_message);
				return false;	
}

function _CF_hasValue(obj, obj_type)
{

	if (obj_type == "TEXT" || obj_type == "PASSWORD" || obj_type == "TEXTAREA")
	{
    	if (obj.value.length == 0) 
      		return false;
    	else 
      		return true;
	}
	else if (obj_type == "SELECT")
	{
		// If the select was replaced by a hidden the object will have no length.
		//  Apply test for text instead.
		if ( obj.length == null ) {
    	if (obj.value.length == 0) 
      		return false;
    	else 
      		return true;
		}
		for (i=0; i < obj.length; i++)
		{
			if (obj.options[i].selected)
				return true;
		}
		return false;	
	}
	else if (obj_type == "RADIO" || obj_type == "CHECKBOX")
	{
				// Radio-buttons with a single choice and single checkboxes do not have a length property.
				//  (Replaces the old SINGLE_VALUE_* obj_type values.)
				if ( obj.length == null ) {
					if (obj.checked) {
						return true;
					} else {
						// Allow for a radio replaced by a hidden.
						if (obj.value.length != null && obj.value.length > 0) {
							//alert("Radio to hidden test succeeded."); return false;
							return true;	
						} else {
							return false;	
						}
					}
				} else {
					//alert("CHECKBOX null test failed."); return false;
					for (i=0; i < obj.length; i++)
					{
						if (obj[i].checked)
							return true;
					}
					return false;	
				}

	}
	else
	{
		alert("Object type: " + obj_type + " is not known to the form checker.");
		return true;
	}

// end of _CF_hasValue
}

/*
		Return true if this field is to be checked, i.e. not in the list of those to be skipped.
		Return false if this field is to be ignored, i.e. is in the list of those to be skipped.

		Usage: if ( checkThisField(field) ) ...

		Note that skipThese is a global variable.
*/
function _CF_checkThisField(fld) {

		if ( skipThese.indexOf("|" + fld + "|") == -1 ) {
			return true;
		} else {
			return false;
		}

// end of _CF_checkThisField
}

// Check whether some fields in a form (_CF_this) are valid (usually just not-empty).
// Do not check those in the comma-separated list skipSet (they are not required).
//
// Usage: _CF_checkmyform(this[, 'position, homephone'])
//
function  _CF_checkmyform(_CF_this, skipSet)
    {

    var lang = _CF_this.lang.value;
		
		// Set up the list of fields to not check whether they have been entered.
		//
		// If there was no list of fields to skip.
		if ( skipSet == null ) {
			//dev var skipSet = new String("");
			//dev alert("skipSet >" + skipSet + "<");
			// skipThese must be global. Do not declare it with var.
			skipThese = "";
		} else {
			//dev alert("skipSet >" + skipSet + "<");
			var skipList = new Array;
			skipList = skipSet.split(/\s*,\s*/);
			//dev alert("skipList has " + skipList.length + " elements. >" + skipList[0] + "< >" + skipList[1] + "<");
			// skipThese must be global. Do not declare it with var.
			skipThese = "|" + skipList.join("|") + "|";
		}

		//dev Remove this block from the production version.
		/*
		if ( _CF_checkThisField("future_comm") ) {
			if  (!_CF_hasValue(_CF_this.future_comm, "CHECKBOX_XX" )) 
					{
					// This just waits for exit from an alert and returns 'false'; 'true' isn't possible.
					if  (!_CF_onError(_CF_this, _CF_this.future_comm, _CF_this.future_comm.value, "Please tick 'future comm'"))
							{
							return false; 
							}
			}
		}
		*/

		/*  7Sep09 EL Old version.
		if ( _CF_checkThisField("date") ) {
			if  (_CF_this.date && !_CF_hasValue(_CF_this.date, "RADIO" )) {
				// This just waits for exit from an alert and returns 'false'; 'true' isn't possible.
				if  (!_CF_onError(_CF_this, _CF_this.date, _CF_this.date.value, dateAlert[lang]))
					{
					// _CF_this.date[0].focus();	// Cannot accept focus(?)
					return false; 
				}
			}
		}
		*/

		if ( _CF_checkThisField("date") ) {
			// See if date exists.
			if  (_CF_this.date) {
				if (!_CF_hasValue(_CF_this.date, "RADIO" )) {
					// This just waits for exit from an alert and returns 'false'; 'true' isn't possible.
					if  (!_CF_onError(_CF_this, _CF_this.date, _CF_this.date.value, dateAlert[lang]))
						{
						// _CF_this.date[0].focus();	// Cannot accept focus(?)
						return false; 
					}
				} else {
					// alert("date exists do nothing");
					1;
				}
			} else {
				//alert("date test not possible");
				alert(dateUndefinedAlert[lang]);
				return false;
			}
		}

		/* dev only Why did I comment this out dev-side? */
		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("payment_option") ) {
				if (!_CF_hasValue(_CF_this.payment_option, "TEXT" ))
						{
						if (!_CF_onError(_CF_this, _CF_this.payment_option, _CF_this.payment_option.value, "Please choose your payment method"))
								{
								return false;
						}
				}
			}
		} catch (theException) {
			alert("pay_opt " + theException.message);	// i.e. "obj has no properties" or "is null or is not an object"
			// Don't do anything.
			1;
		}
		/* X */

		if ( _CF_checkThisField("firstname") ) {
			if  (!_CF_hasValue(_CF_this.firstname, "TEXT" )) {
				if  (!_CF_onError(_CF_this, _CF_this.firstname, _CF_this.firstname.value, firstnameAlert[lang]))
					{
					_CF_this.firstname.focus();
					return false; 
				}
			}
		}

		if ( _CF_checkThisField("lastname") ) {
			if  (!_CF_hasValue(_CF_this.lastname, "TEXT" )) {
				if  (!_CF_onError(_CF_this, _CF_this.lastname, _CF_this.lastname.value, lastnameAlert[lang]))
						{
						_CF_this.lastname.focus();
						return false; 
				}
			}
		}

		if ( _CF_checkThisField("position") ) {
			if  (!_CF_hasValue(_CF_this.position, "TEXT" )) 
					{
					if  (!_CF_onError(_CF_this, _CF_this.position, _CF_this.position.value, positionAlert[lang]))
							{
							_CF_this.position.focus();
							return false; 
							}
			}
		}

		if ( _CF_checkThisField("subOrganization") ) {
			if  (!_CF_hasValue(_CF_this.subOrganization, "TEXT" )) {
				if  (!_CF_onError(_CF_this, _CF_this.subOrganization, _CF_this.subOrganization.value, subOrgAlert[lang]))
						{
						_CF_this.subOrganization.focus();
						return false; 
				}
			}
		}

		if ( _CF_checkThisField("organization") ) {
			if  ( !_CF_hasValue(_CF_this.organization, "SELECT" ) || _CF_this.organization.value == "None" ) {
				if  (!_CF_onError(_CF_this, _CF_this.organization, _CF_this.organization.value, orgAlert[lang]))
						{
						_CF_this.organization.focus();
						return false; 
				}
			}
		}

		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("otherOrg") ) {
				if (!_CF_hasValue(_CF_this.otherOrg, "TEXT" ) && _CF_this.organization.value == "other" )
						{
						if (!_CF_onError(_CF_this, _CF_this.otherOrg, _CF_this.otherOrg.value, otherOrgAlert[lang]))
								{
								_CF_this.otherOrg.focus();
								return false;
						}
				}
			}
		} catch (theException) {
			// Don't do anything.
			1;
		}

		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("homeaddress") ) {
				if (!_CF_hasValue(_CF_this.homeaddress, "TEXT" ))
						{
						if (!_CF_onError(_CF_this, _CF_this.homeaddress, _CF_this.homeaddress.value, homeaddAlert[lang]))
								{
								_CF_this.homeaddress.focus();
								return false;
						}
				}
			}
		} catch (theException) {
			// Don't do anything.
			1;
		}

		if ( _CF_checkThisField("email") ) {
			if  (!_CF_hasValue(_CF_this.email, "TEXT" )) {
				if  (!_CF_onError(_CF_this, _CF_this.email, _CF_this.email.value, EmailAlert[lang]))
						{
						_CF_this.email.focus();
						return false; 
				}
			}

			// validate email fields
    	if (!emailValid(_CF_this.email.value)) {
		  	alert(EmailErrorAlert[lang]);
			 	_CF_this.email.focus();
				return false;
			}
		}

		if ( _CF_checkThisField("officephone") ) {
			if (!_CF_hasValue(_CF_this.officephone, "TEXT" )) {
				if (!_CF_onError(_CF_this, _CF_this.officephone, _CF_this.officephone.value, ophoneAlert[lang]))
						{
						_CF_this.officephone.focus();
						return false;
				}
			}
		}

		if ( _CF_checkThisField("homephone") ) {
			if (!_CF_hasValue(_CF_this.homephone, "TEXT" )) {
				if (!_CF_onError(_CF_this, _CF_this.homephone, _CF_this.homephone.value, hphoneAlert[lang]))
						{
						_CF_this.homephone.focus();
						return false;
				}
			}
		}

		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("participated") ) {
				if  (!_CF_hasValue(_CF_this.participated, "RADIO" )) 
					{
					// This just waits for exit from an alert and returns 'false'; 'true' isn't possible.
					if  (!_CF_onError(_CF_this, _CF_this.participated, _CF_this.participated.value,
									participatedAlert[lang]))
							{
							return false; 
					}
				}
			}
		} catch (theException) {
			//dev alert("participated " + theException.message);	// i.e. "obj has no properties"
			// Don't do anything.
			1;
		}

		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("dateII") ) {
				if  (!_CF_hasValue(_CF_this.dateII, "RADIO" )) {
					// This just waits for exit from an alert and returns 'false'; 'true' isn't possible.
					if  (!_CF_onError(_CF_this, _CF_this.dateII, _CF_this.dateII.value, dateIIAlert[lang]))
						{
						// _CF_this.dateII[0].focus();	// Cannot accept focus(?)
						return false; 
					}
				}
			}
		} catch (theException) {
			//dev alert("participated " + theException.message);	// i.e. "obj has no properties"
			// Don't do anything.
			1;
		}

		/* dev only Why did I comment this out dev-side? */
		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("participation_option") ) {
				if (!_CF_hasValue(_CF_this.participation_option, "RADIO" ))
						{
						if (!_CF_onError(_CF_this, _CF_this.participation_option, _CF_this.participation_option.value, partOptionAlert[lang]))
								{
								return false;
						}
				}
			}
		} catch (theException) {
			// Don't do anything.
			1;
		}

		// try/catch handles the situation where the field does not exist.
		// If the field exists but is empty the user will still be asked to fill it in.
		try {
			if ( _CF_checkThisField("payment_option") ) {
				if (!_CF_hasValue(_CF_this.payment_option, "TEXT" ))
						{
						if (!_CF_onError(_CF_this, _CF_this.payment_option, _CF_this.payment_option.value, payOptionAlert[lang]))
								{
								return false;
						}
				}
			}
		} catch (theException) {
			// Don't do anything.
			1;
		}

// alert("Got to the end of dev checks");
// return false

		// Nothing failed so there must be overall success.
    return true;

// end of _CF_checkmyform
}

//Email address validation fuction
function emailValid (email)
{

	email = trim(email);

	/* Only one @ in email address */
	if (email.indexOf("@") != email.lastIndexOf("@")) {
		return false;
	}

	/* special characters' position checking */
	// Have @ and not be the first
	if (email.indexOf("@") < 1) {
		return false;
	// Last . must be after @ and between . and @ at least one character
	} else if (email.lastIndexOf(".") <= (email.indexOf("@")+1)) {  
		return false;
	// No two .
	} else if (email.indexOf("..") >=0) {
		return false;
	// . must not be the last character
	} else if (email.lastIndexOf(".") == (email.length - 1)) {  // . must not be the last character
		return false;
	}

	/* characters' validation checking */
	// allow ONLY valid characters for email Field
	var validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@.-_";
	var i = 0
	for (i = 0;  i < email.length;  i++)
	{
		ch = email.charAt(i);

		if (validChars.indexOf(ch) != -1)
			continue;

		return false;
	}

	return true;

// emailValid
}

// Return a string with leading and trailing whitespace removed.
function trim(str)
{
	s = str.replace(/^(\s)*/, '');
	s = s.replace(/(\s)*$/, '');
	return s;
}

