/*
 * API de Validación.
 *
 * .Funciones útiles
 *
 * .Funciones de validacion
 * .-conceptuales
 * .-numéricas
 * .-fecha y hora
 * .-alfabéticas
 * .-RUT
 * .-específicas
 */

//esta es la función que se invoca para validar los templates en json
function validar(json){
	var ok=true;
	//buscamos todos los nodos del arbol que tengan validación y ejecutamos la validación
	if(json['validacion']){
		//_error('VALIDAR: hay validación de:'+json['validacion']);
		//ejecutamos la validación para ese campo
		var validacion="marcador_"+json['validacion']+"($(':input[name=\""+json['nombre']+"\"]'));";
		//_error(validacion);
		//alert(validacion);
		if(!(datos_sistema['campo_oculto'].join().indexOf(json['nombre'])>=0)){
			ok = eval(validacion);
			//_error('VALIDAR: '+validacion+'='+ok);
		}
		//_error("ok: "+ok+" validacion: "+validacion);
		//if(!ok){ alert ("error en: marcador_"+json['validacion']+"($(':input[name=\""+json['nombre']+"\"]'));"); }
	}else if (json['templates']){
		//_error('VALIDAR: hay template');
		//recorremos los templates y pedimos la validación de cada uno
		for(var i in json['templates']){
			ok = validar(json.templates[i]) && ok;
		}
	}
	//retornamos el ok, si no hay nada que validar se retorna true.
	return ok;
}

/*
 * solo se llama desde parser_js.js
 * invoca a las parser_ que están todas en parser_js.js
 * considerar moverla pa quel chrome no reclame
 * Uncaught ReferenceError: event_validar is not defined
 * done.
function event_validar(json){
	var ok=true;
	//buscamos todos los nodos del arbol que tengan validación y ejecutamos la validación
	if(json['validacion']){
		//ejecutamos la validación para ese campo
		var validacion="parser_"+json['validacion']+"($(':input[name=\""+json['nombre']+"\"]'));";
		//alert(validacion);
		//hacer if contra arreglo global.
		if(!(datos_sistema['campo_oculto'].join().indexOf(json['nombre'])>=0)){
			ok = eval(validacion);
		}
	}else if (json['templates']){
		//recorremos los templates y pedimos la validación de cada uno
		for(var i in json['templates']){
			ok = event_validar(json.templates[i]) && ok;
		}
	}
	//retornamos el ok, si no hay nada que validar se retorna true.
	return ok;
}
 */

//trim de left y right espacios
function trim_lrsp(obj){
	if(obj.disabled){
		return true;
	}
	var trim = obj.val();

	//trimeamos, ojo con los loops infinitos
	while(trim.charAt(0) == ' '){
		trim = trim.substring(1);
	}
	while(trim.charAt(trim.length-1) == ' '){
		trim = trim.substring(0,trim.length-1);
	}
	obj.val(trim);
	return true;
}

//trim de espacios dobles seguidos.
function trim_dblsp(obj){
	if(obj.disabled){
		return true;
	}
	var trim = obj.val();
	var filter = /  +/;
	if(filter.test(trim)){
		//el replace pone el cursor al final del texto en IE6 de VM (en el mío no).
		trim = trim.replace(/  +/g," ");
		obj.val(trim);
	}
	return true;
}

//deprecada, ahora usamos metadata
function busca_json_pestana(json,nombre){
	var ret=false;
	var value;

	for(var i in json.pestanas){
		value = busca_json(json.pestanas[i],nombre);
		if( typeof value == 'object' ){
			ret=value;
		}
	}

	return ret;
}

//deprecada, ahora usamos metadata
function busca_json(json,nombre){

	var aux;
	if(json['nombre'] && json['nombre']==nombre){
		//alert("return: "+json.nombre);
		return json;
	}
	else if(json['templates']){
		//alert("templates");
		for(var i in json.templates){
			aux = busca_json(json.templates[i],nombre);
			if(typeof aux == 'object'){
				return aux;
			}
		}
	}
	
	return false;
}

/*
function toNatural(val){
	var num=val.value;
	var tmpstr="";
	for(i=0; i<num.length;i++){
		if(isDigit(num.charAt(i))){
			tmpstr+=num.charAt(i);
		}
	}
	val.value=tmpstr;
	return true;
}
*/

/*************************************************************************
 * Validaciones conceptuales
 * **********************************************************************/

