/* -------------------------------------------------------------------------- */
/* [FormValidation.js]: Generic client-side form validator                    */
/*                                                                            */
/* Version 1.1                                                                */
/*   - 2 February 2000 (Bryan Krofchok)                                       */
/*                                                                            */
/* Version 1.2                                                                */
/*   - 1 May 2000 (Bryan Krofchok)                                            */
/*                                                                            */
/* Version 1.3                                                                */
/*   - 23 October 2000 (Natalia Collins)                                      */
/*       * Documentation updated                                              */
/*                                                                            */
/* Version 1.4                                                                */
/*   - 8 February 2001 (Steve Mathias, Bryan Krofchok, Natalia Collins)       */
/*       * Various miscellaneous enhancements                                 */
/*                                                                            */
/* Version Civica                                                             */
/*   - 1 April 2005 (Stuart Gregg)																			      */
/*       * Modified to work with civica form format                           */
/*                                                                            */
/* Copyright (c) 2000-2001 EurekaDIGITAL                                      */
/*                                                                            */
/* Usage: See the comment block for the main validate() function.             */
/* -------------------------------------------------------------------------- */


/* --------------------------- Global "Constants" --------------------------- */

var validatedElementPrefix = '[0-9]{3}~';

var minPasswordLength = 6;


/* ---------------------------- Global Variables ---------------------------- */

var scrollPage = false; 
                           
/* ------------------------ Main Validation Function ------------------------ */

function validate(form) {
  return validate(form, null);
}

function validate(form, specializedValidationFunction)
{
  var identifierPattern = new RegExp(validatedElementPrefix + '.*');


  // Loop through each form element, applying validation tests as appropriate
  for (var i = 0; i < form.elements.length; i++) {
    var inputElement = form.elements[i];


    // Validated elements must have the proper variable name prefix
		fieldIdentifier = inputElement.name.match(identifierPattern);
		
		if( fieldIdentifier == null ) continue;
		
    // Trim any extraneous whitespace from the input element's value
    trimField(inputElement);
        
    // Validate the field based on its type
    var fieldType = getFieldType(inputElement);
    if (fieldType != null)
      for (var validatedType in validators)
        if (fieldType.indexOf(validatedType) >= 0 && !validators[validatedType](inputElement)) return false;
  }

  // If present, run the specialized validation function
  if (specializedValidationFunction != null)
    return eval(specializedValidationFunction);

  // The form data has passed all validation tests...
  return true;
}


/* ---------------------------- Variable Parsers ---------------------------- */

function getFieldIdentifier(inputElement)
{
  var identifierPattern = new RegExp('^' + validatedElementPrefix + '([^~]+)');
  var fieldIdentifier = inputElement.name.match(identifierPattern);
  return (fieldIdentifier != null ? fieldIdentifier[1] : null);
}

function getFieldLabel(inputElement)
{
  // Start with the element's field identifier
  var fieldLabel = getFieldIdentifier(inputElement);
  if (fieldLabel == null) return null;

  // Unescape special characters
  fieldLabel = fieldLabel.replace(/XAX/g, "'");
  fieldLabel = fieldLabel.replace(/XHX/g, "-");
  fieldLabel = fieldLabel.replace(/XSX/g, "/");
  
  // Insert spaces before capitalized letters preceeded by a lower-case letters
  fieldLabel = fieldLabel.replace(/([a-z])([A-Z])/g, '$1 $2');

  // Replace _ with space
  fieldLabel = fieldLabel.replace(/_/, ' ');

  // Insert spaces after capitalized acronyms
  fieldLabel = fieldLabel.replace(/([A-Z][A-Z]+)([A-Z][a-z])/g, '$1 $2');

  // Replace "known" identifiers
  fieldLabel = fieldLabel.replace(/Email/, 'E-mail');
  fieldLabel = fieldLabel.replace(/State Province/, 'State/Province');
  fieldLabel = fieldLabel.replace(/Zip Postal Code/, 'Zip/Postal Code');

  return fieldLabel;
}

function getFieldType(inputElement)
{
  var fieldType = inputElement.name.match(/~~([^~~]+)$/);
  return (fieldType != null ? fieldType[1] : null);
}


/* ------------------ Form Input Element Utility Functions ------------------ */

function trimField(inputElement)
{
  var elementType = inputElement.type;
  if ((elementType == 'text' || elementType == 'textarea')
      && inputElement.value != null)
    inputElement.value = trim(inputElement.value);
}

