//keep initial values as 0, this case if no form exist, JS will not try to display it:
var iFormPages=0, iCurrPage=0, aFormInputs = new Array(), aFormSections = new Array(), bUpdate=false, sRSVP=null, isSF=false;
var oMeta=null, oMetaSF=null, oMetaEmailDest=null, oMetaEmailConf=null;
(window.attachEvent)?window.attachEvent('onload',setFocus):window.addEventListener('load',setFocus,false);
//(window.attachEvent)?window.attachEvent('onload',chkOffshore):window.addEventListener('load',chkOffshore,false);
//debug for Anil:
var okToSubmit=false;

//for FF fix LS footer placement bug:
//window.addEventListener('load', fixFFFooter, false);

//cancel updates on current page, and goto verify page
function cancelToVerify() {
  //since we are in update mode, values are already stored in verify page
  //copy them over to current page, and switch back to verify page:
  for (var i=0; i < aFormInputs[iCurrPage].length; i++) {
	if(typeof aFormInputs[iCurrPage][i]=='object') { //object can be array: radio, checkbox, multi-select.
	  var sSelects=$(aFormInputs[iCurrPage][i]+'Verify').innerHTML; //get object's selected values:
	  var aSelects=sSelects.split(', ');
	  var iNum=1, oArr=$(aFormInputs[iCurrPage][i]+iNum);
	  if(oArr) { //radio, or checkbox
	  do { //loop through all object's elements, unselect all, then re-set selected ones:
	    oArr.checked=false; //unselect all
		for(var j=0;j<aSelects.length;j++)if(oArr.getAttribute('label')==aSelects[j])oArr.checked=true;
		oArr=$(aFormInputs[iCurrPage][i]+(++iNum)); //get next element
	  } while(oArr);
	  } else { //multi-select
	    var oInput=$(aFormInputs[iCurrPage][i]), iLen=oInput.options.length;
		for(var k=0;k<iLen;k++){ //loop through all object's elements, unselect all, then re-set selected ones:
		  oInput.options[k].selected=false; //unselect all
		  for(var j=0;j<aSelects.length;j++)if(oInput.options[k].value==aSelects[j])oInput.options[k].selected=true;
		} //for
	  } //if oArr
	} else $(aFormInputs[iCurrPage][i]).value=$(aFormInputs[iCurrPage][i]+'Verify').innerHTML;
  } //for
  hidePageErrs(iCurrPage); //hide errors in case user generated them through "Update", then decided to "Cancel"
  hideFormPage(iCurrPage);displayFormPage('Verify');
} //cancelToVerify()

//check whether to display or hide section headers on verify page
//if all input elements for given section are blank, hide section header:
function checkVerifySections() {
  for (var i=1;i<aFormInputs.length;i++)
    for(var j=0;j<aFormSections[i].length;j++){ //sections loop
	  var bSection=false, sValue='';
	  var nPipePos=aFormSections[i][j].indexOf('|');
	  var nStart=parseInt(aFormSections[i][j].substring(0,nPipePos));
	  var nEnd=parseInt(aFormSections[i][j].substr(nPipePos+1));
		//check if value exists, obtain object's value from verify page: 
		for(var k=nStart;k<=nEnd;k++)
	    if(typeof aFormInputs[i][k]=='object'){if(trimSpace($(aFormInputs[i][k]+'Verify').innerHTML)){bSection=true;break;}
      } else {if($(aFormInputs[i][k]).value){bSection=true;break;}}
	  var nSection=j+1, oSection=$('p'+i+'_s'+nSection); //try to obtain object, might not exist
		//hide/show section, they are in "p9_s9" (page number and section number) format:
	  if(oSection){
		  if(!bSection)oSection.style.display='none';
		  else oSection.style.display='';
		} //if oSection
  } //for aFormSections
} //checkVerifySections()

//display form page with spacified page index:
function displayFormPage(iPageIndex) {
  $("formPage"+iPageIndex).style.display="block";iCurrPage=iPageIndex;
} //displayFormPage()

//edit specific page (from verify page):
function editPage(iPage) {
  hideFormPage('Verify');
  if(!bUpdate) {
	//switch to update mode:
	switchToUpdateMode(); bUpdate=true;
  } //if !bUpdate
  displayFormPage(iPage);
} //editPage()