//dominio
//TODO mejorar, tomando el dominio repsectivo
//en términos prácticos, es casi un not_null
function validador_dominio(input){
	//var obj_input = $(":input",obj.parent());
	//var valor = obj_input.val();
	var valor = input.val();
	var metadata = input.metadata();
	var parametro_aux;
	var nombre;
	//_alert('parametro: '+metadata.parametro);
	
	if(typeof input.metadata().nombre_parametro == "string"){
		nombre=input.metadata().nombre_parametro;
	}else{
		nombre=input.attr("name");
	}
	//alert('voy a validar: '+nombre);
	//soporte para metadata
	if(metadata['parametro']){
		//alert('voy a validar contra '+metadata.parametro);
		if(metadata['parametro']=='_seq'){//parametro especial que significa que se usara una secuencia en vez de un parametro
			if(!metadata['min']){//tenemos el minimo, de lo contrario usamos el del imput
				inicio=input.val()*1;
			}else{
				inicio=metadata['min'];
			}

			if(!metadata['max']){//ERROR siempre debe estar definido el maximo
				_alert("error de construccion, se intento hacer un select con secuencia sin maximo");
			}else{
				termino=metadata['max'];
			}
			parametro_aux = new Array();
			for (var i=inicio;i<=termino;i++){
				parametro_aux[i]=i;
			}
		}else if(metadata['cadena']){//hay q sacar los datos de otro campo
			campo=$(":input[name='"+metadata['cadena']+"']").val();
			parametro_aux=eval(metadata['parametro']+"['"+campo+"']");
		}else{
			parametro_aux=eval(metadata['parametro']);
		}
	}else if(metadata['except']){
		//no mostramos el campo indicado en este input
		//id del campo
		campo=$(":input[name='"+metadata['except']+"']").val();
		parametro_aux=parametro[nombre];
	}else{
		parametro_aux=parametro[nombre];
	}
	//_error('val_dom: '+metadata+' val: '+valor);
	if(input.disabled){
		return true;
	}
	if (valor==null||valor==''){
		//el valor no puede ser nulo, ahora comparamos con los 
		return false;
	}else{//verificamos que este en el dominio
		//alert('verificando que este en el dominio:'+valor);
		var nulo=(valor==metadata['nulo']);
		var aux;
		for (var id in parametro_aux){
			//seteamos el valor del input
			if(nulo){
				//alert('el valor es nulo, lo aceptamos');
				return true;
			}else if(metadata['val']=='text'){
				aux=parametro_aux[id];
			}else if(metadata['val']=='full'){
				aux=id+". "+parametro_aux[id];
			}else{ 
				aux=id;
			}
			//alert('verificando contra:'+aux);
			if(aux==valor){
				//alert('valor encontrado: '+aux);
				return true;
			}
		}
	}
	//alert('no encontre el valor para '+nombre);
	return false;
}

//distinto de vacio
function validador_not_null(obj){
	var valor = obj.val();
	if(obj.disabled){
		return true;
	}
	if (valor==null||valor==''){
		return false;
	}
	return true;
}

//que esté marcado
function validador_radio(obj){
	if(obj.disabled){
		return true;
	}
	//se separan los if para que no reclame que estan undefined
	if(obj[0].checked){
		return true;
	}
	if(obj[1].checked){
		return true;
	}
	return false;
}

//valida un solo checkbox
function validador_checkbox(obj){
	if(obj.disabled){
		return true;
	}
	if(obj.is(':checked')){
		return true;
	}
	return false;
}

//Valida que los dos campos sean iguales.
function validador_igual(obj){
	if(obj.disabled) return true;
	var data = obj.metadata();
	//buscamos el otro campo
	var obj2 = $(":input[name='"+data.campo+"']");
	//retornamos si son iguales
	return obj.val() == obj2.val();
}

//Valida que los dos correos sean iguales.
function validador_correo_igual(obj){
	var obj_aux, obj_dominio;
	if(obj.disabled) return true;
	//alert(obj.attr("name").split(/_dominio/)[0]);
	//primero hay que averiguar si es dominio o usuario.
	if(obj.attr("name").split(/_dominio/)[0]==obj.attr("name")){//es usuario
		obj_dominio= $(":input[name='"+obj.attr("name")+"_dominio']");
	}else{//es dominio, invertimos las variables.
		obj_aux=obj;
		obj_dominio=obj;
		obj=$(":input[name='"+obj.attr("name").split(/_dominio/)[0]+"']");
	}
	var data = obj.metadata();
	//buscamos el otro campo
	var obj2 = $(":input[name='"+data.campo+"']");
	var obj2_dominio= $(":input[name='"+obj2.attr("name")+"_dominio']");
	//retornamos si son iguales
	return obj.val() == obj2.val() & obj_dominio.val() == obj2_dominio.val();
}

/*************************************************************************
 * Validaciones numéricas
 * **********************************************************************/

//que ho hayan dos o mas espacios seguidos.
//

//numero entre -32000 y 32000
function validador_smallint(obj){
	if(obj.disabled){
		return true;
	}

	//tomar el valor
	var valor = obj.val();
	//poco elegante
	valor = "0"+valor;
	valor = parseInt(valor,10);
	if( isNaN(valor) || valor < -32001 || valor > 32001 ){
		return false;
	}
	else{
		return true;
	}
	return false;
	//return valor > -32001 && valor < 32001;
}

//numero mayor que cero
function validador_ingreso(obj){
	if(obj.disabled){
		return true;
	}

	//tomar el valor
	var ok = false ;
	var valor = obj.val();
	var filter = /\./;
	//primero reemplazamos las , por .
	valor = valor.replace(/,/g,'.');
	//separamos caso con y sin formato
	if( filter.test(valor) ){
		//con formato
		//_error("con formato");
		filter = /^\s*((\d{1,3})|(\d{1,3}\.\d{3})|(\d{1,3}\.\d{3}\.\d{3}))\s*$/;
		ok = filter.test(valor);
	}
	else{
		//sin formato
		//_error("sin formato");
		filter = /^\s*\d*\s*$/;
		ok = filter.test(valor);
	}
	if( ok ){
		//poco elegante
		valor = "0"+valor;
		valor = parseInt(valor,10);
		return valor >= 0 & valor < 10000000;
	}

	return false;
}

