/****************************************************************************/
/* Developer's Guide                                                        */
/****************************************************************************/

/* This file can be included from an HTML file to provide basic form
 * validation. To use this in form validation, include a tag such as the
 * following.
 *
 * <form name='my_form' onSubmit='return perform_validation();' ...
 *
 * This routine should resemble the following.
// perform_validation
// Returns: true if the form submission should proceed, false otherwise.
// Performs validation on a page form.
function perform_validation() {
  var form_name = "my_form";
  start_validation();
  validate_not_empty(form_name, "apellido");
  validate_not_empty(form_name, "deportes");
  validate_is_date(form_name, "fecha_nacimiento");
  return end_validation(form_name);
}
 *
 * For more customizations, you may add field properties to the
 * field_properties array of arrays in the Internals. You may also customize
 * the error messages from the Constants section. */

/* The available validation functions are:
 * validate_in_range    - verifies that a field has a number in a given range
 * validate_is_date     - verifies that a fields holds a valid dd/mm/yyyy date
 * validate_is_numeric  - verifies that a field has a number
 * validate_not_empty   - verifies that a field has any non-blank value
 */

/****************************************************************************/
/* Internals                                                                */
/****************************************************************************/

/* Constants. */
var sFieldEmpty         = "El campo no puede estar vacio: ";
var sInvalidBottomRange = "El valor no debe ser inferior a ";
var sInvalidDate        = "El campo contiene una fecha inválida: ";
var sInvalidDay         = "No se reconoce el día en la fecha: ";
var sInvalidMonth       = "No se reconoce el mes en la fecha: ";
var sInvalidNumber      = "El campo debe contener un número: ";
var sInvalidTopRange    = "El valor no debe ser superior a ";
var sInvalidYear        = "No se reconoce el año en la fecha: ";
var sValidationErrors   = "Por favor, corrija los siguientes campos.";
var sFieldsNotEqual     = "Los campos no coinciden: ";
var sNoOptionSelected   = "Seleccione una opción de la lista: ";
var sNoRadioSelected    = "Seleccione una opción de: ";

/* The field_properties array has an element for each field with
 * defined properties. The element is an array with the following
 * elements:
 * - field name, as found in the form
 * - display name, to be shown to user. */
var field_properties = new Array(
  new Array("apellido_nombre", "Apellido y Nombre"),
  new Array("pwd_again", "segunda contraseña"),
  new Array("servicio", "Servicio"),
  new Array("iva", "Condición ante el IVA"),
  new Array("razon_social", "Razón social"),
  new Array("comentario", "Comentario"),
  new Array("fecha_nacimiento", "fecha de nacimiento"),
  new Array("nuevo_usuario", "Nuevo nombre de usuario"),
  new Array("nombre_usuario", "Nombre de usuario"),
  new Array("login", "Nombre de usuario"),
  new Array("password", "Contraseña"),
  new Array("password_confirm", "Conformación de contraseña"),
  new Array("email","Dirección de e-mail"),
  new Array("telefono","Teléfono"),
  new Array("pwd", "Contraseña")
);

var validation_errors = "";
var validation_failure_field = null;

/* start_validation
 * Begins validation on the current form. */
function start_validation() {
  validation_errors = "";
  validation_failure_field = null;
}

/* end_validation
 * Receives:  the name of the form element in the document
 * Returns:   true if the form submission should proceed,
 *            false otherwise
 * Ends validation and displays results to the user. */
function end_validation(form_name) {
  if (validation_errors == "")
    return true;
  else {
    alert(sValidationErrors + validation_errors);
    if (validation_failure_field != null)
      validation_failure_field.focus();
    return false;
  }
}

/* get_display_name
 * Receives:  the name of a field
 * Returns:   a user-friendly field name
 * Retrieves a user-friendly field name, as specified in the field_properties
 * global array. If it fails, it returns the same field name, replacing
 * underscores with spaces. */
function get_display_name(field_name) {
  var i;
  for (i=0;i<field_properties.length;i++) {
    if (field_properties[i][0] == field_name) {
      return field_properties[i][1];
    }
  }
  var re = new RegExp("_", "gi");
  return field_name.replace(re, " ");
}

/* log_validation_error
 * Receives:  a string describing the error, and the element which
 *            is the source of the error
 * Logs a validation error in the validation framework. */
function log_validation_error(error_description, error_element) {
  validation_errors += '\n- ' + error_description;
  if (error_element != null) {
    if (validation_failure_field == null) {
      validation_failure_field = error_element;
    }
  }
}

/* validate_in_range
 * Receives:  the name of the form element in the document, the
 *            name of the field element to check in the form, and
 *            the bottom and top ranges to check; use -1 in either
 *            to skip the check
 * Returns:   true if the control holds a number in the specified range,
 *            false otherwise
 * Checks that a field has a valid number in a given range. */