//fix LiveSite bug for footer placement in FireFox:
function fixFFFooter(sFormName) {
  if (navigator.userAgent.indexOf('MSIE ')==-1 || navigator.userAgent.indexOf('MSIE 7.')!=-1) {$(sFormName).parentNode.style.height="auto";}
} //fixFFFooter()

//fix LiveSite bug for footer placement:
function fixFooter(sFormName){$(sFormName).parentNode.style.height="auto";}

//form constructor for meta data:
function formConstr(_formId, _formName, _formType, _formAction, _formSuccess, _formSuccess2, _formError, _formExpDate) {
  this.formId=_formId; this.formName=_formName; this.formType=_formType; this.formAction=_formAction;
  this.formSuccess=_formSuccess; this.formSuccess2=_formSuccess2; this.formError=_formError; this.formExpDate=_formExpDate;
} //formConstr()

//form constructor for Email confirmation data:
function formConstrEmailConf(_send, _from, _fromField, _to, _toField, _subject, _body, _inclFields, _attachment, _template) {
  this.send=_send; this.from=_from; this.fromField=_fromField; this.to=_to; this.toField=_toField; this.subject=_subject;
  this.inclFields=_inclFields; this.body=_body; this.attachment=_attachment; this.template=_template;
} //formConstrEmailConf()

//form constructor for Email destination data:
function formConstrEmailDest(_from, _fromField, _to, _cc, _bcc, _subject, _subjectField) {
  this.from=_from; this.fromField=_fromField; this.to=_to; this.cc=_cc; this.bcc=_bcc; this.subject=_subject; this.subjectField=_subjectField;
} //formConstrEmail()

//form constructor for SalesForce data:
function formConstrSF(_url, _oid, _leadSource, _webToLead, _campaignId, _recordType, _nzmd, _rsvp) {
  this.url=_url; this.oid=_oid; this.leadSource=_leadSource; this.webToLead=_webToLead;
  this.campaignId=_campaignId; this.recordType=_recordType; this.nzmd=_nzmd; this.rsvp=_rsvp;
} //formConstrSF()

//return form page index value offset from current:
function getFormPageIndex(iOffset) {
  var iTempIndex=Number(iCurrPage)+Number(iOffset);
  while(iTempIndex<1 || iTempIndex>iFormPages) {
	if(iTempIndex>iFormPages)iTempIndex-=iFormPages;
	else if(iTempIndex<1)iTempIndex+=iFormPages;
  } //while
  return iTempIndex;
} //getArrIndex()

//generate XML of passed form name
function generateXML(sForm) {
  var sSuccess=sRSVP=='Declined'?oMeta.formSuccess2:oMeta.formSuccess;
  var sXML='<Form name="'+oMeta.formName+'" type="'+oMeta.formType+'" action="'+oMeta.formAction+'" expDate="'+oMeta.formExpDate+
  '" successpage="'+sSuccess+'" errorpage="'+oMeta.formError+'">\n';
  sXML+=generateXMLFields();
  sXML+=generateXMLSF(); //SalesForce
  sXML+=generateXMLEmailDest(); //Email destination
  sXML+=generateXMLEmailConf();  //Email Confirmation
  sXML+='</Form>';
//populateDiv(sXML);
/*
if( navigator.userAgent.indexOf( 'MSIE' ) == -1 )populateDiv(sXML);
else okToSubmit=true;
*/
//alert(sXML);
  return sXML;
} //generateXML()

//generate form email confirmation meta data in XML format
function generateXMLEmailConf() {
  var sXML='<EmailConfirmation send="'+oMetaEmailConf.send+'" template="'+oMetaEmailConf.template+'">\n';
  var sEmailFrom=getEmailConfFrom();
  //cc and bcc always blank, used only for parsing purposes:
  sXML+='<from><![CDATA['+sEmailFrom+']]></from><to><![CDATA['+getEmailConfTo()+']]></to><cc></cc><bcc></bcc><subject>'+oMetaEmailConf.subject+'</subject>\n';
  sXML+='<body><![CDATA['+oMetaEmailConf.body+']]></body><includeFields>'+oMetaEmailConf.inclFields+'</includeFields><attachment>'+oMetaEmailConf.attachment+'</attachment>\n';
  return sXML+'</EmailConfirmation>\n';
} //generateXMLEmailConf()