//mayor que cero
//not null
function validador_ingreso_total(obj){
	if(obj.disabled){
		return true;
	}

	//tomar el valor
	var ok = false ;
	var valor = obj.val();
	var filter = /\./;
	//primero reemplazamos las , por .
	valor = valor.replace(/,/g,'.');
	//separamos caso con y sin formato
	if( filter.test(valor) ){
		//con formato
		//_error("con formato");
		filter = /^\s*((\d{1,3})|(\d{1,3}\.\d{3})|(\d{1,3}\.\d{3}\.\d{3}))\s*$/;
		ok = filter.test(valor);
	}
	else{
		//sin formato
		//_error("sin formato");
		filter = /^\s*\d+\s*$/;
		ok = filter.test(valor);
	}
	if( ok ){
		//poco elegante
		valor = "0"+valor;
		valor = parseInt(valor,10);
		return valor >= 0 & valor < 100000000;
	}

	return false;
}

function clean_ingreso(str_ingreso){
	var ret = str_ingreso.replace(/[^\d]/g,"");
	if( ret == "" ){
		//_error("clean:0");
		return 0;
	}
	else{
		//forzamos base 10 por si vienen 0's al principio
		return parseInt(ret,10);
	}
}

function clean_input_ingreso(input){
	var valor = input.val();
	return input.val(clean_ingreso(valor));
}

function format_input_ingreso(input){
	var valor = input.val();
	return input.val(format_ingreso(valor));
}

function format_ingreso(str_ingreso){
	//agregamos los puntos al ingreso
	var tmprut = "";
	var str = str_ingreso+"";
	var largo = str.length-1;
	if( largo < 0 ){
		return "0";
	}
	for ( i=largo; i >= 0; i-- ){
		if( (largo+1-i)%4 == 0 ){
			tmprut = '.' + tmprut ;
			largo++;
		}
		tmprut = str.charAt(i) + tmprut ;
	}
	return tmprut ;
}

//numerico d,d 4,0 a 7,0
function validador_nota(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();//attr("value");
	//primero reemplazamos los . por ,
	var re=/,/g;
	valor = valor.replace(re,'.');
	//veamos si calza con la ER
	var filter=/^(([4-6](\.[0-9])?)|7|7\.0)$/;
	if(filter.test(valor)){
		obj.val(valor);
		return true;
	}
	else{
		return false;
	}
}

function validador_telefono(obj,obj_area){
	if(obj.disabled){
		return true;
	}
	var fono = obj.val();
	var filter=/^\d+$/;

	if(filter.test(fono)){
		//forzamos base 10 por si vienen 0's al principio
		fono = parseInt(fono,10);
		//volvemos a String, limpio de 0's al principio
		fono = fono+""; 
		//el telefono debe tener entre 6 y 7 caracteres
		//según el código de área
		var largo_cod_area = parametro['cod_area_largo'][obj_area.val()];
		//_error("cod area= "+largo_cod_area);
		if( fono.length == largo_cod_area ){
			return true;
		}
		else{
			return false;
		}
	}
	else{
		return false;
	}

	return false;
}

function check_celular(str){
	//if(str.length!=8) return false;
	var filter=/^[6-9]\d{7}$/;
	if( filter.test(str) ){
		return true;
	}
	else{
		return false;
	}
}

//edad mayor que cero y menor que 120
//edad igual que cero para los neonatos
function validador_edad(obj){
	if(obj.disabled){
		return true;
	}
	var edad = obj.val();
	var filter=/^\d+$/;

	if(filter.test(edad)){
		//forzamos base 10 por si vienen 0's al principio
		edad = parseInt(edad,10);
		//evitamos las edades 0.x
		if( edad >= 0 && edad < 120 ){
			return true;
		}
		else{
			return false;
		}
	}
	return false;
}

//cantidad de integrantes grupo familiar
function validador_cantidad_familiares(obj){
	if(obj.disabled){
		return true;
	}
	var cantidad = obj.val();
	var filter=/^\d$/;

	if(filter.test(cantidad)){
		//forzamos base 10 por si vienen 0's al principio
		cantidad = parseInt(cantidad,10);
		//evitamos las cantidades 0.x
		if( cantidad > 0 && cantidad <= parametro['max_integrantes_familia'] ){
			return true;
		}
		else{
			return false;
		}
	}
	return false;
}

//validación para el id_comprobante
function validador_id_comprobante(obj){
	if(obj.disabled){
		return true;
	}
	var id_comprobante = obj.val();
	var filter=/^\d{11}$/;

	if(filter.test(id_comprobante)){
		return true;
	}
	return false;
}

/*************************************************************************
 * Validaciones fecha y hora
 * **********************************************************************/

//minimo: anio actual -75
//maximo: anio actual -15
function validador_fecha_nacimiento(obj){
	//se hace con DateEntry
}

function validador_fecha(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();//attr("value");
	//primero reemplazamos los . por ,
	//veamos si calza con la ER
	//var filter=/^[0-9][0-9]\/[0-9][0-9]\/[0-9][0-9][0-9][0-9]$/;
	//TODO mejorar la validación
	//2008-10-13 00:00:00
	var filter=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
	if(filter.test(valor)){
		obj.val(valor);
		return true;
	}
	else{
		return false;
	}
}

function validador_fecha_ddmmaaaahhmmss(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();//attr("value");
	var filter=/^\d{2}\/\d{2}\/\d{4} \d{2}:\d{2}:\d{2}$/;
	if(filter.test(valor)){
		obj.val(valor);
		return true;
	}
	else{
		return false;
	}
}

