	/**
	 * Clase Javascript que gestiona los envíos AJAX. Recibe como parámetros los siguientes datos
	 * - coFormulario: nombre del formulario a envia
	 * - coEvento: nombre bajo el cual viaja el evento en la petición
	 * - coVariableTipoPeticionAJAX: nombre de la variable bajo el cual se envia el indicador informando que la peticion es AJAX
	 * - urlLlamadaCNC: URL a invocar al realizar la llamada
	 * - coConsolaLlamada: Identificador del elemento del documento HTML para trazar la llamada
	 * - coConsolaRespuesta: Identificador del elemento del documento HTML para trazar la respuesta
	 * - coConsolaEstado: Identificador del elemento del documento HTML para trazar el estado de la llamada
	 * - teMarcaInicioMensaje: Texto que indica que comienza la respuesta AJAX
	 * - teMarcaFinMensaje: Texto que indica que comienza la peticion AJAX
	 * - tePaginaNueva: Texto para identificar si una página es nueva o no (para hacer scroll).
	 * - teHayExcepcion: Texto que indica si se ha producido una excepcion o no
	 * - caMilisegundosRelojEspera: Cantidad de milisegundos que permanecerá en espera el cursor en las peticiones AJAX
	 * - teMensajeSalida: Mensaje que aparecerá cuando un usuario intente abandonar la página.
	 * - liURLVuelta: Direccion de la url de vuelta
	 * - teMensajeErrorServidor: Mensaje que aparecerá cuando se produzca un error en el servidor
     * - coCampoFoco: Identificador del campo que se le asignara el foco
	 */