//generate form email destination meta data in XML format
function generateXMLEmailDest() {
  var sXML='<EmailDestination>\n';
  var sEmailDest=getEmailDestFrom();
  var sEmailDestSubject=getEmailDestSubject();
  //body and attachment always blank, used only for parsing pursposes:
  sXML+='<from><![CDATA['+sEmailDest+']]></from><to><![CDATA['+oMetaEmailDest.to+']]></to><cc><![CDATA['+oMetaEmailDest.cc+']]></cc><bcc><![CDATA['+oMetaEmailDest.bcc+']]></bcc>\n';
  sXML+='<subject>'+sEmailDestSubject+'</subject><body></body><attachment></attachment>\n';
  return sXML+'</EmailDestination>\n';
} //generateXMLEmailDest()

//generate form fields data in XML format
function generateXMLFields() {
  var sXML='<Fields>\n', sField;
  //aFormInputs[0] has form metadata
/*  
  for(var i=0;i<aFormInputs[0].length;i++) {
//TODO: get meta fields here (possibly)
  } //for metadata
*/
  if(oMeta.formId)
	sXML+='<Field name="formId" salesforceid="" validation="" email="yes"><value>'+oMeta.formId+'</value></Field>\n';
  for(var j=1;j<aFormInputs.length;j++)
    for(var k=0;k<aFormInputs[j].length;k++) {
	  sField=aFormInputs[j][k];
	  //for string types get value from verify page, for objects loop through actual form objects to get value:
	  if(typeof sField=='object') {
		var m=1, oArr=$(sField+m);
		if(oArr) { //radio, or checkbox:
		do {
		  if(oArr.checked)sXML+='<Field name="'+sField+'" salesforceid="'+oArr.getAttribute('sf')+'" validation="" email="'+oArr.getAttribute('email')+'" secure="'+oArr.getAttribute('secure')+'" label="'+getXMLValueAttribute(oArr.getAttribute('label'))+'"><value>'+getXMLValue(oArr.value)+'</value></Field>\n';
		  oArr=$(sField+(++m));
		} while(oArr);
		} else { //multi-select:
		  var oInput=$(sField), iLen=oInput.options.length;
		  for(var m=0;m<iLen;m++)if(oInput.options[m].selected)sXML+='<Field name="'+sField+'" salesforceid="'+oInput.getAttribute('sf')+'" validation="" email="'+oInput.getAttribute('email')+'" secure="'+oInput.getAttribute('secure')+'" label="'+getXMLValueAttribute(oInput.getAttribute('label'))+'"><value>'+getXMLValue(oInput.options[m].value)+'</value></Field>\n';
		} //if oArr
	  } else {
		  if($(sField+'Verify'))
			sXML+='<Field name="'+sField+'" salesforceid="'+$(sField).getAttribute('sf')+'" validation="" email="'+$(sField).getAttribute('email')+'" secure="'+$(sField).getAttribute('secure')+'" label="'+getXMLValueAttribute($(sField).getAttribute('label'))+'"><value>'+$(sField+'Verify').innerHTML+'</value></Field>\n';
		  else sXML+='<Field name="'+sField+'" salesforceid="'+$(sField).getAttribute('sf')+'" validation="" email="'+$(sField).getAttribute('email')+'" secure="'+$(sField).getAttribute('secure')+'" label="'+getXMLValueAttribute($(sField).getAttribute('label'))+'"></Field>\n';
		  }
	} //for (inner)
	if(sRSVP!='false')sXML+='<Field name="acceptDecline" salesforceid="'+oMetaSF.rsvp+'" validation="" email="no"><value>'+sRSVP+'</value></Field>\n';
	//else sXML+='<Field name="acceptDecline" salesforceid="" validation="" email="yes"><value></value></Field>\n';
  return sXML+'</Fields>\n';
} //generateXMLFields()