function validador_fecha_hhmmssddmmaaaa(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();//attr("value");
	var filter=/^\d{2}:\d{2}:\d{2} \d{2}\/\d{2}\/\d{4}$/;
	if(filter.test(valor)){
		obj.val(valor);
		return true;
	}
	else{
		return false;
	}
}

function validador_fecha_dma(obj){
	if(obj.disabled){
		return true;
	}

	var ret = false;

	var valor = obj.val();

	//TODO mejorar la validación
	var filter=/^\d{2}\/\d{2}\/\d{4}$/;
	if(filter.test(valor)){
		obj.val(valor);
		ret = true;
	}
	else{
		return false;
	}
	//var data = obj.metadata();
	//var val_ini = $("#"+data['campos'][0]).val();
	//var val_ter = $("#"+data['campos'][1]).val();

	//if( obj.attr("id") != "fecha_inicio_periodo" && obj.attr("id") != "fecha_termino_periodo" ){//data['campos'].length <= 2 ){
	//if( data['campos'].length < 0 ){
		//data = $(".seleccione",obj.parent()).metadata();
	//}
	//else{

	//validación para periodos con dateentry que pisa la metadata
        if( obj.attr("id") != "fecha_inicio_periodo" && obj.attr("id") != "fecha_termino_periodo" ){//data['campos'].length <= 2 ){
	}
	else{

		var val_ini = $("#fecha_inicio_periodo").val();
		var val_ter = $("#fecha_termino_periodo").val();

		if ( val_ini != '' & val_ter != '' ){
			val_ini = ''+val_ini.split("/")[2]+val_ini.split("/")[1]+val_ini.split("/")[0];
			val_ter = ''+val_ter.split("/")[2]+val_ter.split("/")[1]+val_ter.split("/")[0];
			if( val_ini >= val_ter ){
				return false;
			}
		}
	}

	return ret;
}

function validador_hora_hms(obj){
	if(obj.disabled){
		return true;
	}

	var ret = false;

	var valor = obj.val();

	//TODO mejorar la validación
	//var filter=/^\d{2}\/\d{2}\/\d{4}$/;
	var filter=/^\d{2}:\d{2}:\d{2}$/;
	if(filter.test(valor)){
		obj.val(valor);
		ret = true;
	}
	else{
		return false;
	}

	return ret;
}

/*************************************************************************
 * Validaciones alfabéticas
 * **********************************************************************/

//OJO esta es alfanumérica :P
//Soporta los siguientes caracteres: [0-9],[A-Z],[a-z], slash, punto, guión, underscore.
//sin espacios al final.
function validador_sysname(obj){
	if(obj.disabled){
		return true;
	}
	var nombre = obj.val();

	_error('sysname: '+nombre);
	//sin espacio al final.
	var filter=/^[0-9a-z\/\-_. ]*[0-9a-z\/\-_.]+$/i;
	if (filter.test(nombre)){
		return true;
	}

	return false;
}

function validador_sysname_null(obj){
	if(obj.disabled){
		return true;
	}
	var nombre = obj.val();

	if( nombre == "" ){
		return true;
	}

	//sin espacio al final.
	var filter=/^[0-9a-z\/\-_. ]*[0-9a-z\/\-_.]+$/i;
	if (filter.test(nombre)){
		return true;
	}

	return false;
}

function validador_departamento(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();

	if( valor == "" ){
		return true;
	}
	else{
		return validador_direccion(obj);
	}
}

function validador_poblacion(obj){
	if(obj.disabled){
		return true;
	}
	var valor = obj.val();

	if( valor == "" ){
		return true;
	}
	else{
		return validador_direccion(obj);
	}
}