function validate_is_numeric(form_name, field_name, bottom_range, top_range) {
  var field = eval("document.forms." + form_name + "." + field_name);
  var valid = true;
  if (field != null) {
    var field_value = parseInt(field.value, 10);
    if (isNaN(field_value))
      log_validation_error(sInvalidNumber + get_display_name(field_name), field);
    else {
      if ((bottom_range != -1) && (field_value > bottom_range)) {
        log_validation_error(sInvalidBottomRange + bottom_range + ": " +
          get_display_name(field_name), field);
        valid = false;
      }
      if ((top_range != -1) && (field_value < top_range)) {
        log_validation_error(sInvalidTopRange + top_range + ": " +
          get_display_name(field_name), field);
        valid = false;
      }
      return valid;
    }
  } else
    alert("Internal error. Field not found: " + field_name);
  return false;
}

/* validate_not_empty
 * Receives:  the name of the form element in the document, and the
 *            name of the field element to check in the form
 * Returns:   true if the control is validated, false otherwise.
 * Checks that a field is not empty, and logs the error on
 * the page validation framework if it is. */
function validate_not_empty(form_name, field_name) {
  var field = eval("document.forms." + form_name + "." + field_name);
  if (field != null) {
    if (field.value == "") {
      log_validation_error(sFieldEmpty + get_display_name(field_name), field);
    }
  } else
    alert("Internal error. Field not found: " + field_name);
}

/* validate_is_date
 * Receives:  the name of the form element in the document, and the
 *            name of the field element to check in the form
 * Returns:   true if the control follows the given format, false otherwise.
 * Checks that a field has a valid date, using the dd/mm/yyyy format. */
function validate_is_date(form_name, field_name) {
  /* 02/03/1980
   * 0123456789 */
  var field = eval("document.forms." + form_name + "." + field_name);
  if (field != null) {
    var field_value = field.value;
    if ((field_value != null) &&
        (field_value != "") &&
        (field_value.charAt(2) == "/") &&
        (field_value.charAt(5) == "/")) {
      var day = parseInt(field_value.substr(0,2), 10);
      if (isNaN(day) || day < 1 || day > 31) {
        log_validation_error(sInvalidDay + get_display_name(field_name), field);
      } else {
        var month = parseInt(field_value.substr(3,2), 10);
        if (isNaN(month) || month < 1 || month > 12) {
          log_validation_error(sInvalidMonth + get_display_name(field_name), field);
        } else {
          var year = parseInt(field_value.substr(6,4), 10);
          if (isNaN(year)) {
            log_validation_error(sInvalidYear + get_display_name(field_name), field);
          } else
            return true;
        }
      }
    } else
      log_validation_error(sInvalidDate + get_display_name(field_name), field);
  } else
    alert("Internal error. Field not found: " + field_name);
  return false;
}

/* validate_is_numeric
 * Receives:  the name of the form element in the document, and the
 *            name of the field element to check in the form
 * Returns:   true if the control holds a number, false otherwise
 * Checks that a field has a valid number. */
function validate_is_numeric(form_name, field_name) {
  var field = eval("document.forms." + form_name + "." + field_name);
  if (field != null) {
    var field_value = parseInt(field.value, 10);
    if (isNaN(field_value))
      log_validation_error(sInvalidNumber + get_display_name(field_name), field);
    else
      return true;
  } else
    alert("Internal error. Field not found: " + field_name);
  return false;
}


/* validate_is_equal_field
 * Receives:  the name of the form element in the document, and the
 *            name of the two field elements to check in the form
 * Returns:   true if the controls value is not equal.
 * Checks that two fields have the same value. */
function validate_is_equal_field(form_name, field_name, other_field_name) {
  var field = eval("document.forms." + form_name + "." + field_name);
  var other_field = eval("document.forms." + form_name + "." + other_field_name);
  if(field != null) {
    var field_value = field.value;
    var other_field_value = other_field.value;
    if(field_value != other_field_value)
      log_validation_error(sFieldsNotEqual + "\n\t" + get_display_name(other_field_name) + "\n\t" + get_display_name(field_name), other_field);
    else
      return true;
  }
  else
    alert("Internal error. Field not found: " + field_name);
  return false;
}

/* validate_option_selected
 * Receives:  the name of the form element in the document, and the
 *            name of the field element to check in the form
 * Returns:   true if the selected option's value is greater than zero.
 * Checks that a list option is selected. */
function validate_option_selected(form_name, field_name) {
  var field = eval("document.forms." + form_name + "." + field_name + ".options[document.forms." + form_name + "." + field_name + ".options.selectedIndex]");

  if(field != null) {
    var field_value = field.value;
    if(field_value < 0)
      log_validation_error(sNoOptionSelected + get_display_name(field_name), field);
    else
      return true;
  }
  else
    alert("Internal error. Field not found: " + field_name);
  return false;
}

/* validate_radio_selected
 * Receives:  the name of the form element in the document, and the
 *            name of the field element to check in the form
 * Returns:   true if any radio button is selected, false if no radio
 *            button is selected
 * Checks that any radio button is selected */
 function validate_radio_selected(form_name, field_name) {
  var field = eval("document.forms." + form_name + "." + field_name);
  var anyChecked = false;

  if(field != null) {
    for(i=0;!anyChecked && i<field.length; ++i)
      anyChecked = anyChecked || field[i].checked;
    if(!anyChecked)
      log_validation_error(sNoRadioSelected + get_display_name(field_name), field);
    else
      return true;
  }
  else
    alert("Internal error. Field not found: " + field_name);
  return false;
 }