//generate form SalesForce meta data in XML format
function generateXMLSF() {
  var sXML='<SalesForce>\n';
  sXML+='<url>'+oMetaSF.url+'</url>\n';
  sXML+='<oid>'+oMetaSF.oid+'</oid>\n';
  //sXML+='<lead_source>'+oMetaSF.leadSource+'</lead_source>\n';
  sXML+='<leadSource>'+oMetaSF.leadSource+'</leadSource>\n';
  sXML+='<webToLead>'+oMetaSF.webToLead+'</webToLead>\n';
  //sXML+='<Campaign_ID>'+oMetaSF.campaignId+'</Campaign_ID>\n';
  sXML+='<campaignId>'+oMetaSF.campaignId+'</campaignId>\n';
  sXML+='<recordType>'+oMetaSF.recordType+'</recordType>\n';
  sXML+='<NZMD>'+oMetaSF.nzmd+'</NZMD>\n';
  return sXML+'</SalesForce>\n';
} //generateXMLSF()

//get email "from" confirmation value both from "from" and email from field:
function getEmailConfFrom() {
  var emailConf=oMetaEmailConf.from;
  if(oMetaEmailConf.fromField!='')emailConf+=getFieldValue(oMetaEmailConf.fromField);
  return emailConf;
} //getEmailConfFrom()

//get email "to" confirmation value both from "to" and email to field:
function getEmailConfTo() {
  var emailConf=oMetaEmailConf.to;
  if(oMetaEmailConf.toField!='')emailConf+=getFieldValue(oMetaEmailConf.toField);
  return emailConf;
} //getEmailConfTo()

//get email destination "from" value, get it from "from" as well as from "fromField":
function getEmailDestFrom() {
  var emailDest=oMetaEmailDest.from;
  if(oMetaEmailDest.fromField!='')emailDest+=getFieldValue(oMetaEmailDest.fromField);
  return emailDest;
} //getEmailDestTo()

//get email destination "subject" value, get it from "subject" as well as from "subjectField":
function getEmailDestSubject(){
  var emailSub=oMetaEmailDest.subject;
  if(oMetaEmailDest.subjectField!='')emailSub+=getFieldValue(oMetaEmailDest.subjectField);
  return emailSub;
} //getEmailDestSubject()

//get "field" value for specified field
function getFieldValue(sFieldValue) {
  for(var i=1;i<=iFormPages;i++)
    for (var j=0;j<aFormInputs[i].length;j++)
      if(aFormInputs[i][j]==sFieldValue){
		if($(aFormInputs[i][j]+'Verify'))return $(aFormInputs[i][j]+'Verify').innerHTML;
		else return $(aFormInputs[i][j]).value;
  }
  return '';
} //getFieldValue()

//get user selected value(s) from array element such as radio, checkbox, or multi-select:
function getSelected(sInputElement) {
  var i=1, oArr=$(sInputElement+i), sReturn="";
  if(oArr) { //radio, or checkbox
  do {
	if(oArr.checked){
		if(oArr.getAttribute('verifyLabel')!=null)sReturn+=oArr.getAttribute('verifyLabel')+', ';
		else sReturn+=oArr.getAttribute('label')+', ';
	}//Saurabh 16/06/09- Modified the parameter within the getAttribute() from label to verifyLabel to display 'Yes' or 'No' on verify page
	//Saurabh 03/08/09- added an if/else in case the verifyLabel attribute is not there (did in CTS Portal) 
	oArr=$(sInputElement+(++i));
  } while(oArr);
  } else { //multi-select
    var oInput=$(sInputElement), iLen=oInput.options.length; 
	for(var j=0;j<iLen;j++)if(oInput.options[j].selected)sReturn+=oInput.options[j].text+', ';
  } //if oArr
  return sReturn.substr(0,sReturn.lastIndexOf(', '));
} //getSelected();

//return valid XML value
//if sValue is null, return nothing, otherwise check for XML not allowed chars, and surround with CDATA
function getXMLValue(sValue){
  if(!trimSpace(sValue))return '';
  if(sValue.match('&')!=-1)return '<![CDATA['+sValue+']]>';
  else return sValue;
} //getXMLValue()