function MotorAJAX(coFormulario, coEvento, coVariableTipoPeticionAJAX, urlLlamadaCNC, coConsolaLlamada,
					coConsolaRespuesta, coConsolaEstado, teMarcaInicioFinMensaje, tePaginaNueva,
					teHayExcepcion, caMilisegundosRelojEspera, teMensajeSalida, liURLVuelta, teMensajeErrorServidor,
					coCampoFoco, boEsUsoBotoneraGenerica, boPreguntarAlAbandonarPagina, deClaveHaySesionActiva,
					boEsASL21, deZonaMensajes, deZonaOperacionEnCurso, deZonaOpacaOperacionEnCurso,
					deNombreClaveHayQueRefrescarZona, valorClaveToken, deNombreVariableJSONRefrescarZona)
{
	this.coFormulario = coFormulario;
	this.coEvento = coEvento;
	this.coVariableTipoPeticionAJAX = coVariableTipoPeticionAJAX;
	this.urlLlamadaCNC = urlLlamadaCNC;
	
	// Para buscar el tag que indica si es pagina nueva o no
	this.tePaginaNueva = tePaginaNueva;
	// Para buscar el tag que indica si hay errores de validacion o no
	this.teContenedorErrores = 'contenedorErrores';
		
	this.coConsolaLlamada = coConsolaLlamada;
	this.coConsolaRespuesta = coConsolaRespuesta;
	this.coConsolaEstado = coConsolaEstado;
	
	this.liURLVuelta = liURLVuelta;
	this.teMensajeErrorServidor = teMensajeErrorServidor;
	this.teMensajeSesionActiva = deClaveHaySesionActiva;
	
	// Este evento es un evento del CN. 
	this.coEvento_chequearSesionActiva = "chequearSesionActiva";
	
	this.boEsASL21 = boEsASL21;
	
	this.deZonaMensajes = deZonaMensajes;
	this.deZonaOperacionEnCurso = deZonaOperacionEnCurso;
	this.deZonaOpacaOperacionEnCurso = deZonaOpacaOperacionEnCurso;
	this.deNombreClaveHayQueRefrescarZona = deNombreClaveHayQueRefrescarZona;
	this.valorClaveToken = valorClaveToken;
	this.deNombreVariableJSONRefrescarZona = deNombreVariableJSONRefrescarZona;
	
	
	//Constantes
	this.metodoEnvioFormulario = 'POST';
	this.respuestaRecibida = 4;
	this.separadorParametros = '&';
	this.separadorClaveValor = '=';
	// JMP: Constantes para gestionar respuestas HTML ademas de JSON
	this.teInicioFormulario = '<form id="' + this.coFormulario + '"';
	this.teFinFormulario = '</form> <!--' + this.coFormulario + '-->';
	this.teCierreEtiqueta = '>';
	this.inTipoRespuestaJSON = 1;
	this.inTipoRespuestaHTML = 0;
	
	this.teIniVariable = 'var ';
	this.teFinVariable = ' =';
	this.teMarcaIniValor = '\'';
	this.teMarcaFinValor = ';';
	
	this.teMarcaInicioMensaje = '<' + teMarcaInicioFinMensaje + '>';
	this.teMarcaFinMensaje = '</' + teMarcaInicioFinMensaje + '>';
	
	this.teInicioTitulo = '<title>';
	this.teFinTitulo = '</title>';
	
	// Cantidad de milisegundos ue permanecerá el reloj de arena durante las esperas a peticiones AJAX.
	this.caMilisegundosRelojEspera = caMilisegundosRelojEspera;
	
	// Para identificar el temporizador que establece el cursor de espera.
	this.idTimer;
	
	// Array con todos los elementos de tipo input y select de la pagina
	// Servirá para cuando se esté esperando la respuesta a una peticion y situemos
	// el cursor sobre un boton, el cursor sea un reloj de arena (cursor wait).
	this.ltInputsPagina = document.getElementsByTagName("input");
	this.ltSelectsPagina = document.getElementsByTagName("select");
	
	// Al cargar la pagina ponemos el tipo de cursor por defecto
	document.body.style.cursor = "default";

    var nombreCampoFoco = coCampoFoco;
    var elementoFoco = document.getElementById(nombreCampoFoco);
    if (elementoFoco != null)
        elementoFoco.focus();
		
	
	var formulario = document.getElementById(this.coFormulario);
    
	
	/**
	* Valida si hay que preguntar antes de abandonar la pagina. Si estamos en la primera 
	* pagina, preguntaremos solo si se ha modificado algun campo del formulario. Si no estamos
	* en la primera pagina, siempre preguntaremos antes de abandonar.
	*/
	function validarOnbeforeunload ()
	{
		// Si hay que preguntar al abandonar pagina (la pagina no es la primera del proceso),
		// retornamos el mensaje que se mostrara al abandonar.
		if (boPreguntarAlAbandonarPagina)
			return teMensajeSalida;
		
		// Si la pagina es primera de proceso, preguntamos antes de abandonar solo si ha habido cambios.
		
		// Validamos que no haya habido cambios en los campos de entrada
		// (text, file, password, radio y checkbox).
		var ltInputsFormulario = formulario.getElementsByTagName('input');
		for (i = 0; i < ltInputsFormulario.length; i++)
		{
			if ( (ltInputsFormulario[i].type == "text") ||
				 (ltInputsFormulario[i].type == "file") ||
				 (ltInputsFormulario[i].type == "password") )
			{
				if (ltInputsFormulario[i].value != ltInputsFormulario[i].defaultValue)
					return teMensajeSalida;
			}
			
			if ( (ltInputsFormulario[i].type == "radio") ||
				 (ltInputsFormulario[i].type == "checkbox") )
			{
				if ( ltInputsFormulario[i].checked != ltInputsFormulario[i].defaultChecked)
					return teMensajeSalida;
			}
		}
			
		// Validamos que no haya habido cambios en los campos de tipo select
		var ltSelectsFormulario = formulario.getElementsByTagName('select');
		for (i = 0; i < ltSelectsFormulario.length; i++)
		{
			var ltOpcionesSelect=ltSelectsFormulario[i].getElementsByTagName("option");
			
			var valSelect = false;
			/* Si no hay ningun valor seleccionado por defecto no validamos ese select */
			for (k=0; k<ltOpcionesSelect.length; k++)
			{
				if (ltOpcionesSelect[k].defaultSelected)
				{
					valSelect = true;
					break;
				}
			}
			
			if ( (valSelect) && (!ltOpcionesSelect[ltSelectsFormulario[i].selectedIndex].defaultSelected) )
				return teMensajeSalida;
		}
		
		// Validamos que no haya habido cambios en los campos de tipo textarea
		var ltAreasFormulario = formulario.getElementsByTagName('textarea');
		for (i = 0; i < ltAreasFormulario.length; i++)
		{
			if ( ltAreasFormulario[i].value != ltAreasFormulario[i].defaultValue)
					return teMensajeSalida;
		}
		
		return;
	}

	// Si está activado el motor Ajax, antes de abandonar la pagina avisamos al usuario de
	// que perderá los datos que haya rellenado, para que decida si realmente quiere 
	// abandonar o no.
	// Al recuperar el foco la pantalla, se programa en evento onbeforeunload. Esto se hace para
	// que cuando se abra una nueva ventana, al volver a nuestra pantalla y queremos abandonarla,
	// que nos pregunte si realmente queremos abandonar (y avise de que perderemos los datos).
	// OJO!!! SI HAY ERROR NO GENERAMOS EVENTO (para que el usuario abandone sin más).
	if (teHayExcepcion == "N")
	{
		if (!boEsUsoBotoneraGenerica) {
			// En Integración ASL1-ASL2 no se activa onbeforeunload. Ya lo hace ASL1.
			window.onbeforeunload = function(e)
			{ 
	    		//return teMensajeSalida;
				return validarOnbeforeunload ();
			};
			
			window.onfocus = function (e)
			{
	            if (elementoFoco != null)
	                elementoFoco.focus();
	            
				window.onbeforeunload = function(e)
				{ 
	    			//return teMensajeSalida;
	    			return validarOnbeforeunload ();
				};
				
			};
		}
		
	}
	else
	{
		// En caso contrario (hay error o no activado ajax) anulamos el evento
		// onbeforeunload para que no pregunte al abandonar pagina.
		if (document.all)
			window.document.body.onbeforeunload=null;
		else
			window.onbeforeunload=null;
	}
	
	// Al cargar la pagina ponemos el tipo de cursor de los botones por defecto
	for(var i=0; i<this.ltInputsPagina.length; i++)
		this.ltInputsPagina[i].style.cursor="default";
	for(var i=0; i<this.ltSelectsPagina.length; i++)
		this.ltSelectsPagina[i].style.cursor="default";
		
	/**
	 * Creamos las variables dependientes al cargar la pagina
	 * Creamos un atributo en la pagina con el valor actual de cada campo dependiente.
	 * Esto es necesario para saber si un atrubto ha cambiado su valor, lanzando en este caso
	 * el evento correspondiente (en caso contrario no se haria nada).
	 * Por cada bloque con el formato teVarJS_x creamos una variable a nivel de documento.
	 * Antes se buscaban todos los elementos con name teVarJS, pero da problemas de 
	 * accesibilidad (no usar name en etiquetas script), así que buscamos bloques con el id
	 * con el formato teVarJS_x. Buscamos teVarJS_1, teVarJS_2.. asi hasta que no encontremos
	 * el elemento, y por cada elemento encontrado lo metemos en una lista.
	 */
	//this.ltVarJS = document.getElementsByName('teVarJS');
	this.ltVarJS = new Array();
	
	var contador = 0;
	var scriptTeVarJS;
	while (true)
	{
		contador ++;
		scriptTeVarJS = document.getElementById('teVarJS_' + contador);
		
		if ( scriptTeVarJS == null )
			break;
		
		this.ltVarJS[contador - 1] = scriptTeVarJS;
	}
	// FIN busqueda elementos teVarJS_x
	
	
	this.nombreVarJS = '';
	this.valorVarJS = '';
	this.nodoJS = document.getElementById(this.coFormulario);
	this.nuPosIniJS = 0;
	this.nuPosFinJS = 0;
	this.atributoJS;
	
	for (k=0; k<this.ltVarJS.length; k++)
	{
		this.nuPosIniJS = this.ltVarJS[k].text.indexOf(this.teIniVariable);
		this.nuPosFinJS = this.ltVarJS[k].text.indexOf(this.teFinVariable);
				
		if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
		{
			this.nombreVarJS = this.ltVarJS[k].text.substring(this.nuPosIniJS + this.teIniVariable.length, this.nuPosFinJS);
			
			this.nuPosIniJS = this.ltVarJS[k].text.indexOf(this.teMarcaIniValor);
			this.nuPosFinJS = this.ltVarJS[k].text.indexOf(this.teMarcaFinValor);
			if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
			{
				this.valorVarJS = this.ltVarJS[k].text.substring(this.nuPosIniJS+1, this.nuPosFinJS-1);
						
				this.atributoJS = document.createAttribute(this.nombreVarJS);
				this.atributoJS.nodeValue = this.valorVarJS;
				this.nodoJS.setAttributeNode(this.atributoJS);	
			}
			else
				throw "Error al obtener valor de la variable JS";
		}
		else
			throw "Error al obtener nombre de la variable JS";
				
	}
	
	/**
	 * Método que realiza el envio de una petición mediante AJAX de manera sincrona
	 */ 
	this.enviar = function (coEvento)
	{	
		this.enviarSincronoAsincrono(coEvento, true);
	}
	
	/**
	 * Método que realiza el envio de una petición mediante AJAX, tomando los parámetros del formulario y 
	 * realizando la invocacion. La vuelta de la llamada se realiza al método this.procesarRespuesta.
	 * El envío se realiza de manera sincrona o asincrona segun un parametro.
	 */ 
	this.enviarSincronoAsincrono = function (coEvento, boEnvioSincrono)
	{
		this.ponerCursorEspera ();
		
		// Pasados 10 segundos, si no se ha recibido la respuesta a una peticion (caida servidor,...),
		// se pone el tipo de cursor por defecto, para que el usuario tenga la sensación de que puede
		// volver a realizar peticiones y haga lo que crea oportuno.
		// Este codigo hace lo mismo que si llamasemos a la funcion ponerCursorDefecto, pero lo
		// hacemos así porque si no da error en algunos navegadores.
		this.idTimer = setTimeout("document.body.style.cursor = \"default\";"+
				" ltInputPag = document.getElementsByTagName(\"input\");"+
				" ltSelectPag = document.getElementsByTagName(\"select\");"+
				" for(var i=0; i<ltInputPag.length; i++)"+
				" ltInputPag[i].style.cursor=\"default\";"+
				" for(var i=0; i<ltSelectPag.length; i++)"+
				" ltSelectPag[i].style.cursor=\"default\";", this.caMilisegundosRelojEspera);
		
		if (boEnvioSincrono)
		{	
			peticion = this.crearPeticion();
			peticion.open(this.metodoEnvioFormulario, this.urlLlamadaCNC, false);
			peticion.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
			var parametros = this.crearCadenaParametros(coEvento,'',''); 
			this.trazarLlamada(parametros);
			
			try
			{
				peticion.send(parametros);
			}
			catch (error)
			{
				gestorErrores = new GestorErrores (this.coFormulario, this.teMensajeErrorServidor, this.liURLVuelta);
				gestorErrores.lanzarError();
			}
			
			if (peticion.readyState == this.respuestaRecibida)
			{
				this.procesarRespuesta(peticion.responseText);
			}
			else
			{
				gestorErrores = new GestorErrores (this.coFormulario, this.teMensajeErrorServidor, this.liURLVuelta);
				gestorErrores.lanzarError();
			}
		}
		else
		{
			var instancia = this;
			
			peticion = this.crearPeticion();
			peticion.open(this.metodoEnvioFormulario, this.urlLlamadaCNC, true);
			peticion.onreadystatechange = function()
			{
				if (peticion.readyState == instancia.respuestaRecibida)
					instancia.procesarRespuesta(peticion.responseText);
			}
			peticion.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
			var parametros = this.crearCadenaParametros(coEvento,'',''); 
			this.trazarLlamada(parametros);
			peticion.send(parametros);
		}
		
	}
	
	
	
	/**
	 * Método que realiza el envio de una petición mediante AJAX, tomando los parámetros del formulario y 
	 * realizando la invocacion. La vuelta de la llamada se realiza al método this.procesarRespuesta.
	 * El envío se realiza de manera sincrona o asincrona segun un parametro.
	 */ 
	this.enviarEnlace = function (coEvento, coClave, coValor)
	{
		this.ponerCursorEspera ();
		
		// Pasados 10 segundos, si no se ha recibido la respuesta a una peticion (caida servidor,...),
		// se pone el tipo de cursor por defecto, para que el usuario tenga la sensación de que puede
		// volver a realizar peticiones y haga lo que crea oportuno.
		// Este codigo hace lo mismo que si llamasemos a la funcion ponerCursorDefecto, pero lo
		// hacemos así porque si no da error en algunos navegadores.
		this.idTimer = setTimeout("document.body.style.cursor = \"default\";"+
				" ltInputPag = document.getElementsByTagName(\"input\");"+
				" ltSelectPag = document.getElementsByTagName(\"select\");"+
				" for(var i=0; i<ltInputPag.length; i++)"+
				" ltInputPag[i].style.cursor=\"default\";"+
				" for(var i=0; i<ltSelectPag.length; i++)"+
				" ltSelectPag[i].style.cursor=\"default\";", this.caMilisegundosRelojEspera);
		
			
		peticion = this.crearPeticion();
		peticion.open(this.metodoEnvioFormulario, this.urlLlamadaCNC, false);
		peticion.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
		var parametros = this.crearCadenaParametros(coEvento, coClave, coValor); 
		this.trazarLlamada(parametros);
		
		try
		{
			peticion.send(parametros);
		}
		catch (error)
		{
			gestorErrores = new GestorErrores (this.coFormulario, this.teMensajeErrorServidor, this.liURLVuelta);
			gestorErrores.lanzarError();
		}
		
		if (peticion.readyState == this.respuestaRecibida)
		{
			this.procesarRespuesta(peticion.responseText);
		}
		else
		{
			gestorErrores = new GestorErrores (this.coFormulario, this.teMensajeErrorServidor, this.liURLVuelta);
			gestorErrores.lanzarError();
		}
		
	}
	
	
	/**
	 * Método que realiza el envio de una petición de manera sincrona para verificar si hay sesión  
	 * activa o no. En caso de producirse cualquier error, consideramos la sesión cmo NO activa.
	 * @return true si hay sesión activa.
	 * @return false en caso contrario.
	 */
	this.boHaySesionActiva =  function () 
	{
		peticion = this.crearPeticion();
		peticion.open(this.metodoEnvioFormulario, this.urlLlamadaCNC, false);
		peticion.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
		var parametros = this.crearCadenaParametros(this.coEvento_chequearSesionActiva,'','');
		peticion.send(parametros);
		if (peticion.status!=200)
			return false;
		else
		{
			if (peticion.responseText==this.teMensajeSesionActiva)
				return true;
			else
				return false;
		}
	}	
	
	/**
	 * Método que crea una cadena con la concatenacion de los campos de un formulario, tomando todos 
	 * los elementos del formulario que tengan informado el atributo 'name'. Para los checkbox y radios solo se añade
	 * el valor seleccionado. Por último se añade un parámetro que indica que la petición es mediante AJAX
	 */
	this.crearCadenaParametros = function(coEvento, coClave, coValor)
	{
		var formulario = document.getElementById(this.coFormulario);
		var cadenaParametros = '';
		for (i = 0; i < formulario.elements.length; i++)
		{
			if (formulario.elements[i].name != '')
			{
				elementoHTML = formulario.elements[i];
				// JRO Obtener el valor del editor de textos ricos
				if (elementoHTML.type=="textarea" && elementoHTML.getAttribute("class")!=null &&
						elementoHTML.getAttribute("class").indexOf("editorTextoRico")>=0) 
				{
					teTextoEditor = "";
					deNombreTextArea = elementoHTML.id;
					if (CKEDITOR!=null) 
						teTextoEditor =	eval("CKEDITOR.instances[\""+deNombreTextArea+"\"].getData()");

					if (i > 0)
						cadenaParametros = cadenaParametros + this.separadorParametros;
					
					cadenaParametros = cadenaParametros  + encodeURIComponent(formulario.elements[i].name) + this.separadorClaveValor + encodeURIComponent(teTextoEditor);
				} 
				else
				{
					// JMP
					if ( ( (formulario.elements[i].type == "checkbox") || (formulario.elements[i].type == "radio") ) &&
					     ( !formulario.elements[i].checked ) )
						continue;
				
					if (i > 0)
						cadenaParametros = cadenaParametros + this.separadorParametros;
						
					cadenaParametros = cadenaParametros  + encodeURIComponent(formulario.elements[i].name) + this.separadorClaveValor + encodeURIComponent(formulario.elements[i].value);
				}
			}
		}
		
		if (i > 0)
			cadenaParametros = cadenaParametros + this.separadorParametros;
			
		cadenaParametros  = cadenaParametros + this.coEvento + this.separadorClaveValor + encodeURIComponent(coEvento);
		cadenaParametros = cadenaParametros + this.separadorParametros + this.coVariableTipoPeticionAJAX + this.separadorClaveValor + 'true';
		
		if (coClave != '')
			cadenaParametros = cadenaParametros + this.separadorParametros + coClave + this.separadorClaveValor + encodeURIComponent(coValor);
			
		return cadenaParametros;
	}

	/**
	 * Método que obtiene la respueta, llamando la metodo 'this.obtenerRespuesta(teRespuesta);'. En caso se ser
	 * la respuesta de tipo JSON, se instancia el controlador indicado y se le pasan los datos para que se procesen
	 * en caso de ser HTML, se sobre escribe el contenido del elemento 'form' por el contenido del elemento 'form' 
	 * recibido, reejecutando los posibles Javascript recibidos
	 */
	this.procesarRespuesta = function(teRespuesta)
	{
		try 
		{
		
			if ((teRespuesta == null) || (teRespuesta.replace(/ /g, '') == ''))
			{
				this.trazarEstado('La respuesta recibida en una cadena vacía o blancos');
				throw "La respuesta recibida en una cadena vacía o blancos";
			}
		
			// Solamente se está chequeando que hay sesión activa
			if (teRespuesta==this.teMensajeSesionActiva) {
				this.ponerCursorDefecto();
				return;
			}
			//Obtenemos la respuesta
			var teRespuestaSinMarcas = new Array(2);
			teRespuestaSinMarcas = this.obtenerRespuesta(teRespuesta);
			
			//Comentamos esta linea para evitar problemas al tener una copia de la pagina y por tanto campos html
			//con id's repetidos (falla por ejemplo el poner el foco al campo a traves del 'for' del label en IE
			//this.trazarRespuesta(teRespuestaSinMarcas[1]);
			
			if (teRespuestaSinMarcas[0] == this.inTipoRespuestaJSON)
			{
				boHayMensajes = false;
				this.ponerCursorDefecto ();
    				
				clearTimeout(this.idTimer);
				
				// Incidencia 880854: Se produce un error por "SyntaxError: unterminated string literal"
				// cuando en la cadena a evaluar hay un salto de linea, por lo que es necesario devaluar
				// este caracter (charCode = 10) antes de hacer el eval. Este error se produce cuando se
				// pulsa intro en un textarea y se monta una respuesta JSON con el valor del textarea.
				// OJO: al pulsar intro en IE se convierte en dos caracteres 10 (salto de linea) y 
				// 13 (retorno de carro), por lo que este último también se tiene en cuenta.
				var auxi = "";
				for (i=0;i<teRespuestaSinMarcas[1].length;i++)
				{
					if (teRespuestaSinMarcas[1].charCodeAt(i) == 10)
						auxi += '\\\\n';
					else if (teRespuestaSinMarcas[1].charCodeAt(i) == 13)
						auxi += '\\\\r';
					else
						auxi += teRespuestaSinMarcas[1].charAt(i);
				}
				teRespuestaSinMarcas[1] = auxi;
				
				var respuesta = eval('(' + teRespuestaSinMarcas[1] + ')');
				var indiceContador = 0;
				while (indiceContador < respuesta.tareas.length)
				{
					if (respuesta.tareas[indiceContador].tipoElemento == 'ControladorMensajesValidacion')
						boHayMensajes = true;
					
					var instanciacion = 'controlador = new ' +  respuesta.tareas[indiceContador].tipoElemento + '();';
					eval(instanciacion);
					//this.coFormulario se añade unicamente para el caso del controladorSelect,
					//para actualizar la  la variable con el valor actual seleccionado del formulario (existe si hay algun campo dependiente) del elemento select.
					//En el resto de casos no es utilizado.
					controlador.ejecutar(respuesta.tareas[indiceContador].datosElemento, this.coFormulario);
					indiceContador++;
				}
				
				
				// En este punto se ha procesado una respuesta JSON correctamente. Esto significa que se han pasado las
				// validaciones necesarias en la pagina, por lo que ocultamos la zona de mensajes de validacion si la hubiera.
				// Esta accion solo se realiza cuando estamos en la nueva version de la arquitectura (ASL21).
				if ( (this.boEsASL21) && (!boHayMensajes) ) 
				{
					zonaMensajes = new Zona();
					zonaMensajes.ocultar(this.deZonaMensajes, false);
				}
				
				// Ocultamos la zona de operación en curso cuando recibamos la respuetsa
				if (this.boEsASL21) 
				{
					zonaOperacion = new Zona();
					zonaOperacion.ocultar(this.deZonaOperacionEnCurso, false);
					
					//Ocultamos la zona opaca que se muestra cuando hay operacion en curso.
					zonaOperacion.ocultarOperacionEnCursoModal(this.deZonaOpacaOperacionEnCurso);
				}
				
				
			}
			else if (teRespuestaSinMarcas[0] == this.inTipoRespuestaHTML)
			{
				
				// Verificamos si hay que refrescar una zona o el formulario entero. Si encontramos la marca
				// deNombreClaveHayQueRefrescarZona, actualizamos zona. En caso contrario actualizamos formulario.
				
				deCadenaTratar = teRespuestaSinMarcas[1];
				
				posClave = deCadenaTratar.indexOf("id=\"" + deNombreClaveHayQueRefrescarZona);
				
				if (posClave >= 0) /* Actualizamos una zona, pues hemos encontrado la marca deNombreClaveHayQueRefrescarZona */
				{
					 
					//-------------------------------------------//
					//-------------------------------------------//
					//           Actualización de zona			 //
					//-------------------------------------------//
					//-------------------------------------------//
					
					// La marca de refresco de zona es de la forma: <input type="hidden" id="campoBoHayQueRefrescarZona" value="xxxxx" />
					// Obtenemos el nombre de la zona a refrecar -value del hidden-
					posIniZona = posClave + 'id="'.length + deNombreClaveHayQueRefrescarZona.length + '" value="'.length;
					deZonaRefrescar = deCadenaTratar.substring (posIniZona);
					
					posFinZona = deZonaRefrescar.indexOf("\"");
					
					deZonaRefrescar = deZonaRefrescar.substring(0,posFinZona).replace(/ /g, "");
					
					liZonasRefrescar = deZonaRefrescar.split(",");
					
					deCadenaTratarAux = deCadenaTratar;
					
					for (nZona = 0; nZona<liZonasRefrescar.length; nZona ++)
					{
						deCadenaTratar = deCadenaTratarAux;
					
						deZonaRefrescar = liZonasRefrescar[nZona];
						
						// Hemos obtenido la zona a actualizar. Comprobamos que la zona existe.
						zonaActualizar = document.getElementById(deZonaRefrescar);
						
						if (zonaActualizar != null)
						{
							// Obtenemos el codigo html de la zona que hay que actualizar. 
							posIniZona = deCadenaTratar.indexOf("id=\"" + deZonaRefrescar);
							
							// Nos situamos en el inicio de la zona a actualizar
							deCadenaTratar = deCadenaTratar.substring(posIniZona - '<div '.length);
							
							// Buscamos el cierre de la zona a actualizar, teniendo en cuenta que puede haber zonas incluidas en ella.
							zonasAbiertas = 0;
							for (i=0;i<deCadenaTratar.length; i++)
							{
								if 	(	((deCadenaTratar.length - i) > 4) &&
										( (deCadenaTratar.charAt(i) == '<') &&
										((deCadenaTratar.charAt(i+1) == 'd') || (deCadenaTratar.charAt(i+1) == 'D')) &&
										((deCadenaTratar.charAt(i+2) == 'i') || (deCadenaTratar.charAt(i+2) == 'I')) &&
										((deCadenaTratar.charAt(i+3) == 'v') || (deCadenaTratar.charAt(i+3) == 'V')) )		)
								{
										zonasAbiertas++;
								}
								else if (	((deCadenaTratar.length - i) > 6) &&
											( (deCadenaTratar.charAt(i) == '<') &&
											(deCadenaTratar.charAt(i+1) == '/') &&
											((deCadenaTratar.charAt(i+2) == 'd') || (deCadenaTratar.charAt(i+2) == 'D')) &&
											((deCadenaTratar.charAt(i+3) == 'i') || (deCadenaTratar.charAt(i+3) == 'I')) &&
											((deCadenaTratar.charAt(i+4) == 'v') || (deCadenaTratar.charAt(i+4) == 'V')) &&
											(deCadenaTratar.charAt(i+5) == '>')  )		)
								{
									zonasAbiertas--;
									
									if (zonasAbiertas == 0)
									{
										deCadenaTratar = deCadenaTratar.substring(deCadenaTratar.indexOf(">")+1,i);
										break;
									}
								}
							}
							
							// Actualizamos el html de la zona con el recibido en la respuesta.
							deCodigoZona = deCadenaTratar;
							zonaActualizar.innerHTML = deCodigoZona;
							
							// Ejecutamos el JS de la zona actualizada. Para ello, buscamos en el codigo de la zona
							// los bloques teJS_, y por cada uno ejecutamso su JS asociado.
							while (deCadenaTratar.indexOf ('teJS_') >= 0)
							{
								posIni = deCadenaTratar.indexOf("id=\"teJS_");
								deCadenaTratar = deCadenaTratar.substring(posIni + "id=\"teJS_".length);
								
								posIni = deCadenaTratar.indexOf(">");
								posFin = deCadenaTratar.indexOf("</script>");
								
								cadenaEjecutar = deCadenaTratar.substring(posIni+1, posFin);
								eval(cadenaEjecutar);
							}
							
							// Por cada teVarJS_x contenido en la zona, creamos una variable a nivel de documento.
							// Esto se hace para saber el valor actual de las variables de los campos que tienen
							// boEventoSiCambiaValor, para lanzar el evento solo si se cambia el valor.
							deCadenaTratar = deCodigoZona;
							while (deCadenaTratar.indexOf ('teVarJS_') >= 0)
							{
								posIni = deCadenaTratar.indexOf("id=\"teVarJS_");
								deCadenaTratar = deCadenaTratar.substring(posIni + "id=\"teVarJS_".length);
								posIni = deCadenaTratar.indexOf(">");
								posFin = deCadenaTratar.indexOf("</script>");
								teVariable = deCadenaTratar.substring(posIni, posFin);
								
								this.nuPosIniJS = teVariable.indexOf(this.teIniVariable);
								this.nuPosFinJS = teVariable.indexOf(this.teFinVariable);
										
								if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
								{
									this.nombreVarJS = teVariable.substring(this.nuPosIniJS + this.teIniVariable.length, this.nuPosFinJS);
									
									this.nuPosIniJS = teVariable.indexOf(this.teMarcaIniValor);
									this.nuPosFinJS = teVariable.indexOf(this.teMarcaFinValor);
									if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
									{
										this.valorVarJS = teVariable.substring(this.nuPosIniJS+1, this.nuPosFinJS-1);
												
										this.atributoJS = document.createAttribute(this.nombreVarJS);
										this.atributoJS.nodeValue = this.valorVarJS;
										this.nodoJS.setAttributeNode(this.atributoJS);	
									}
									else
										throw "ActualizarZona: Error al obtener valor de la variable JS";
								}
								else
									throw "ActualizarZona: Error al obtener nombre de la variable JS";		
							}
						}
						else
						{
							throw "ActualizarZona: No se puede actualizar una zona inexistente";
						}
					
					}//Fin de for de lista de zonas ha actualizar
					
					
					/* Puesto que se ha hecho una petición al servidor, hay que actualizar el token */
					deCadenaTratar = teRespuestaSinMarcas[1];
					posToken = deCadenaTratar.indexOf("id=\"" + this.valorClaveToken);
					if (posToken >= 0)
					{
						/* <input type="hidden" id="campoBoHayQueRefrescarZona" value="xxxxx" /> */
						posIniToken = posToken + 'id="'.length + this.valorClaveToken.length + '" value="'.length;
						cadenaAux = deCadenaTratar.substring (posIniToken);
						posFinToken = cadenaAux.indexOf("\"");
						
						vaToken = cadenaAux.substring(0,posFinToken).replace(/ /g, "");
						
						var elemToken = document.getElementById(this.valorClaveToken);
						
						if (elemToken != null)
						{
							var evalToken = 'elemToken.value = \'' + vaToken + '\'';
							eval(evalToken);						
						}
					}
					
					// Junto al refresco de zona se pueden ejecutar eventos JSON. Estos eventos se almacenan en una variable JS
					// cuyo nombre se especifica en deNombreVariableJSONRefrescarZona. Hay que obtener el texto JSON y ejecutarlo.
					deCadenaTratar = teRespuestaSinMarcas[1];
					nuPosicionInicio = deCadenaTratar.indexOf(this.teMarcaInicioMensaje);
					nuPosicionFin = deCadenaTratar.indexOf(this.teMarcaFinMensaje);
					
					if ( (nuPosicionInicio > -1) && (nuPosicionFin > -1) )
					{
						deCadenaTratar = deCadenaTratar.substring(nuPosicionInicio + this.teMarcaInicioMensaje.length, nuPosicionFin);
						
						// Incidencia 880854: Se produce un error por "SyntaxError: unterminated string literal"
						// cuando en la cadena a evaluar hay un salto de linea, por lo que es necesario devaluar
						// este caracter (charCode = 10) antes de hacer el eval. Este error se produce cuando se
						// pulsa intro en un textarea y se monta una respuesta JSON con el valor del textarea.
						// OJO: al pulsar intro en IE se convierte en dos caracteres 10 (salto de linea) y 
						// 13 (retorno de carro), por lo que este último también se tiene en cuenta.
						var auxi = "";
						for (i=0;i<deCadenaTratar.length;i++)
						{
							if (deCadenaTratar.charCodeAt(i) == 10)
								auxi += '\\\\n';
							else if (deCadenaTratar.charCodeAt(i) == 13)
								auxi += '\\\\r';
							else
								auxi += deCadenaTratar.charAt(i);
						}
						deCadenaTratar = auxi;
						
						var respuesta = eval('(' + deCadenaTratar + ')');
						var indiceContador = 0;
						while (indiceContador < respuesta.tareas.length)
						{
							var instanciacion = 'controlador = new ' +  respuesta.tareas[indiceContador].tipoElemento + '();';
							eval(instanciacion);
							controlador.ejecutar(respuesta.tareas[indiceContador].datosElemento, this.coFormulario);
							indiceContador++;
						}
					}
					
					this.ponerCursorDefecto ();
					
					// Ocultamos la zona de operación en curso cuando recibamos la respuetsa
					if (this.boEsASL21) 
					{
						zonaOperacion = new Zona();
						zonaOperacion.ocultar(this.deZonaOperacionEnCurso, false);
						
						//Ocultamos la zona opaca que se muestra cuando hay operacion en curso.
						zonaOperacion.ocultarOperacionEnCursoModal(this.deZonaOpacaOperacionEnCurso);
					}
					
					return;
				} // Fin de actualizacion de zona
				
				//-------------------------------------------//
				//-------------------------------------------//
				//        Actualización de formulario		 //
				//-------------------------------------------//
				//-------------------------------------------//
				
				// Tratar respuesta HTML
				var formulario = document.forms[this.coFormulario];
				formulario.innerHTML = teRespuestaSinMarcas[1];
				
				if (teRespuestaSinMarcas[2]!=null && teRespuestaSinMarcas[2]!='')
					formulario.encoding = teRespuestaSinMarcas[2];

				// Ejecutamos todo el JS cuyo name sea teJS. Esto se hace porque
				// al actualizar el innerHTML no se ejecuta el js contenido.
				//var scriptJS = document.getElementsByName('teJS');
				//for (i=0; i<scriptJS.length; i++)
				//{
					//eval(scriptJS[i].text);
				//}
				/**
				 * Por cada bloque con el formato teJS_x ejecutamos el contenido de dicho bloque.
				 * Antes se buscaban todos los elementos con name teJS, pero da problemas de 
				 * accesibilidad (no usar name en etiquetas script), así que buscamos bloques con el id
				 * con el formato teJS_x. Buscamos teJS_1, teJS_2.. asi hasta que no encontremos
				 * el elemento, y por cada elemento encontrado ejecutamos si texto.
				 */
				
				
				var scriptJS;
				var contador = 0;
				
				/* Ejecutamos el JS que viene en la respuesta. */
				deCadenaTratar = teRespuestaSinMarcas[1];
				while (deCadenaTratar.indexOf ('teJS_') >= 0)
				{
					posIni = deCadenaTratar.indexOf("id=\"teJS_");
					deCadenaTratar = deCadenaTratar.substring(posIni + "id=\"teJS_".length);
					
					posIni = deCadenaTratar.indexOf(">");
					posFin = deCadenaTratar.indexOf("</script>");
					
					cadenaEjecutar = deCadenaTratar.substring(posIni+1, posFin);
					eval(cadenaEjecutar);
				}
				
				
				// Buscamos tambien si hay teJS y si existen los ejecutamos (esto lo hacemos
				// por si hay paginas fuera de la arquitectura que necesitan ejecutar JS).
				scriptJS = document.getElementById('teJS');
				if ( scriptJS != null )
					eval(scriptJS.text);

				// SMS: Bloques con id teJSA_x asociados a analytics
				// Buscamos tambien si hay teJSA_x y si existen los ejecutamos.
				contador = 0;
				while (true)
				{
					contador ++;
					scriptJS = document.getElementById('teJSA_' + contador);
					if ( scriptJS == null )
						break;
					
					eval(scriptJS.text);
				}
				
				// JMP: Bloques con id teJSG_x asociados a Google analytics
				// Buscamos si hay teJSG_x y si existen los ejecutamos.
				contador = 0;
				while (true)
				{
					contador ++;
					scriptJS = document.getElementById('teJSG_' + contador);
					if ( scriptJS == null )
						break;
					
					eval(scriptJS.text);
				}

				// Buscamos tambien si hay teJS_exp y si existen los ejecutamos. La marca teJS_exp la
				// ponemos en la JSP de error por expiracion de sesion.
				scriptJS = document.getElementById('teJS_exp');
				if ( scriptJS != null )
					eval(scriptJS.text);

				// FIN ejecución bloques teJS_x
				
				// JMP: Bloques con id teJSM_x asociados a Google Maps
				// Buscamos si hay teJSM_x y si existen los ejecutamos.
				contador = 0;
				while (true)
				{
					contador ++;
					scriptJS = document.getElementById('teJSM_' + contador);
					if ( scriptJS == null )
						break;
					
					eval(scriptJS.text);
				}

				////////////////////////
				// Actualizamos la lista de variables teVarJS_x
				contador = 0;
				this.ltVarJS = new Array();
                while (true)
                {
                    contador ++;
                    scriptTeVarJS = document.getElementById('teVarJS_' + contador);

                    if ( scriptTeVarJS == null )
                        break;

                    this.ltVarJS[contador - 1] = scriptTeVarJS;
                }
                // Por cada teVarJS_x creamos una variable a nivel de documento.
				for (k=0; k<this.ltVarJS.length; k++)
				{
					this.nuPosIniJS = this.ltVarJS[k].text.indexOf(this.teIniVariable);
					this.nuPosFinJS = this.ltVarJS[k].text.indexOf(this.teFinVariable);
							
					if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
					{
						this.nombreVarJS = this.ltVarJS[k].text.substring(this.nuPosIniJS + this.teIniVariable.length, this.nuPosFinJS);
						
						this.nuPosIniJS = this.ltVarJS[k].text.indexOf(this.teMarcaIniValor);
						this.nuPosFinJS = this.ltVarJS[k].text.indexOf(this.teMarcaFinValor);
						if ( (this.nuPosIniJS > -1) && (this.nuPosFinJS > -1) )
						{
							this.valorVarJS = this.ltVarJS[k].text.substring(this.nuPosIniJS+1, this.nuPosFinJS-1);
									
							this.atributoJS = document.createAttribute(this.nombreVarJS);
							this.atributoJS.nodeValue = this.valorVarJS;
							this.nodoJS.setAttributeNode(this.atributoJS);	
						}
						else
							throw "Error al obtener valor de la variable JS";
					}
					else
						throw "Error al obtener nombre de la variable JS";
							
				}
				////////////////////////
				
				// Ocultamos la zona de operación en curso cuando recibamos la respuetsa
				if (this.boEsASL21) 
				{
					zonaOperacion = new Zona();
					zonaOperacion.ocultar(this.deZonaOperacionEnCurso, false);
					
					//Ocultamos la zona opaca que se muestra cuando hay operacion en curso.
					zonaOperacion.ocultarOperacionEnCursoModal(this.deZonaOpacaOperacionEnCurso);
				}
				
				// Sólo se va al principio de pagina cuando la pagina sea nueva o haya errores de validacion y no sea ASL21.
				if ( 	(this.esPaginaNueva(teRespuestaSinMarcas[1])) || 
						( (this.hayErroresValidacion(teRespuestaSinMarcas[1])) && (!boEsASL21) )
					)
				{	
					// posicionamos cursor
					window.scrollTo(0, 0);
				}
				
				this.ponerCursorDefecto ();
				
			}
			else if ( (teRespuesta.indexOf(this.teInicioTitulo) > -1) && (teRespuesta.indexOf(this.teFinTitulo) > -1) )
			{
				// Si se reconoce que lo que viene es una pagina HTML, la pintamos tal y como viene.
				// Este es el caso de expiracion de sesion en entornos integrados con AJAX, que la
				// Pasarela redirige a la home, por lo que aqui llega una pagina html.
				
				// Ponemos a la pagina el titulo que viene en la respuesta.
				var titulo=teRespuesta.substring(teRespuesta.indexOf(this.teInicioTitulo) + this.teInicioTitulo.length,
												teRespuesta.indexOf(this.teFinTitulo));
				document.title = titulo;
				
				// Pintamos la pagina recibida por respuesta.
				document.body.innerHTML = teRespuesta;
				
				// Anulamos el evento onbeforeunload para que no pregunte al abandonar pagina.
				if (document.all)
					window.document.body.onbeforeunload=null;
				else
					window.onbeforeunload=null;
				
				this.ponerCursorDefecto ();
			}
			else
				throw teRespuestaSinMarcas[1];
				
			this.trazarEstado('Respuesta Procesada correctamente.');
			
		} 
		catch (error) 
		{
			this.trazarRespuesta(teRespuesta);
			this.trazarEstado('Error al procesar respuesta: "' + this.obtenerDescripcionError(error) + '"');
			
			gestorErrores = new GestorErrores (this.coFormulario, this.teMensajeErrorServidor, this.liURLVuelta);
			gestorErrores.lanzarError();
			
			this.ponerCursorDefecto ();
			
		}	
	} 
	
	/**
	 * Método que devuelve una array donde indica el tipo de respuesta detectada y el texto de la misma.
	 * Para la posicion cero del array si vale this.inTipoRespuestaJSON indica que la respuesta es JSON, si vale 
	 * this.inTipoRespuestaHTML, indica que la respuesta es HTML y si vale -1 que ha habido un error al 
	 * procesar la respuesta.
	 */
	this.obtenerRespuesta = function (teRespuesta)
	{
		var respuesta = new Array(3);
		// respuesta segun codificacion de formulario
		respuesta[2] = '';
		var nuPosicionInicio = teRespuesta.indexOf(this.teInicioFormulario);
		var nuPosicionFin = -1;
		
		if (nuPosicionInicio > -1) // Respuesta HTML
		{
			nuPosicionFin = teRespuesta.indexOf(this.teFinFormulario);
			
			if ( (nuPosicionInicio > -1) && (nuPosicionFin > -1) )
			{
				teRespuesta = teRespuesta.substring(nuPosicionInicio, nuPosicionFin);
				nuPosicionInicioCierre = teRespuesta.indexOf(this.teCierreEtiqueta);
				if (nuPosicionInicioCierre > -1)
				{
					if (teRespuesta.substring(nuPosicionInicio,nuPosicionInicioCierre).indexOf('multipart')>0)
						respuesta[2] = 'multipart/form-data';
					respuesta[0] = this.inTipoRespuestaHTML;
					respuesta[1] = teRespuesta.substring(nuPosicionInicioCierre + this.teCierreEtiqueta.length);
					
				}
				else
				{
					respuesta[0] = -1;
					respuesta[1] = 'Error en sintaxis de formulario';
				}
			}
			else
			{
				respuesta[0] = -1;
				respuesta[1] = 'Tipo de respuesta Incorrecta';
			}
		}
		else // Respuesta JSON
		{
			nuPosicionInicio = teRespuesta.indexOf(this.teMarcaInicioMensaje);
			nuPosicionFin = teRespuesta.indexOf(this.teMarcaFinMensaje);
			
			if ( (nuPosicionInicio > -1) && (nuPosicionFin > -1) )
			{
				respuesta[0] = this.inTipoRespuestaJSON;
				respuesta[1] = teRespuesta.substring(nuPosicionInicio + this.teMarcaInicioMensaje.length, nuPosicionFin);
			}
			else
			{
				respuesta[0] = -1;
				respuesta[1] = 'No se encuentran las marcas mensaje JSON';
			}
		}
		return respuesta;
	}

	/**
	 * Método que crea un objeto XMLHTTPRequest
	 */
	this.crearPeticion = function()
	{
		var peticionAJAX;
		try 
		{ 
			// no es IE
			if(window.XMLHttpRequest) 
				peticionAJAX = new XMLHttpRequest();
			else
				peticionAJAX = new ActiveXObject("Microsoft.XMLHTTP");
		} 
		catch (error) 
		{
			this.trazarLlamada('Error al instanciar objeto XMLHTTP' + this.obtenerDescripcionError(error));
		}	
		return peticionAJAX;
	}
	
	/**
	 * Método que busca la descriptcion del error, debido a la distinta modelizacion de esta informacion en FF e IE
	 */
	this.obtenerDescripcionError = function(error)
	{
		if ((typeof error) == "string")
			return error;
		else
		{
			if (typeof error.description != 'undefined')
				return error.description;
			else
				return error;
		}
	}
	
	/**
	 * Metodo que indica si una pagina es nueva o no
	 */
	this.esPaginaNueva = function (teRespuesta)
	{
		var teCadenaBusqueda = '<input name="' + this.tePaginaNueva + '" value="true"';
		return teRespuesta.indexOf(teCadenaBusqueda) > 0;
	}
	
	/**
	 * Metodo que indica si una pagina tiene o no errores de validacion
	 */
	this.hayErroresValidacion = function (teRespuesta)
	{
		var teCadenaBusqueda = '<div id="' + this.teContenedorErrores + '"></div>';
		return teRespuesta.indexOf(teCadenaBusqueda) <= 0;
	}
	
	/**
	 * Metodo que pone el tipo de cursor por defecto tanto en la pagina como en sus botones
	 */
	this.ponerCursorDefecto = function ()
	{
		document.body.style.cursor = "default";
		
		for(var i=0; i<this.ltInputsPagina.length; i++)
	    	this.ltInputsPagina[i].style.cursor="default";
	    for(var i=0; i<this.ltSelectsPagina.length; i++)
	    	this.ltSelectsPagina[i].style.cursor="default";
	}
	
	/**
	 * Metodo que pone el tipo de cursor de espera (reloj arena) tanto en la pagina como en sus botones
	 */
	this.ponerCursorEspera = function ()
	{
		document.body.style.cursor = "wait";
		
		for(var i=0; i<this.ltInputsPagina.length; i++)
	    	this.ltInputsPagina[i].style.cursor="wait";
   	    for(var i=0; i<this.ltSelectsPagina.length; i++)
	    	this.ltSelectsPagina[i].style.cursor="wait";
	}
	
	/**
	 * Método que traza en la consola de llamada
	 */
	this.trazarLlamada = function(teLlamada)
	{
		var consolaEntrada = document.getElementById(this.coConsolaLlamada);
		this.trazar(teLlamada, consolaEntrada);
	}
	
	/**
	 * Método que traza en la consola de respuesta
	 */
	this.trazarRespuesta = function(teRespuesta)
	{
		var consolaRespuesta = document.getElementById(this.coConsolaRespuesta);
		this.trazar(teRespuesta, consolaRespuesta);
	}
	
	/**
	 * Método que traza en la consola de estado
	 */
	this.trazarEstado = function(teEstado)
	{
		var consolaEstado = document.getElementById(this.coConsolaEstado);
		this.trazar(teEstado, consolaEstado);
	}
	
	/**
	 * Método que traza sobre el elemento HTML recibido, sobreescribiendo la propiedad 'innerHTML'
	 */
	this.trazar = function(texto, elementoDelDocumento)
	{
		if (elementoDelDocumento != null)
			elementoDelDocumento.innerHTML = texto; 
	}
}