//Soporta los siguientes caracteres: [0-9][A-Z][a-z]
//Ñ,ñ, áéíóúüö guión, apóstrofes, espacios, slash, punto, coma
//sin símblolos al principio
function validador_direccion(obj){
	if(obj.disabled){
		return true;
	}
	var nombre = obj.val();

	var filter=/^[ñöüá-úa-z0-9][ñöüá-úa-z0-9\-' \/\.,]*$/i;
	if (filter.test(nombre)){
		return true;
	}
	else{
		return false;
	}
}

//Soporta los siguientes caracteres: [A-Z][a-z] Ñ,ñ,
//áéíóúüö blancos, apóstrofes, guión.
//sin símblolos al principio.
function validador_nombre(obj){
	if(obj.disabled){
		return true;
	}
	var nombre = obj.val();

	//sin espacios al final es demasiado restrictivo, considerar usabilidad.
	//filter=/^[ñöüá-úa-z\-' ]*[ñöüá-úa-z\-']+$/i;
	//sin símblolos al principio
	var filter=/^[ñöüá-úa-z][ñöüá-úa-z\-' ]*$/i;
	if (filter.test(nombre)){
		return true;
	}

	return false;
}

//Soporta los siguientes caracteres: [A-Z][a-z] Ñ,ñ,
//áéíóúüö blancos, apóstrofes, guión.
//sin símblolos al principio.
function validador_nombre_vacio(obj){
	if(obj.disabled){
		return true;
	}
	var nombre = obj.val();

	//sin espacios al final es demasiado restrictivo, considerar usabilidad.
	//filter=/^[ñöüá-úa-z\-' ]*[ñöüá-úa-z\-']+$/i;
	//sin símblolos al principio, soporta vacío
	var filter=/^[ñöüá-úa-z]*[ñöüá-úa-z\-' ]*$/i;
	if (filter.test(nombre)){
		return true;
	}

	return false;
}

function validador_apellido_paterno(obj){
	return validador_nombre(obj);
}
function validador_apellido_materno(obj){
        return validador_nombre(obj);
}

function validador_usuario_correo(obj){
        if(obj.disabled){
		return true;
	}
	var usuario = obj.val();
	//el anulador de backreference está de más...
	//soportamos punto, guión y símbolo de suma.
	var filtro_usuario=/^([\w-+]+(?:\.[\w-+]+)*)$/i;
	return filtro_usuario.test(usuario);
}

function validador_dominio_correo(obj){
	if(obj.disabled){
		return true;
	}

	var dominio = obj.val();
	//OJO, revisar filtro
	var filtro_dominio=/^((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
	return filtro_dominio.test(dominio);
}

/*************************************************************************
 * Validaciones RUT
 * **********************************************************************/

function check_rut_alumno(str){
	//retorna un rut bueno o vacio
	//OJO
	//hacer con string format
	var rut = parseInt(str.replace(/[^\d]/g, ""),10);
	//rut alumno minimo un millon 1.000.000
	if( isNaN(rut) || rut < 1000000 || rut >= 50000000 ){
		return "";
	}

	return ""+rut;
}

function check_rut_familiar(str){
	if( str == undefined ){
		return "";
	}
	//retorna un rut bueno o vacio
	var rut = parseInt(str.replace(/[^\d]/g, ""),10);
	//rut familiar minimo cien mil 100.000
	if( isNaN(rut) || rut < 100000 || rut >= 50000000 ){
		return "";
	}

	return ""+rut;
}

function check_rut_generico(str){
	if( str == undefined ){
		return "";
	}
	//retorna un rut bueno o vacio
	var rut = parseInt(str.replace(/[^\d]/g, ""),10);
	//rut genérico, mínimo cero, máximo 8 dígitos
	if( isNaN(rut) || rut < 1 || rut > 99999999 ){
		return "";
	}

	return ""+rut;
}

//no se usa
function format_rut(str){
	return format_ingreso(str);
}

//por completitud
//para RUT's fuera de rango
/*
function validador_rut_generico(obj_rut){
	var ret=check_rut_generico(obj_rut.val())==""?false:true;
	_error('generico: '+ret);
	return ret;
}
*/

function validador_rut_generico(obj_rut){

	var obj_rut_class = obj_rut.attr("class");
	var obj_dv = $("."+obj_rut_class+"_dv",obj_rut.parent());
	var rut_ok = false ;
	var dv_ok = false ;

	//check de rut
	var rut = check_rut_generico(obj_rut.val());
	if( rut != "" ){
		rut_ok = true;
		//actualizamos el input
		obj_rut.val(rut);
	}
	else{
		obj_rut.parent().addClass("error");
	}

	if( obj_dv.val() == "" ){
		obj_dv.parent().addClass("error");
	}
	else if ( checkDV(obj_rut,obj_dv) ){
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().removeClass("error");
		dv_ok = true;
	}
	else{
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().addClass("error");
	}
	var ret = rut_ok & dv_ok ;
	return ret ;
}

//Soporta lo siguiente: Módulo 11+dv, con Mínimo
//'1.000.000', Máximo '49.999.999'.
function validador_rut_alumno(obj_rut){

	var obj_dv = $(".rut_alumno_dv",obj_rut.parent());
	var rut_ok = false ;
	var dv_ok = false ;

	//check de rut
	var rut = check_rut_alumno(obj_rut.val());
	if( rut != "" ){
		rut_ok = true;
		//actualizamos el input
		obj_rut.val(rut);
	}
	else{
		obj_rut.parent().addClass("error");
	}

	if( obj_dv.val() == "" ){
		obj_dv.parent().addClass("error");
	}
	else if ( checkDV(obj_rut,obj_dv) ){
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().removeClass("error");
		dv_ok = true;
	}
	else{
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().addClass("error");
	}
	var ret = rut_ok && dv_ok ;
	//alert("rut: "+rut_ok+" dv: "+dv_ok);
	return ret ;
}

function validador_rut_familiar_aux(obj_rut){

	var name = obj_rut.attr("name");

	var rut_ok = false ;
	var dv_ok = false ;

	//check de rut
	//var rut = format_rut(check_rut_familiar(obj_rut.val()));
	var rut = check_rut_familiar(obj_rut.val());
	if( rut != "" ){
		rut_ok = true;
		//actualizamos el input
		obj_rut.val(rut);
	}
	else{
		//obj_rut.parent().addClass("error");
		//el return salta validación contra DV cuando el RUT está malo
		return false;
	}

	//pasamos el rut, vemos dv
	//familiares[n][rut_familiar]
	var filter=/^familiares\[(\d+)\]\[(.*)\]$/;
	var aux = filter.exec(name);
	//var name_dv = "familiares["+aux[1]+"][rut_familiar_dv]";
	var obj_dv = $("input[name='familiares["+aux[1]+"][rut_familiar_dv]']");

	if( obj_dv.val() == "" ){
		//obj_dv.parent().addClass("error");
	}
	else if ( checkDV(obj_rut,obj_dv) ){
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		//obj_dv.parent().removeClass("error");
		dv_ok = true;
	}
	else{
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		//obj_dv.parent().addClass("error");
	}
	//el orden importa
	var ret = dv_ok && rut_ok ;

	return ret;
}

function validador_rut_familiar(obj_rut){

	var ret = marcador_rut_familiar_aux(obj_rut);
//	alert("marqué: "+obj_rut.val()+" como "+ret);
	if(!ret){ _error("rut malo"); return false; }

	//el RUT está bueno, continuamos.

	var name = obj_rut.attr("name");
	//veamos que no es del postulante
	if( obj_rut.val() == check_rut_familiar(datos_usuario['rut'].split("-")[0]) ){
	//OJO_REVISAR if( obj_rut.val() == check_rut_familiar( $("#rut_del_postulante_tabla_familiares").html().split("-")[0]) ){
		_error("rot=postulante");
		return false;
	}

	//veamos que no está repetido con otro familiar
	var array_de_inputs = $("#familiares .rut_familiar");

	//$("#familiares .rut_familiar").each(function(){marcador_rut_familiar_aux($(this));});

	for( var i=0; i < array_de_inputs.length; i++ ){
		//no me comparo conmigo mismo ni los anteriores
		//marcador_rut_familiar_aux(array_de_inputs.eq(i));
		for( var j=i+1; j < array_de_inputs.length; j++ ){
			//vemos si hay uno repetido
			if( array_de_inputs.eq(i).val() == array_de_inputs.eq(j).val() ){
//				_error("rut repetido en:<br/>"+i+": "+array_de_inputs.eq(i).val()+"<br/>"+j+": "+array_de_inputs.eq(j).val());
				//los ruts están estructuralmente buenos, asi que los marcamos a mano
				array_de_inputs.eq(i).parent().parent().toggleClass("error", true);
				array_de_inputs.eq(j).parent().parent().toggleClass("error", true);
				//ret tiene que ser true si es que el error es en otro lado
				//y false si es que el error es en el rut en cuestión.
				/*
				if( array_de_inputs.eq(i).attr('name') == obj_rut.attr('name') ){
					_error("este es");
					ret=false;
				}
				else{
					ret=true;
				}
				*/
				//ret=false;
			}
		}
	}

	return ret ;
}

function validador_rut_inscripcion(obj_rut){

	var obj_rut_class = obj_rut.attr("class");
	//_error("obj_rut_class: "+obj_rut_class);
	var obj_dv = $("."+obj_rut_class+"_dv",obj_rut.parent());
	//_error("obj_dv.val= "+obj_dv.val());
	var rut_ok = false ;
	var dv_ok = false ;

	//check de rut
	var rut = check_rut_familiar(obj_rut.val());
	if( rut != "" ){
		rut_ok = true;
		//actualizamos el input
		obj_rut.val(rut);
	}
	else{
		obj_rut.parent().addClass("error");
	}

	if( obj_dv.val() == "" ){
		obj_dv.parent().addClass("error");
	}
	else if ( checkDV(obj_rut,obj_dv) ){
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().removeClass("error");
		dv_ok = true;
	}
	else{
		//re-agregar cuando se separen los div
		//obj_rut.parent().removeClass("error");
		obj_dv.parent().addClass("error");
	}
	var ret = rut_ok & dv_ok ;
	//alert("rut: "+rut_ok+" dv: "+dv_ok);
	return ret ;
}

/*
function validador_rut_familiar(obj_rut){

	var rut_ok = false ;

	//check de rut
	//var rut = format_rut(check_rut_familiar(obj_rut.attr("value")));
	var rut = check_rut_familiar(obj_rut.attr("value"));
	if( rut != "" ){
		rut_ok = true;
		//actualizamos el input
		obj_rut.val(rut);
	}
	//alert("rut: "+obj_rut.val()+": "+rut_ok);
	_error("rut fam: "+rut_ok);
	return rut_ok ;
}
*/


//debe ser el DV correcto respecto al RUT.
//recibe los input de rut y dv como objetos DOM
//retorna true/false
function checkDV(obj_rut,obj_dv)
{
	//check_rut_familiar contiene check_rut_alumno
	//var rut = check_rut_familiar(obj_rut.val());
	var rut = check_rut_generico(obj_rut.val());
	var dv  = clean_dv(obj_dv.val());
	if( rut == "" || dv == "" ){
		return false;
	}
	//OJO_REVISAR var largo = rut.length;
	var dvr = '0';
	var suma = 0;
	var mul  = 2;
	for (i= rut.length -1 ; i >= 0; i--){
		suma = suma + rut.charAt(i) * mul;
		if(mul == 7){
			mul = 2;
		}
		else{
			mul++;
		}
	}
	res = suma % 11;
	if (res==1){
		dvr = 'k';
	}
	else{
		if(res==0){
			dvr = '0';
		}
		else{
			dvi = 11-res;
			dvr = dvi + "";
		}
	}
	if(dvr != dv.toLowerCase()){
		//alert("EL RUT o DV es incorrecto.");
		return false;
	}
	return true;
}

//para el Call Center
function calcularDV(str_rut)
{
	var rut = check_rut_generico(str_rut);
	if( rut == "" ){
		return 'X';
	}
	var dvr = '0';
	var suma = 0;
	var mul  = 2;
	for (i= rut.length -1 ; i >= 0; i--){
		suma = suma + rut.charAt(i) * mul;
		if(mul == 7){
			mul = 2;
		}
		else{
			mul++;
		}
	}
	res = suma % 11;
	if (res==1){
		dvr = 'K';
	}
	else{
		if(res==0){
			dvr = '0';
		}
		else{
			dvi = 11-res;
			dvr = dvi + "";
		}
	}
	return dvr;
}

//Soporta: 0,1,2,3,4,5,6,7,8,9,k,K.
function clean_dv(str){
	if( str == undefined ) return "";
	var dv = str.replace(/[^\d|k|K]/g, "");
	return dv ;
}

/*************************************************************************
 * Validaciones específicas
 * **********************************************************************/

//Soporte paramétrico, y en caso de celular: prefijo
//celular + número, maximo 8 dígitos, inicia con [6-9].
//recibe cualquiera de los 3 selectores de input de telefonos
function validador_telefonos(obj){

	var ret = false;

	var data = obj.metadata();

	if( ! data['campos']){
		data = $(".seleccione",obj.parent()).metadata();
	}
	/*
	if( ! data['campos'] ){
	       //alert("tampoco !!");
	}
	*/

	var obj_area = $("."+data['campos'][0]+" :input");
	var obj_fono = $("."+data['campos'][1]+" :input");
	var obj_celu = $("."+data['campos'][2]+" :input");
	/*
	_error("obj_area: "+obj_area.attr("name"));
	_error("obj_fono: "+obj_fono.attr("name"));
	_error("obj_celu: "+obj_celu.attr("name"));
	*/
/*
	var obj_area = $(".cod_area :input");
	var obj_fono = $(".telefono :input");
	var obj_celu = $(".telefono_celular :input");
*/
	//alert(obj_celu.html());
	var area = obj_area.val();
	//alert("area: "+area);
	var fono = obj_fono.val();
	var celu = obj_celu.val();

	var null_area = ((typeof area == 'undefined') || area == "" )?true:false;
	var null_fono = ((typeof fono == 'undefined') || fono == "" )?true:false;
	var null_celu = ((typeof celu == 'undefined') || celu == "" )?true:false;

	var _area = false;
	var _fono = false;
	var _celu = false;

	//primero el codigo de area
	//var filter=/^(58|57|55|52|51|53|33|32|34|35|2|72|75|71|73|42|41|43|45|63|64|65|67|61)$/;
	//no implementar hasta recibir la lista actualizada.
	//if( ! _area && filter.test(area) ){
	if( null_area ){
		$(".caja_selecciona",obj_area.parent().parent()).addClass("error");
		_area = false;
	}
	else{
		$(".caja_selecciona",obj_area.parent().parent()).removeClass("error");
		//$(".caja_selecciona",obj_area.parent().parent()).addClass("error");
		_area = true;
	}
	//_error("area: "+_area);

	//pasado esto, sabemos que hay al menos uno de los 2 campos con datos.
	if( null_fono & null_celu ){
		obj_celu.parent().addClass("error");
		obj_fono.parent().addClass("error");
		//_error("false: null_celu & null_fono ");
		return false;
	}

	//validamos el telefono si es que hay.
	//si no hay, lo marcamos bueno.
	if( null_fono ){
		obj_fono.parent().removeClass("error");
		_fono = true;
		//_error("null_fono: "+_fono);
	}
	//vemos telefono
	else{
		//hay fono pero no hay area
		if( null_area ){
			$(".caja_selecciona",obj_area.parent().parent()).addClass("error");
			obj_fono.parent().addClass("error");
			_fono = false;
		}
		else{
			_fono = validador_telefono(obj_fono,obj_area);
			obj_fono.parent().toggleClass("error", ! _fono );
			//_error("fono: "+_fono);
		}
	}

	//validamos el celular si es que hay.
	//si no hay, lo marcamos bueno.
	if( null_celu ){
		obj_celu.parent().removeClass("error");
		_celu = true;
		//_error("null_celu: "+_celu);
	}
	else{
		_celu = check_celular(celu);
		obj_celu.parent().toggleClass("error", ! _celu );
		//_error("celu: "+_celu);
	}

	//preparamos el resultado a retornar
	ret = _area & ( _fono & _celu ) ;

	//_error("ret: "+ret);
	return ret;
}

//minimo 8
//distinto fecha nacimiento
function validador_password(obj){
	var valor = obj.val();
	if(obj.disabled){
		return true;
	}
	if (valor==null || valor=='' || valor.length < 8){
		return false;
	}

	return true;
}

//esta variante es para el administrador de usuarios.
//no debe obligar el cambio de password.
function validador_password_vacio(obj){
	var valor = obj.val();
	if(obj.disabled){
		return true;
	}
	if (valor==''){
		return true;
	}
	if (valor=null || valor.length < 8){
		return false;
	}

	return true;
}

//recibe el tipo de parametro
function validador_parametrico(obj){
}

//Recibe: un conjunto de validaciones, en caso que alguna de ellas no sea
//exitosa, envía la información correspondiente a la interfaz de datos faltantes.
function validador_datos_faltantes(){
	var todo_ok = true;
	//gatillamos las validaciones
	for(var i in formulario.pestanas){
		validar(formulario.pestanas[i]);
	}	
	//hay que trimear
	//

	//borramos la tabla
	var tabla=$(".fila_tabla_datos_faltantes");
	tabla.replaceWith('');

	
	//recorremos buscando 
	var primero = true;
	$(".tabMain").each(function(){

			//saco el id: div_n
			var id = $(this).attr("id");
			//luego el n
			//id = id.substring(id.length-1,id.length);
			id = id.split('_')[1];

			//texto de la pestana, en .tabArea
			var pestana = $("#pestana_"+id).html();

			//agregamos la validación a mano de los totales familiares anuales
			//porque no son un campo de verdad.
			//solo para la pestaña correspondiente
			if( id == 3 ){
				_error("id=3");
				//agregamos a mano la validación de los totales de ingresos familiares anuales.
				//la validación se hace al actualizar...incluye 5000
				actualizar_ingresos_totales();
				var year = [parametro['anio_anterior'],parametro['anio_actual']];
				var tr_0 = $(".total_ingreso_"+year[0]+"_0").parent();
				if( tr_0.hasClass("error") ){
					agrega_dato_faltante(tr_0,pestana);
					todo_ok=false;
				}
				var tr_1 = $(".total_ingreso_"+year[1]+"_1").parent();
				if( tr_1.hasClass("error") ){
					agrega_dato_faltante(tr_1,pestana);
					todo_ok=false;
				}
			}
			//saltamos la pestaña de postular.
			//if( pestana == 'POSTULAR' ){ return true; }
			if( id == 5 ){ return true; }

			$(".error :input",this).each(function(i){
				todo_ok = false;
				agrega_dato_faltante($(this),pestana);
				//este return es para que no rompa el each
				return true;
			});
			//_error("input: "+$(this).attr("name")+" clase: "+$(this).parent().parent().hasClass("error_radio"));
			$(".error_radio :input",this).each(function(i){
				//_error("input: "+$(this).attr("name")+" clase: "+$(this).parent().parent().hasClass("error_radio"));
				todo_ok = false;
				//tratamiento especial de los radio
				//que son arreglos de input
				//_error("input: "+$(this).attr("name"));
				if( primero ){
					agrega_dato_faltante($(this),pestana);
					primero = false;
				}else{
					primero = true;
				}
				//este return es para que no rompa el each
				return true;
			});
	});

	return todo_ok;
}

function validador_tabla_familiares(){
	_error("inicio_validador_tabla_familiares");

	return true;
}

function agrega_dato_faltante(input,pestana){
	//saco el nombre del input
	var name = input.attr("name");
	var filter=/^$/;

	//ingresos[0][]
	filter=/^ingresos\[\d\]\[(.*)\]$/;
	if( filter.test(name) ){
		name = "ingresos_postulante";
	}

	//familiares[0][ingresos][0][0]
	//filter=/^familiares\[\d\]\[ingresos\]\[\d\]\[(.*)\]$/;
	filter=/^familiares\[\d\]\[ingresos\]\[\d\]\[\d\]$/;
	if( filter.test(name) ){
		name = "ingresos_familiares";
	}

	//familiares[n][nombre_familiar]
	filter=/^familiares\[\d\]\[(.*)\]$/;
	if( filter.test(name) ){
		name = "familiares_"+filter.exec(name)[1];
	}

	var id = pestana.split('.')[0];

	//busco el nombre en el formulario
	//var json = busca_json_pestana(formulario,name);
	//ahora lo saco de la metadata
	var titulo = input.metadata()['titulo'];

	var tr=$("<tr class=\"fila_tabla_datos_faltantes\" ></tr>");

	tr.html('<td>'+titulo+'</td>\n <td><span class="vinculo">'+pestana+'</span></td>\n <td>'+ayuda[name]+'</td>\n');
	//tr.click(function(){ $("#pestana_"+id).trigger('click'); });

	tr.appendTo($("#datos_faltantes"));

	$(".vinculo",tr).click(function(){ $("#pestana_"+id).trigger('click'); });

	return tr;
}

//validación para periodos con dateentry que pisa la metadata
/*
	//var data = obj.metadata();
	//var val_ini = $("#"+data['campos'][0]).val();
	//var val_ter = $("#"+data['campos'][1]).val();

	//if( obj.attr("id") != "fecha_inicio_periodo" && obj.attr("id") != "fecha_termino_periodo" ){//data['campos'].length <= 2 ){
	//if( data['campos'].length < 0 ){
		//data = $(".seleccione",obj.parent()).metadata();
	//}

        if( obj.attr("id") != "fecha_inicio_periodo" && obj.attr("id") != "fecha_termino_periodo" ){//data['campos'].length <= 2 ){
	}
	else{

		var val_ini = $("#fecha_inicio_periodo").val();
		var val_ter = $("#fecha_termino_periodo").val();

		if ( val_ini != '' & val_ter != '' ){
			val_ini = ''+val_ini.split("/")[2]+val_ini.split("/")[1]+val_ini.split("/")[0];
			val_ter = ''+val_ter.split("/")[2]+val_ter.split("/")[1]+val_ter.split("/")[0];
			if( val_ini >= val_ter ){
				return false;
			}
		}
	}
*/

/*function validador_usuario_correo(obj){

	var ret = true;
	var clase = obj.attr("class");
	var usuario = obj.val();
	//preguntamos si el otro campo tiene dato
	//var obj_dominio= $(":input[name='"+obj.attr("name")+"_dominio']");
	var obj_dominio= $(".usuario_dominio",obj.parent().parent());
	_error(obj_dominio.html());
	if( obj.val() == "" || obj_dominio.val() == "" ){
		return false;
	}
	return validador_formato_usuario_correo(obj)
}*/


/*function validador_dominio_correo(obj){

	var ret = true;
	var clase = obj.attr("class");
	var dominio = obj.val();

	//preguntamos si el otro campo tiene dato
	//var obj_usuario= $(":input[name='"+obj.attr("name")+"_usuario']");
	var obj_usuario= $(".usuario_correo",obj.parent().parent());
	_error("input: "+obj_usuario.val());
	if( obj.val() == "" && obj_usuario.val() == "" ){
		return false;
	}

	return validador_formato_dominio_correo(obj);
}*/