//return valid XML value which can be used as attribute value
//remove ampersands and replace double quotes with two single quotes
function getXMLValueAttribute(sValue){
  if(!trimSpace(sValue))return '';
  sValue=sValue.replace(/&/g,"");
  sValue=sValue.replace(/"/g,"''");
  return sValue;
} //getXMLValueAttribute()

//hide form page with spacified page index:
function hideFormPage(iPageIndex) {
  $("formPage"+iPageIndex).style.display="none";
  iCurrPage=0;
} //hideFormPage()

//hide all page error messages:
function hidePageErrs(iPageIndex) {
  $("formPage"+iPageIndex+"Err").style.display="none";
  var oDivs=$("formPage"+iPageIndex).getElementsByTagName("div");
  for(var i=0; i < oDivs.length; i++)if(oDivs[i].className=="formErrorFieldCMS")oDivs[i].style.display="none";
} //hidePageErrs()

//temporary function to populate div so Anil can see generated XML in text format:
function populateDiv(sXML) {
  $('hiddenXML').innerHTML=sXML;
  $('debugId').style.display='block';
  okToSubmit=true;
} //populateDiv()

//populate verify page with user entered/selected values.
//for blank values suppress display of that value
//if all section values blank, suppress section header display:
function populateVerifyPage() {
  for (var i=1; i < aFormInputs.length; i++)
    for (var j=0; j < aFormInputs[i].length; j++){
      var oValueWrap=$(aFormInputs[i][j]+'VerifyWrap'), sValue=null;
      if(typeof aFormInputs[i][j]=='object'){
        sValue=getSelected(aFormInputs[i][j]);
        $(aFormInputs[i][j]+'Verify').innerHTML=sValue;
      } else {
        sValue=$(aFormInputs[i][j]).value;
        $(aFormInputs[i][j]+'Verify').innerHTML=sValue;
      } //if object
      if(!sValue)oValueWrap.style.display="none";
      else oValueWrap.style.display="";
    } //for inner
    checkVerifySections();
} //populateVerifyPage()

//rotate to form page offset from current:
function rotate(iOffset) {
  var iNextIndex=getFormPageIndex(iOffset);
  if(iNextIndex!=iCurrPage){hideFormPage(iCurrPage);displayFormPage(iNextIndex);setFocus()}
} //rotate()

//rotate to verify page:
function rotateToVerify() {
  populateVerifyPage();hideFormPage(iCurrPage);displayFormPage('Verify');
} //rotateVerify()

//attempt to set focus on 1st element on current page:
function setFocus() {
  var sFocus=aFormInputs[iCurrPage][0],oFocus=$(sFocus);
  if(oFocus)oFocus.focus();
} //setFocus()

//show page error
function showErrPage(iPageIndex) {
  $("formPage"+iPageIndex+"Err").style.display="block";
} //showErrPage()

//show required field errors for passed input element:
function showErrReq(sInputElement) {
  var oErr=$(sInputElement+"ErrReq");
  if(oErr)oErr.style.display="block";
} //showErrReq()

//show validation field errors for passed input element:
function showErrVal(oInputElement,iNum) {
  var oErr=$(oInputElement.name+"ErrVal"+iNum);
  if(oErr)oErr.style.display="block";
} //showErrVal()

function submitForm(sForm) {
/*
if(!okToSubmit) {
  $('xmlform').value=generateXML(sForm);
  //return false;
} else {
*/
  $('xmlform').value=generateXML(sForm);
//okToSubmit=false;
  oForm=$(oMeta.formName);
  if(oMeta.formName!="manageprofile")
	oForm.action='/tucms/requestController.do';
  oForm.method='POST';
  //DIRECTLY CALL FIRECLICK'S ONSUBMIT HANDLER: (unless it's offshore, then skip):
  if(oMeta.formName!="manageprofile"){
	if(document.URL.indexOf("isOffshore=y")==-1 && navigator.userAgent.indexOf('Safari')==-1){oForm.onsubmit();}}
//alert('will now submit\noForm = '+oForm+'\noForm.name = '+oForm.name+'\noForm.method='+oForm.method+'\nsubmitting to: '+oForm.action);
  oForm.submit();

//} //if okToSubmit

} //submitForm()

function submitFormAccept(sForm) {
  sRSVP='Accepted';submitForm(sForm);
} //submitFormAccept()

function submitFormDecline(sForm) {
  sRSVP='Declined';submitForm(sForm);
} //submitFormDecline()

function submitFormWrap(sForm) {
  sRSVP='false';submitForm(sForm);
} //submitFormWrap()

//switch passed input element to edit mode (from error mode):
function switchToEditMode(oInputElement) {
  switch(oInputElement.type){
  	case "text":
  	case "select-one":
  	  if(oInputElement.className.match('Error'))oInputElement.className=oInputElement.className.substring(0,oInputElement.className.lastIndexOf('Error'));
  	  break;
  	default:
  	  if(oInputElement.className.match('Error'))oInputElement.className=oInputElement.className.substring(0,oInputElement.className.lastIndexOf('Error'));
  } //switch
} //switchToErrMode()

//wrapper used by radio and checkbox inputs, loops through all input element
//and call switchToEditMode()
function switchToEditModes(sInputElement){
	var i=1, oArr=$(sInputElement+'S'+i);
	while(oArr){
		switchToEditMode(oArr);
	  oArr=$(sInputElement+'S'+(++i));
  } //while
} //switchToEditModes()

//switch passed input element to error mode (if not already in that mode):
function switchToErrMode(oInputElement){
  switch(oInputElement.type){
  	case "text":
  	case "select-one":
  	  if(!oInputElement.className.match('Error'))oInputElement.className+='Error';
  	  break;
  	default:
  	  if(!oInputElement.className.match('Error'))oInputElement.className+='Error';
  	  //alert(oInputElement.name+' is of type: '+oInputElement.type+'\nit\'s class is: '+oInputElement.className);
  }//switch
}//switchToErrMode()

//wrapper used by radio and checkbox inputs, loops through all input element
//and call switchToErrMode()
function switchToErrModes(sInputElement){
	var i=1, oArr=$(sInputElement+'S'+i);
	while(oArr){
		switchToErrMode(oArr);
	  oArr=$(sInputElement+'S'+(++i));
  }//while
}//switchToErrModes()

//switch to update mode (buttons and certain text):
function switchToUpdateMode(){
  for(var i=1;i<=iFormPages;i++) {
	$('formTextUpdate'+i).style.display="inline";
	$('formIntroSection'+i).style.display="none";
	$('formUpdateSection'+i).style.display="block";
	$('formButtonSection'+i).style.display="none";
	$('formButtonSectionUpdate'+i).style.display="block";
  } //for
} //switchToUpdateMode()

//FireClick's step sequencer, invoked on form buttons clicks
//sFormName ==> current form name, sCurrPage ==> current page (on which button was clicked),
//sAction ==> can be: 'Next', 'Prev', 'Update', 'Cancel', 'Edit'
function track_step(sFormName, sCurrPage, sAction){
	var sName=sFormName+'_'+sCurrPage+'_'+sAction;
	var subCat=sAction+'_'+sCurrPage;
  pageTracker._trackEvent('Form Buttons',subCat,sFormName);
  fc_rpt(null,{fc_track: sName});
} //track_step()

//trim whitespace from sValue:
function trimSpace(sValue) {
  var regExTrim=/^\s*(.*?)\s*$/;return sValue.replace(regExTrim, "$1");
} //trimSpace()

//validate passed input element (not array, arrays validated through validateArr() function)
//1st find out if this is a required field, and if yes check if value is entered/selected
//2nd find out if RegEx(s) exist for this field, if yes evaluate entered value against it
function validate(oInputElement) {
	switchToEditMode(oInputElement); //in case input element is in error mode
  var sInputRegEx=oInputElement.name+"RegExp";
  var oReq=$(oInputElement.name+"Req"), i=1, oRegExp=$(sInputRegEx+i), sValue=trimSpace(oInputElement.value);
  if(oReq && oReq.value=="true" && !sValue){switchToErrMode(oInputElement);showErrReq(oInputElement.name);return false;}
  while(oRegExp && sValue) {
	tempRegExp=new RegExp(oRegExp.value, "m");
	if(tempRegExp.source=='email'){
	  if(!validateEmail(sValue)){switchToErrMode(oInputElement);showErrVal(oInputElement,i);return false;}
	} else {
	  if(!tempRegExp.test(sValue)){switchToErrMode(oInputElement);showErrVal(oInputElement,i);return false;}
	} //if tempRegExp
	oRegExp=$(sInputRegEx+(++i));
  } //while oRegExp
  return true;
} //validate()

//validate array (radios, checkboxes, etc.) by looping through array elements:
//RegEx should not exist for objects, so only validate if required
function validateArr(sInputElement) {
  var oReq=$(sInputElement+"Req");
  if(oReq && oReq.value=="true") {
	var i=1, oArr=$(sInputElement+i);
	if(oArr){ //radio, or checkbox:
	  while(oArr){
	    if(oArr.checked){switchToEditModes(sInputElement);return true;}
	    oArr=$(sInputElement+(++i));
    } //while
    switchToErrModes(sInputElement);
	} else { //must be multi-select:
	  var oInput=$(sInputElement), iLen=oInput.options.length;
	  for(var j=0;j<iLen;j++)if(oInput.options[j].selected && oInput.options[j].value!=''){switchToEditMode(oInput);return true;}
	  switchToErrMode(oInput);
	} //if oArr
	showErrReq(sInputElement);return false;
  } //if oReq
  return true;
} //validateArr()

//validate sValue to email format
//TODO: fix this, should use regEx instead as other input elements
function validateEmail(sValue) {
  var iAtPos=sValue.indexOf('@'), iLen=sValue.length, iDotPos=sValue.lastIndexOf('.');
  var iDotRange=iLen-iDotPos;
  if(sValue.match(' '))return false; //embedded spaces
  if(iAtPos==-1)return false; //no @
  if(iAtPos!=sValue.lastIndexOf('@'))return false; //more than 1 @
  if(iAtPos<1 || iLen-iAtPos<4)return false; //not enough before or after @
  if(iDotPos==-1)return false; //no dot
  if(iDotRange<3 || iDotRange>4)return false; //must be 2 or 3 chars after dot
  if(iDotPos-iAtPos<2)return false; //not enough chars between @ and dot
  return true;
} //validateEmail()

//validate whole form (all pages):
function validateForm() {
  for (var i=1; i<=iFormPages; i++)
    if(!validatePage(i)){editPage(i);return false;}
  return true;
} //validateForm()

//validate page with passed index:
function validatePage(iPageIndex) {
  var bValidated=true;
  hidePageErrs(iPageIndex); //hide any existing error messages first
  customSetRequired(iPageIndex);
  for (var i=0;i<aFormInputs[iPageIndex].length;i++)
	if(typeof aFormInputs[iPageIndex][i]=='object') { //object can be array: radio, checkbox, etc.
	  if(!validateArr(aFormInputs[iPageIndex][i]))bValidated=false;
	} else if(!validate($(aFormInputs[iPageIndex][i])))bValidated=false;
  if(!bValidated)showErrPage(iPageIndex);  //display page error message
  return bValidated;
} //validatePage()

//shortcut to get object:
function $(element) {return document.getElementById(element);}

//================= TEXTAREA HELPER FUNCIONTS START ========================
//limit textarea length to maxLimit and consecutive chars length to noSpaceLimit
function checkText(elem, maxLimit, noSpaceLimit) {
  if(elem.value.length>maxLimit)elem.value=elem.value.substring(0,maxLimit);
  if(elem.value.length>noSpaceLimit){
    var strArray=elem.value.split(" "), changed=false;
    for(var i=0;i<strArray.length;i++)
      if(strArray[i].length>noSpaceLimit){
        changed=true;
	strArray[i]=insertSpaces(strArray[i],noSpaceLimit);
      } //if length
    if(changed){
      var combinedWord="";
      for(var i=0;i<strArray.length;i++)combinedWord+=strArray[i]+" ";
      elem.value=combinedWord.substring(0,combinedWord.length-1);
    } //if changed
  } //if noSpaceLimit
} //checkText()

//insert spaces into longWord every noSpaceLimit chars
function insertSpaces(longWord, noSpaceLimit) {
  var v_pointer=0, v_return="";
  while( v_pointer < longWord.length ) {
    v_return+=longWord.slice(v_pointer, v_pointer+noSpaceLimit)+" ";
    v_pointer+=noSpaceLimit;
  } //while
  return v_return.substring( 0, v_return.length-1 );
} //insertSpaces()
//================= TEXTAREA HELPER FUNCIONTS END ========================