String.prototype.trim = function() {
    var x = this;
    x = x.replace(/^\s*(.*)/, "$1");
    x = x.replace(/(.*?)\s*$/, "$1");
    return x;
};
String.prototype.replaceAll = function(cadena1, cadena2) {
    var expresion = typeof(cadena1.source) != "undefined" ? cadena1.source : cadena1;
    var terminaEnCadena1 = new RegExp(expresion + "$").test(this);
    return this.split(cadena1).join(cadena2) + (terminaEnCadena1 ? cadena2 : "");
};

/* clase Parametro */
Parametro = function(elemento){
    var EXPRESION_REGULAR_PARAMETRO = "^([SL][ILFDTSBEAO][SN]([0-9]{4})[a-zA-Z0-9_.]+(\\[\\])?)$";
		
    var EXPRESION_REGULAR_ENTERO = "^-?[0-9]+$";
    var EXPRESION_REGULAR_DECIMAL = "^-?[0-9]+(\\.[0-9]+)?$";
    var EXPRESION_REGULAR_FECHA = "^(([3][01])|([12][0-9])|(0[1-9]))-((1[012])|(0[1-9]))-[0-9]{4}$";
    var EXPRESION_REGULAR_CADENA = "^(\\w|\\W)*$";
    var EXPRESION_REGULAR_BOOLEANO = "^(true)|(false)$";
    var EXPRESION_REGULAR_EMAIL = "^\\w([-_\\.]?\\w)*@\\w([-_\\.]?\\w)*\\.\\w{2,4}$";
    var EXPRESION_REGULAR_ARCHIVO = "^(\\w|\\W)*$";
    var EXPRESION_REGULAR_OTRO = "^(\\w|\\W)*$";
	
    var DELIMITADOR_ELEMENTOS_LISTA = ';';

    // Tipo de dato: I (Integer), L (Long), F (Float), D (Doble), T (Date, Time), S (String), B (Boolean), O (Otro, sin validación en particular)
    /** Tipo de dato entero (int)*/
    var TIPO_PARAMETRO_ENTERO = 'I';
    /** Tipo de dato entero largo (long)*/
    var TIPO_PARAMETRO_ENTERO_LARGO = 'L';
    /** Tipo de dato decimal (float) */
    var TIPO_PARAMETRO_DECIMAL = 'F';
    /** Tipo de dato decimal largo (double) */
    var TIPO_PARAMETRO_DECIMAL_LARGO = 'D';
    /** Tipo de dato fecha (Date) */
    var TIPO_PARAMETRO_FECHA = 'T';
    /** Tipo de dato cadena (String) */
    var TIPO_PARAMETRO_CADENA = 'S';
    /** Tipo de dato booleano (boolean) */
    var TIPO_PARAMETRO_BOOLEANO = 'B';
    /** Tipo de dato email (String con formato email) */
    var TIPO_PARAMETRO_EMAIL = 'E';
    /** Tipo de dato archivo (File) */
    var TIPO_PARAMETRO_ARCHIVO = 'A';
    /** Tipo de dato otro (sin definir) */
    var TIPO_PARAMETRO_OTRO = 'O';
	    
    // Dato simple o lista: S (Dato Simple),  L (Lista), M (Multiple)
    /** Tipo de dato simple */
    var TIPO_PARAMETRO_DATO_SIMPLE = 'S';
    /** Tipo de dato lista */
    var TIPO_PARAMETRO_LISTA = 'L';
    /** Tipo de dato múltiple */
    var TIPO_PARAMETRO_MULTIPLE = 'M';
	    
    // Dato obligatorio: S (Si), N (No)
    /** Tipo de dato obligatorio */
    var TIPO_PARAMETRO_OBLIGATORIO_SI = 'S';
    /** Tipo de dato opcional */
    var TIPO_PARAMETRO_OBLIGATORIO_NO = 'N';

    this.elemento = elemento;
    var error = null;

    var getValorElemento = function(elemento) {
        switch(elemento.type) {
            case "text":
            case "hidden":
            case "password":
            case "input":
            case "button":
            case "submit":
            case "image":
            case "reset":
            case "textarea":
            case "file":
                return typeof(elemento.value) == "undefined" ? "" : elemento.value;
                break;
            case "select-one":
                return elemento.options[elemento.selectedIndex].value;
                break;
            case "select-multiple":
                var valores = new Array();
                for (var i = 0; i < elemento.options.length; i++) {
                    if (elemento.options[i].selected) {
                        valores[valores.length] = elemento.options[i].value;
                    }
                }
                return valores.join(DELIMITADOR_ELEMENTOS_LISTA);
                break;
            case "checkbox":
            case "radio":
                return elemento.checked ? elemento.value : "";
                break;
            default:
                break;
        }
    };
	
    this.getValor = function(elemento) {
        if (typeof(elemento.options) == "undefined" && typeof(elemento.length) != "undefined") {	/* Es un array de campos y no es un select*/
            var valores = new Array();
            var valor = null;
            for (var i = 0; i < elemento.length; i++) {
                valor = getValorElemento(elemento[i]);
                if (valor != "") {
                    valores[valores.length] = valor;
                }
            }
            return valores.join(DELIMITADOR_ELEMENTOS_LISTA);
        } else {
            return getValorElemento(elemento);
        }
    };

    var id = typeof(elemento.name) == "undefined" ? elemento[0].name : elemento.name;
    var valor = this.getValor(elemento);
    var formato = id.substring(0, 7);
    var obligatorio = id.charAt(2) == TIPO_PARAMETRO_OBLIGATORIO_SI;
    var longitud = -1;
    var nombre = typeof(elemento.title) != "undefined" && elemento.title != "" ? elemento.title.toUpperCase() : id.substring(7).replace("[]", "").replaceAll("_", " ").toUpperCase();

    longitud = parseInt(id.substring(3, 7), 10);

    var validarTipoParametro = function() {
        var expresionRegular = null;
        var esDatoSimple = id.charAt(0) == TIPO_PARAMETRO_DATO_SIMPLE;
        var valores = esDatoSimple ? new Array(valor) : valor.split(DELIMITADOR_ELEMENTOS_LISTA);

        if (esDatoSimple && valores.length > 1) {
            return false;
        }

        var valorAux = null;
        for (var i = 0; i < valores.length; i++) {
            valorAux = valores[i];

            switch(id.charAt(1))
            {
                case TIPO_PARAMETRO_ENTERO:
                case TIPO_PARAMETRO_ENTERO_LARGO:
                    expresionRegular = EXPRESION_REGULAR_ENTERO;
                    error = JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_NUMERICO;
                    if (isNaN(parseInt(valorAux, 10))) {
                        alert(error);
                        return false;
                    }
                    break;
                case TIPO_PARAMETRO_DECIMAL:
                case TIPO_PARAMETRO_DECIMAL_LARGO:
                    expresionRegular = EXPRESION_REGULAR_DECIMAL;
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_NUMERICO
                    if(isNaN(parseFloat(valorAux))) {
                        alert(error);
                        return false;
                    }
                    break;
                case TIPO_PARAMETRO_FECHA:
                    expresionRegular = EXPRESION_REGULAR_FECHA;
                    error =  JS_ALERT_CAMPO+" "+ nombre + " "+JS_ALERT_FECHA_VALIDA;
                    break;
                case TIPO_PARAMETRO_CADENA:
                    expresionRegular = EXPRESION_REGULAR_CADENA;
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_CARACTERES_NOPERMITIDOS;
                    if ((valorAux.length > longitud)&&(longitud>0)) {
                        alert( JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_TIENE+" "+valorAux.length+" "+JS_ALERT_Y_EXCEDE_LONGITUD+"(" + longitud + ")");
                        return false;
                    }
                    break;
                case TIPO_PARAMETRO_BOOLEANO:
                    expresionRegular = EXPRESION_REGULAR_BOOLEANO;
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_BOOLEANO;
                    if(valorAux.toLowerCase() != "true" && valorAux.toLowerCase() != "false") {
                        alert(error);
                        return false;
                    }
                    break;
                case TIPO_PARAMETRO_EMAIL:
                    expresionRegular = EXPRESION_REGULAR_EMAIL;
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_EMAIL_VALIDO;
                    if (valorAux.length > longitud) {
                        alert( JS_ALERT_CAMPO+" " + nombre + " "+ JS_ALERT_EXCEDE_LONGITUD+"(" + longitud + ")");
                        return false;
                    }
                    break;
                case TIPO_PARAMETRO_ARCHIVO:
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_CARACTERES_NOPERMITIDOS;
                    expresionRegular = EXPRESION_REGULAR_ARCHIVO;
                    break;
                case TIPO_PARAMETRO_OTRO:
                    error =  JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_CARACTERES_NOPERMITIDOS;
                    expresionRegular = EXPRESION_REGULAR_OTRO;
                    break;
                default:
                    return false;
            }

            if (valorAux.match(new RegExp(expresionRegular, "g")) == null){
                alert(error);
                return false;
            }
        }

        return true;
    };

    this.validar = function() {

        if (this.elemento.name == "") {
            return true;
        } else if (id.match(new RegExp(EXPRESION_REGULAR_PARAMETRO, "g")) == null) {
            alert(JS_ALERT_PARAMETRO+" " + nombre + " "+JS_ALERT_NO_PERMITIDO);
            return false;
        } else {
            if (obligatorio && (valor == null || valor.trim() == "")) {
                alert( JS_ALERT_CAMPO+" " + nombre + " "+JS_ALERT_OBLIGATORIO);
                return false;
            } else if (valor == null || valor == "") {
                return true;
            } else {
                return validarTipoParametro();
            }
        }
        return true;
    };
};