function isBlank(inputElement)
{
  var elementType = inputElement.type;
  if (elementType == 'text' || elementType == 'textarea' || elementType == 'password' || elementType == 'file')
    return (inputElement.value == null || inputElement.value == '');
  else if (elementType == 'select-one') {
    if (inputElement.selectedIndex < 0) return true;
    optionText = inputElement.options[inputElement.selectedIndex].text;
    optionValue = inputElement.options[inputElement.selectedIndex].value;
    return (optionText == null
            || optionText == ''
            || optionText.indexOf('---') >= 0
            || optionValue == null
            || optionValue == ''
            || optionValue.indexOf('---') >= 0);
  }
  return false;
}

function selectElementAvoidSeparator(selectElement)
{
  if (selectElement.options[selectElement.selectedIndex].text.indexOf('---') >= 0) {
    for (var i = 0; i < selectElement.options.length; i++) {
      if (selectElement.options[i].defaultSelected) {
        selectElement.selectedIndex = i;
        return;
      }
    }
    selectElement.selectedIndex = 0;
  }
}

/* -------------------------- Validation Functions -------------------------- */

var validators = new Object();

validators['Required'] = function(inputElement)
{
  if (isBlank(inputElement)) {
    var elementType = inputElement.type;
    var fieldIdentifier = getFieldIdentifier(inputElement);
    var fieldLabel = getFieldLabel(inputElement);
    var errorMessage = '';
    if (elementType == 'text' || elementType == 'textarea' || elementType == 'file')
      errorMessage = 'The ' + fieldLabel + ' field is required and cannot be blank.\n' +
        'Please enter a value, then re-submit the form...';
    else if (elementType == 'select-one')
      errorMessage = 'Please select ' + fieldLabel +
        ', then\nre-submit the form...';
    else if (elementType == 'password') {
      if (fieldIdentifier.match(/Confirm/)) {
        fieldLabel = fieldLabel.replace(/(Confirm | Confirm)/, '');
        errorMessage = 'For confirmation, please enter your ' + fieldLabel + ' twice...';
      }
      else
        errorMessage = 'Please enter ' + getPrefixArticle(fieldLabel) + fieldLabel + '...';
    }
    showValidationError(inputElement, errorMessage);

    return false;
  }
  return true;
};

validators['Alphanumeric'] = function(inputElement)
{
  if (!isBlank(inputElement) && !isAlphanumeric(inputElement.value)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can contain only letters and digits, and no spaces.\nPlease ' +
      'check the value, then re-submit the form...');
    return false;
  }
  return true;
};

validators['Alphabetic'] = function(inputElement)
{
  var alphabeticPattern = /^[A-Za-z]+$/;

  if (!isBlank(inputElement) && !inputElement.value.match(alphabeticPattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can contain only letters, and no digits or spaces.\nPlease ' +
      'check the value, then re-submit the form...');
    return false;
  }
  return true;
};

validators['Date'] = function(inputElement)
{
  var datePattern = /^[0-9]?[0-9]\/[0-9]?[0-9]\/[0-9][0-9][0-9][0-9]$/;

  if (!isBlank(inputElement) && !inputElement.value.match(datePattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can only be input in mm/dd/yyyy format.\nPlease ' +
      'check the value, then re-submit the form...');
    return false;
  }
  return true;
};

validators['Time'] = function(inputElement)
{
  var timePattern = /^[0-1]?[0-9]:[0-5][0-9] ?[AaPp][Mm]$/;

  if (!isBlank(inputElement) && !inputElement.value.match(timePattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can only be input in 9:00AM format.\nPlease ' +
      'check the value, then re-submit the form...');
    return false;
  }
  return true;
};

validators['Numeric'] = function(inputElement)
{
  var numericPattern = /^[0-9]+$/;

  if (!isBlank(inputElement) && !inputElement.value.match(numericPattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can contain only digits, and no letters or spaces.\nPlease ' +
      'check the value, then re-submit the form...');
    return false;
  }
  return true;
};

validators['Password'] = function(inputElement)
{
  if (inputElement.type == 'password') {

    /* Ordinary password field... */
    if (!getFieldIdentifier(inputElement).match(/Confirm/)) {
      if (!isBlank(inputElement)) { /* don't check blank password fields */
        if (!isAlphanumeric(inputElement.value)) {
          showValidationError(inputElement, 'Passwords can contain only ' +
            'letters and numbers, and no spaces...');
          inputElement.value = '';
          return false;
        }
        else if (inputElement.value.length < minPasswordLength) {
          showValidationError(inputElement, 'Passwords must have at least ' +
            minPasswordLength + ' characters...');
          inputElement.value = '';
          return false;
        }
      }
    }

    /* Password confirmation field... */
    else {

      // Obtain the paired password element, and check for password match
      var pairedInputElement = (inputElement.form)[inputElement.name.replace(/Confirm/, '')];
      if (pairedInputElement != null
          && pairedInputElement.type == 'password'
          && !isBlank(pairedInputElement)) {
        if (inputElement.value != pairedInputElement.value) {
          showValidationError(pairedInputElement, 'The ' + getFieldLabel(pairedInputElement) +
            ' field and confirmation do not match.\nPlease re-enter the password...');
          inputElement.value = pairedInputElement.value = '';
          return false;
        }
      }
    }
  }
  return true;
};

