[SOLUCIONADO]Error JS: RangeError: Maximum call stack size exceeded

Buen dia, estoy teniendo un problema en un proyecto desarrollado con Toba 2.3.0 y Postgres 8.4, dentro de un formulario tengo un ef_combo, que es cargado por un método en el dao, de tal forma que de acuerdo al item que selecciona muestra u oculta ciertos ef_editables del formulario. El campo que determina lo que oculto y lo que no esta en la tabla por lo que hago una llamada desde javascript a un metodo en el ci, el cual se comunica a traves del dao con la base de datos, devuelvo este resultado a javascript y en base a este oculto o no los campos. El problema es que quiero borrar el contenido de los ef que voy a ocultar, he probado utilizar los métodos resetar_estado(), set_estado(’ ‘) y set_estado(’') obteniendo siempre el mensaje de error “Error JS: RangeError: Maximum call stack size exceeded” en el navegador Chromium y el error “Error JS: InternalError: too much recursion” en el navegador Firefox 14. He revisado varias veces el código y es similar a otros proyectos hechos en las versiones 2.1 y 2.2 no presentando problemas.

//Este es el código que utilizo en el procesar del combo (JS)


//---- Procesamiento de EFs --------------------------------
		
		{$this->objeto_js}.evt__id_tipoempresa__procesar = function(es_inicial)
		{
			var id_tipoempresa = this.ef('id_tipoempresa').get_estado();
			if (id_tipoempresa != 'nopar') {
				this.controlador.ajax('get_datos_tipoempresa', id_tipoempresa, this, this.actualizar_datos_tipoempresa);
			}
		}

//Este es el código es el que utilizo en el ci (PHP)


//-----------------------------------------------------------------------------------
	//---- Funciones AJAX----------------------------------------------------------------
	//-----------------------------------------------------------------------------------
	
	function ajax__get_datos_tipoempresa($id_tipoempresa, toba_ajax_respuesta $respuesta)
	{
		$contenido = ' id_tipoempresa = ' . $id_tipoempresa;
		$datos = dao_padron_general::get_gen_tiposempresa($contenido);
		if (isset($datos[0]['es_personafisica'])) {
			if (($datos[0]['es_personafisica']) == 'true') {
				$resultado = 'SI';
			} else {
				$resultado = 'NO';
			} 
		}
		$respuesta->set($resultado); 
	}

//Este es el código que utilizo para procesar el resultado y mostrar o no los campos (JS)


//---- Pregunto si es empresa o no y oculto o no los campos--------------------
		
		{$this->objeto_js}.actualizar_datos_tipoempresa = function(tipoempresa)
		{
			if (tipoempresa == 'SI'){
				this.ef('razonsocial_empresa').resetear_estado();
				this.ef('razonsocial_empresa').ocultar();
				this.ef('fechainicio_empresa').ocultar();
				this.ef('idtipo_documento').mostrar();
				this.ef('dni_persona').mostrar();
				this.ef('apellido_persona').mostrar();
				this.ef('nombres_persona').mostrar();
				this.ef('fecha_nacimiento').mostrar();
				this.ef('sexo_persona').mostrar();
				
				this.controlador.dep('frm_ml_parentescos').mostrar();
			} else {
				this.ef('idtipo_documento').ocultar();
				this.ef('dni_persona').ocultar();
				this.ef('apellido_persona').ocultar();
				this.ef('nombres_persona').ocultar();
				this.ef('fecha_nacimiento').ocultar();
				this.ef('sexo_persona').ocultar();
				this.controlador.dep('frm_ml_parentescos').ocultar();
				this.ef('razonsocial_empresa').mostrar();
				this.ef('fechainicio_empresa').mostrar();
			}  
		}     

Adjunto debajo las capturas de los mensajes de error arrojados por los navegadores.
Desde ya muchas gracias por su ayuda. Saludos


Captura de pantalla de 2012-07-31 08:06:27.png

Captura de pantalla de 2012-07-31 08:06:27.png

Captura de pantalla de 2012-07-31 08:08:06.png

Captura de pantalla de 2012-07-31 08:08:06.png

Hola Facundo,

Los metodos para ocultar y mostrar, poseen un parametro que indica si se debe resetear el valor o no.
http://desarrollotoba.siu.edu.ar/toba_editor_trunk/doc/api_js/ef.html#ocultar

obteniendo siempre el mensaje de error "Error JS: RangeError: Maximum call stack size exceeded" en el navegador Chromium y el error "Error JS: InternalError: too much recursion" en el navegador Firefox 14. He revisado varias veces el código y es similar a otros proyectos hechos en las versiones 2.1 y 2.2 no presentando problemas.

En el JS que me pegaste, el unico punto que me puede parecer conflictivo es la condicion que determina si se hace o no la llamada ajax, el metodo procesar se dispara cuando el ef pierde el foco o se cambia su estado, tenelo en cuenta para que no te este generando problemas.

A priori, no hay ningun indicio claro de recursion… salvo que haya otras funciones que esten tocando algun ef y hagan que se entre en un ciclo de procesamiento infinito.
Lo que te pediria es que me pegues todo el JS que lleva esa operacion, que incluya la parte del Ci, etc.

Si el browser te esta dando ese error es porque en algun lado se esta disparando un ciclo recursivo.

Saludos

Buen día Richard, gracias por la respuesta, de acuerdo a lo comentado por usted le hago llegar el código solicitado.

//Este es el código javascript que utilizo para extender el formulario en cuestión

<?php
class ei_frm_padron extends sim_ei_formulario
{
	function extender_objeto_js()
	{
		echo "
			{$this->objeto_js}.ini = function () {
			this.ef('apellido_persona').input().onchange = function() {
				var ef = {$this->objeto_js}.ef('apellido_persona');
				ef.set_estado(ef.get_estado().toUpperCase());
				}
				
			this.ef('nombres_persona').input().onchange = function() {
				var ef = {$this->objeto_js}.ef('nombres_persona');
				ef.set_estado(ef.get_estado().toUpperCase());
				}
			
			this.ef('razonsocial_empresa').input().onchange = function() {
				var ef = {$this->objeto_js}.ef('razonsocial_empresa');
				ef.set_estado(ef.get_estado().toUpperCase());
				}
				
			this.ef('observaciones_contribuyente').input().onchange = function() {
				var ef = {$this->objeto_js}.ef('observaciones_contribuyente');
				ef.set_estado(ef.get_estado().toUpperCase());
				}
			}
		
		
		//---- Procesamiento de EFs --------------------------------
		
		{$this->objeto_js}.evt__id_tipoempresa__procesar = function(es_inicial)
		{
			//if (!es_inicial) {
				var id_tipoempresa = this.ef('id_tipoempresa').get_estado();
				if (id_tipoempresa!= null) {
					this.controlador.ajax('get_datos_tipoempresa', id_tipoempresa, this, this.actualizar_datos_tipoempresa);
				}
			//}
		}
		
		
		//---- Pregunto si es empresa o no y oculto o no los campos--------------------
		
		{$this->objeto_js}.actualizar_datos_tipoempresa = function(tipoempresa)
		{
			if (tipoempresa == 'SI'){
				this.ef('razonsocial_empresa').resetear_estado();
				this.ef('razonsocial_empresa').ocultar();
				this.ef('fechainicio_empresa').ocultar();
				this.ef('idtipo_documento').mostrar();
				this.ef('dni_persona').mostrar();
				this.ef('apellido_persona').mostrar();
				this.ef('nombres_persona').mostrar();
				this.ef('fecha_nacimiento').mostrar();
			} else {
				this.ef('idtipo_documento').ocultar();
				this.ef('dni_persona').ocultar();
				this.ef('apellido_persona').ocultar();
				this.ef('nombres_persona').ocultar();
				this.ef('fecha_nacimiento').ocultar();
				this.ef('razonsocial_empresa').mostrar();
				this.ef('fechainicio_empresa').mostrar();
			}  
		}     
		
		//---- Procesamiento de EFs --------------------------------
		
		{$this->objeto_js}.evt__cuip_contribuyente__procesar = function(es_inicial)
		{
			if (!es_inicial) {
				var cuip_contribuyente = this.ef('cuip_contribuyente').get_estado();
				if (cuip_contribuyente!= null) {
					this.controlador.ajax('get_datos_escuip', cuip_contribuyente, this, this.actualizar_datos_cuip_contribuyente);
				}
			}
		}
		
		//---- Pregunto si es valido el CUIP--------------------
		
		{$this->objeto_js}.actualizar_datos_cuip_contribuyente = function(cuip)
		{
			if (!cuip) {
				alert('El n\u00famero de C.U.I.P. ingresado no es v\u00e1lido, por favor verifiquelo y vuelva a intentarlo');
				this.ef('cuip_contribuyente').set_estado('');
			}  
		}    
	
		";
	}
}
?>

//Este es el código en php de la función que utilizo para saber que tipo de entidad es, esta en el CI

function ajax__get_datos_tipoempresa($id_tipoempresa, toba_ajax_respuesta $respuesta)
	{
		$contenido = ' id_tipoempresa = ' . $id_tipoempresa;
		$datos = dao_padron_general::get_gen_tiposempresa($contenido);
		if (isset($datos[0]['es_personafisica'])) {
			if (($datos[0]['es_personafisica']) == 'true') {
				$resultado = 'SI';
			} else {
				$resultado = 'NO';
			} 
		}
		$respuesta->set($resultado); 
	}

//Este es el código en php de la función que utilizo para controlar que el CUIP sea válido, también está en el CI

function ajax__get_datos_escuip($cuip, toba_ajax_respuesta $respuesta_cuip)
	{
		$esCuit = false;
		$cuit_rearmado = '';
		 //Separo cualquier caracter que no tenga que ver con numeros
		 $longitud = strlen($cuip);
		for ($i = 0; $i < $longitud; $i++) {   
			if ((ord(substr($cuip, $i, 1)) >= 48) && (ord(substr($cuip, $i, 1)) <= 57)) {
				$cuit_rearmado = $cuit_rearmado . substr($cuip, $i, 1);
			}
		}
		$cuip = $cuit_rearmado;
		if ( strlen($cuit_rearmado) <> 11) {  //Si to estan todos los digitos
			$esCuit = false;
		} else {
			$x = 0;
			$i = 0;
			$dv = 0;
			//Multiplico los digitos
			$vec[0] = (substr($cuip, 0, 1)) * 5;
			$vec[1] = (substr($cuip, 1, 1)) * 4;
			$vec[2] = (substr($cuip, 2, 1)) * 3;
			$vec[3] = (substr($cuip, 3, 1)) * 2;
			$vec[4] = (substr($cuip, 4, 1)) * 7;
			$vec[5] = (substr($cuip, 5, 1)) * 6;
			$vec[6] = (substr($cuip, 6, 1)) * 5;
			$vec[7] = (substr($cuip, 7, 1)) * 4;
			$vec[8] = (substr($cuip, 8, 1)) * 3;
			$vec[9] = (substr($cuip, 9, 1)) * 2;
						
			//Suma cada uno de los resultado
			for ( $i = 0;$i <= 9; $i++) {
				$x += $vec[$i];
			}
			$dv = (11 - ($x % 11)) % 11;
			if ($dv == (substr($cuip, 10, 1)) ) { 
				$esCuit = true;
			} 
		}
		$respuesta_cuip->set($esCuit); 
	}	

Quedo a la espera de sus observaciones. Saludos.

Hola Facundo,

el problema es el siguiente, vos redefiniste el onchange del ef… el tema es que dentro de dicha funcion haces uso del metodo set_estado, el cual vuelve a disparar el onchange del ef, por lo que estas generando un ciclo infinito de onchange recursivos en el momento que le cambias el estado por primera vez al ef, ya sea que lo reseteas o lo cambias manualmente con la respuesta ajax.

Tendrias que ponerle un caso base a dicho mecanismo, o sino ir directamente y cambiar el valor del input() por el DOM, en lugar de pasar por la API.
La mezcla genero un caso inflamable :smiley:

Saludos

Buenas tardes Richard, muchas gracias por la respuesta, mezclé mal los ingredientes entonces, ahora lo corrijo.
Saludos