/* obtiene los nombres de los campos del formulario */
function getListaNombreCampos(formulario) {
    var listaNombresCampos = "";
    for(var i = 0; i < formulario.elements.length; i++) {
        if (listaNombresCampos.indexOf(formulario.elements[i].name + ";") == -1) {
            listaNombresCampos += formulario.elements[i].name + ";";
        }
    }
    listaNombresCampos = listaNombresCampos.split(";");
    listaNombresCampos.length = listaNombresCampos.length != 0 ? listaNombresCampos.length - 1 : 0;
    return listaNombresCampos;
}

/* valida un formulario completo */
function validarFormulario(formulario) {

    var listaNombresCampos = getListaNombreCampos(formulario);
    for(var i = 0; i < listaNombresCampos.length; i++) {
        if (typeof(formulario[listaNombresCampos[i]]) != "undefined") {

            var parametro = new Parametro(formulario[listaNombresCampos[i]]);

            if (!parametro.validar()) {
                try {
                    formulario[listaNombresCampos[i]].focus();
                } catch (excepcion) { /* no hacemoas nada */ }
                return false;
            }
        }
    }

    return true;
}

/* valida una direccion de email */
function validarCorreo(direccion) {
    var nombre = '\\w([-_\\.]?\\w)*';
    var dominio = '\\w([-_\\.]?\\w)*';
    var extension = '\\.\\w{2,3}';
    var correo = nombre + '@' + dominio + extension;
	
    var expresionRegular = new RegExp ('^' + correo + '$');
	
    return expresionRegular.test (direccion);
}