validators['ZipPostalCode'] = function(inputElement)
{
  var zipPattern = /^((\d\d\d\d\d((-\d\d\d\d)?))|([A-Z]\d[A-Z] \d[A-Z]\d))$/;

  if (!isBlank(inputElement) && !inputElement.value.match(zipPattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field must contain a five-digit ZIP code,\n' +
      'ZIP+4 code (99999-9999), or Canadian postal code (A9A 9A9).\n' +
      'Please check the value, then re-submit the form...');
    return false;
  }
  return true;
}

validators['PhoneNumber'] = function(inputElement)
{
  var phonePattern = /^[0-9 ()\/.x-]*$/;

  if (!inputElement.value.match(phonePattern)) {
    showValidationError(inputElement, 'The ' + getFieldLabel(inputElement) +
      ' field can contain only digits and common\n\"phone number\" characters ' +
      '[ ( ) - / . x ]. Please check\nthe value, then re-submit the form...');
    return false;
  }
  return true;
}

validators['EmailAddress'] = function(inputElement)
{
  var emailPattern = /^([^@. ]+\.)*[^@. ]+@([^@. ]+\.)+[^@. ]+$/;

  if (!isBlank(inputElement) && !inputElement.value.match(emailPattern)) {
    showValidationError(inputElement, 'Invalid E-mail address. Please check ' +
      'the format,\nthen re-submit the form...');
    return false;
  }
  return true;
}

validators['URL'] = function(inputElement)
{
  var urlPattern = /^(http:\/\/|https:\/\/|mailto:)([^. ]+\.)+[^. ]+$/;

  var url = inputElement.value;

  if(!getFieldIdentifier(inputElement).match(/LinkText/)) {
    if (!isBlank(inputElement) && !url.match(urlPattern)) {
      showValidationError(inputElement, 'Invalid URL' +
        (url.indexOf('http://') != 0 && url.indexOf('https://') != 0 && url.indexOf('mailto:') != 0 ?
          ' (must begin with \'http://\' or \'https://\' or \'mailto:\')' : '') +
          '. Please check the format,\nthen re-submit the form...');
      return false;
    }
  } else {
    // Obtain the paired URL element
    var pairedInputElement = (inputElement.form)[inputElement.name.replace(/LinkText/, '')];
    if (pairedInputElement != null && !isBlank(pairedInputElement)) {
      if (isBlank(inputElement)) {
        errorMessage = 'The ' + getFieldLabel(inputElement) +
          ' field cannot be blank.\nPlease enter ' + getFieldLabel(inputElement) + ' and re-submit the form...';
        inputElement.focus();
        alert(errorMessage);
        scrollBy(0,-42);
        return false;
      }
    }
  }
  return true;
}

function showValidationError(inputElement, errorMessage)
{
  inputElement.focus();
  alert(errorMessage);
  if (scrollPage) scrollBy(0,-20);
}



/* String Utility Functions */

function isAlphanumeric(str)
{
  return str.match(/^[A-Za-z0-9]+$/);
}

function trim(str)
{
  if (str != null) {
    str = str.replace(/(\r\n)/g, '\n');
    str = str.replace(/[\f\r]+/g, '\n');  /* test for \v fails in IE */
    str = str.replace(/[\t]+/g, ' ');
    str = str.replace(/ [ ]+/g, ' ');
    str = str.replace(/^ /, '');
    str = str.replace(/ \n/g, '\n');
    str = str.replace(/\n /g, '\n');
    str = str.replace(/ $/, '');
    str = str.replace(/\n\n[\n]+/g, '\n\n');
    str = str.replace(/^\n\n/, '');
    str = str.replace(/^\n/, '');
    str = str.replace(/\n\n$/, '');
    str = str.replace(/\n$/, '');
  }
  return str;
}

function getPrefixArticle(str)
{
  return (str.match(/^[AEIOU]/) ? 'an ' : 'a ');
}

function ValidateAndSubmit( form )
{
	if( validate(form, null) ) form.submit();
}