/* valida varias direcciones de emal separadas por comas o por puntos y comas */
function validarCorreos(cadenaDirecciones) {
    var nombre = '\\w([-_\\.]?\\w)*';
    var dominio = '\\w([-_\\.]?\\w)*';
    var extension = '\\.\\w{2,3}';
    var correo = nombre + '@' + dominio + extension;
    var correos = correo + '(\\s*[;,]\\s*' + correo + ')*';
	
    var expresionRegular = new RegExp ('^' + correos + '$');
	
    return expresionRegular.test (cadenaDirecciones);
}

function validarTelefono(telefono, longitud) {
    if(!longitud) { longitud = 9; }

    var expresion = "^[0-9 ]*$";
    var esTelefono = (new RegExp(expresion)).test(telefono);
    return esTelefono && telefono.replaceAll(" ", "").length >= 9 && telefono.length <= longitud;
}

function validarFax(fax) {
    validarTelefono(fax);
}

function isCaracterEspecial(charCode) {
    return [0, 8, 9, 13].indexOf(charCode) != -1;
}

function isCaracterOperacion(keyCode) {
    return [13, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46].indexOf(keyCode) != -1;
}

function isTeclaControl(keyCode) {
    return [0, 8, 9, 13, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46].indexOf(keyCode) != -1;
}

function isCaracterNumerico(charCode) {
    return (charCode >= 48 && charCode <= 57) || charCode == 0 || typeof charCode == "undefined";
}

function isCaracterTelefono(charCode){
    return (charCode >= 48 && charCode <= 57) || charCode==40
          || charCode==41 || charCode==43 || charCode==45 || charCode == 0 || typeof charCode == "undefined";
}

function isCaracterDatoNumerico(charCode) {
    return isCaracterNumerico(charCode) || charCode == 46;
}

/* para compatibilidades con firefox, ie, chrome y opera */
function getEventCodes(evento) {
    var keyCode = evento.keyCode;
    var charCode = typeof evento.charCode == "undefined" ? 0 : evento.charCode;

    if(typeof evento.charCode != "undefined") { /* firefox y chrome */
        if(evento.keyCode == evento.charCode) {
            keyCode = 0;
        }
    } else if(typeof evento.which == "undefined") { /* ie */
        charCode = evento.keyCode;
        keyCode = 0;
    } else { /* opera */
        charCode = evento.which && isCaracterEspecial(keyCode) ? 0 : keyCode;
        keyCode = charCode ? 0 : keyCode;
    }

    return {'charCode': charCode, 'keyCode': keyCode};
}

function validarSoloNumeros(evento) {
    var c = getEventCodes(evento);
    
    return isTeclaControl(c.keyCode) && isCaracterNumerico(c.charCode);
}

function validarSoloNumerosTelefono(evento) {
    var c = getEventCodes(evento);

    return isTeclaControl(c.keyCode) && isCaracterTelefono(c.charCode);
}

function validarDatoNumerico(evento) {
    var c = getEventCodes(evento);

    return isTeclaControl(c.keyCode) && isCaracterDatoNumerico(c.charCode);
}

function limitarLongitud(campo, longitud, evento) {
    var c = getEventCodes(evento);
    
    return campo.value.length < longitud || isTeclaControl(c.keyCode);
}
