
//--------------------------------------------------------------------------------------------
// Copyright © 2002 Master Lex 
//
// Autor:	 Christian Sandoval Moya 
// Fecha:	 Abril 2002          
// Objetivo: Presenta una serie de funciones comunes en dtbar.asp  y contenido.asp
//			 para el manejo del arbol del contenido del sitio web.	Se juntan en este
//			 archivo para reutilización y consistencia de código. 
//--------------------------------------------------------------------------------------------


var PROYECTO = '';

var m_strNoTextos = "Textos no disponibles...";	//Frase para cuando no se pueda mostrar una parte de la BD
var m_strCargando = "Cargando...";	//Frase que se le muestra al usuario cuando se está cargando un xml
var m_strNoDisponible = "No disponible..."; 

var strTexto = "<DIV class='clsItem'><img src='images/1pix.gif' type='img'></img><SPAN class='clsSpace' state='NoCargado' type='indicador'><SPAN class='clsCollapse' >+</SPAN></SPAN><SPAN class='clsLabel' type='label' ";
var strTexto_Hoja = "<DIV class='clsItem'><SPAN class='clsSpace' state='NoCargado' type='indicador'><SPAN class='clsLeaf' type='hoja'>.</SPAN></SPAN><SPAN class='clsLabel' type='label' ";  
var strCierre = "</SPAN><DIV class='hide' type='container'></DIV></DIV>"

var m_RutaItemActual = new Array();
var m_TituloRutaItemActual = new Array();
var m_PropiedadRutaItemActual = new Array();
var m_ValorRutaItemActual = new Array();
var m_AlcanceRutaItemActual = new Array();
var m_BDActual;
var m_ItemActual;
var m_TipoRutaItemActual = new Array();
var m_HrefRutaItemActual = new Array();

var m_TopeValorProp = new Array();

//***************************************************************************************************
//Function:	MoverArriba
//Objetivo:	Se desplaza un item hacia abajo en el árbol. Solamente tiene en cuenta los items que 
//			son visibles para el usuario; es decir, aunque una parte del árbol se haya cargado, 
//			si está oculta, no se tomará en cuenta para desplazarse hacia abajo.
//			Esta función se ejecuta cuando el usuario utiliza la tecla UP y la flecha 'UP' del
//			dtbar.asp.  Se debe tener en cuenta que si el item actual es una sección se moviliza
//			hacia arriba, ya que las secciones no se deben desplegar.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function MoverArriba()
{
	var objSpan;
	var objIndicador;	
	var objDivOculto;
	var objNuevo;
	var objHermanos;
	var nI;

	//En caso de que no exista el objeto actual se sale
	if( null == top.fraIzquierdo.fraBarra.m_objActual ) 
		return;

	//Se obtiene quien es el item anterior a él
	objNuevo = ObtenerHermanoAnt(top.fraIzquierdo.fraBarra.m_objActual.parentElement);

	if(objNuevo == null)
	{
		//Significa que es el hermano mayor

		//Se verifica que el objeto 'abuelo' del mismo no sea la raiz
		if(top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.id == "divRaiz")
			return false;
		
		var objPadre = top.fraIzquierdo.fraBarra.m_objActual.parentElement;		
		objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");
		CargarAnteriorPagina(objSpan);
		return;
		
		//se obtiene el elemento superior en la lista
		//Recuerde Actual: siempre es un span
		//Padre: siempre es un div de clase clsItem que contiene el actual y sus hijos
		//Padre del padre: siempre es un div de type container que tiene los hermanos del actual
		objNuevo = top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.parentElement;
		
		if(objNuevo == null)
			return false;
			
		//Cambio resultado de nuevos requerimientos. Como ahora se ocultan todos los hermanos
		//hay que hacer visible los hermanos del padre para poder seguir navegando.
		
		objHermanos = ObtenerHermanos(objNuevo);
		
		for(nI = 0; nI< objHermanos.length; nI++)
		{
			if(objHermanos[nI].className == "clsItemOculto")
			{
				objHermanos[nI].className = "clsItem";
			}
		}
			
		//Nuevo requerimiento: Cuando el usuario navege por una rama diferente a la que tenía anteriormente
		//se debe 'cerrar' la anterior. Para ello se toman los hermanos anterior del item actual y se comprime.
		
		//Se busca dentro del 'abuelo' el item que indica el + o el -
		objIndicador = ObtenerElementoHtml(objNuevo, "SPAN","indicador")
		objDivOculto = ObtenerElementoHtml(objNuevo, "DIV","container");
		
		//Se obtiene exactamente el hermano mayor a el span actual, pero
		//puede ser que este span tenga los hijos desplegados 
		objSpan = ObtenerElementoHtml(objNuevo, "SPAN","label")

		ComprimirRama(objDivOculto, objIndicador);
		//Nótese que no se pregunta por si está desplegado o no, el árbol hijo
		//ya que en estos casos ya se debió haber recorrido dicha rama

		SeleccionarItem(objSpan,true,false);
		return;

		alert(objNuevo.innerHTML);
		objNuevo = ObtenerHermanoAnt(objNuevo); 
		
		if(objNuevo == null)
			return;
			
		//Se obtiene el div contenedor

		objDivContenedor = ObtenerElementoHtml(objNuevo,"DIV","container");
		objIndicador = ObtenerElementoHtml(objNuevo,"SPAN","indicador");
		
		if(objDivContenedor == null || objIndicador == null)
			return;
			
		if(objIndicador.state == 'Oculto')
		{
			//Si el indicador esta oculto, hay que mostrarlo y seleccionar el ultimo hijo
				
			//Se obtiene el primer hijo
			objNuevo = ObtenerUltimoHijo(objDivContenedor);
				
			//Se debe indicar que el div es visible
			objIndicador.state == 'Visible';
			//Se indica que esta parte de la rama se expandio
			objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>"
			//Se debe hacer visible el div
			objDivContenedor.className = 'shown';
				
			//Ahora se obtiene el span del título
			objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
		}
		else if(objIndicador.state == 'Visible') 
		{
			//Si está visible los hijos del elemento actual, solamente se selecciona el ultimo hijo
				
			if(objDivContenedor != null)
			{
				//El hijo contiene el span del +/-, el span del título (que debe ser el actual) y un div Contenedor
				objNuevo = ObtenerUltimoHijo(objDivContenedor);
										
				if(objNuevo != null)
				{	
					//Ahora se debe buscar el span del título
					objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
				}
			}
		}
		else if(objIndicador.state == 'NoCargado')
		{
			//Hay que cargar el XML, visualizar los hijos y seleccionar el primer hijo
				
			//Cambio resultado de nuevos requerimientos. Ahora cuando se carga un archivo xml
			//indica que una rama del arbol se va a mostrar, pero las otras hay que ocultarlas

			objHermanos = ObtenerHermanos(objNuevo);
			for(nI = 0; nI< objHermanos.length; nI++)
			{
				if(objHermanos[nI].className == "clsItem" && objHermanos[nI] != objNuevo)
				{
					objHermanos[nI].className = "clsItemOculto";
								
				}
			}
				
			//Ahora se debe buscar el span del título
			objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");

			//Expande el nodo (lo hace visible)
			if(ExpandirNodo(objDivContenedor, objIndicador) == false)
				return false;
				
			//Carga el archivo XML 
			CargarXML(objSpan,objIndicador,objDivContenedor);
			
			objNuevo = ObtenerUltimoHijo(objDivContenedor);
				
			//Ahora se obtiene el span del título
			objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
		}
		
		
		///////////////////////////////
	}
	else
	{

		//Se busca dentro del 'abuelo' el item que indica el + o el -
		objIndicador = ObtenerElementoHtml(objNuevo, "SPAN","indicador")
		
		//Se obtiene exactamente el hermano mayor a el span actual, pero
		//puede ser que este span tenga los hijos desplegados 
		objSpan = ObtenerElementoHtml(objNuevo, "SPAN","label")
	
		//Se pregunta por si el hermano mayor tiene sus hijos visibles, para recorrerlos
		if(objIndicador != null && objIndicador.state == "Visible")
		{
			var objContenedor = ObtenerElementoHtml(objNuevo,"DIV","container");

			//Indica que el hermano mayor a el actual tiene sus hijos visibles
			var objUltimoHijo = ObtenerUltimoHijo(objContenedor);
			
			if(objUltimoHijo != null)
			{
				//Se obtiene exactamente el hermano mayor a el span actual, pero
				//puede ser que este span tenga los hijos desplegados 
				objSpan = ObtenerElementoHtml(objUltimoHijo, "SPAN","label")
			}
		}
	}	
	//Se cambia el objeto actual
	SeleccionarItem(objSpan,true,false);
//	while(top.fraIzquierdo.fraBarra.m_objActual.TipoItem == "S")
	{
		//Si se trata de una sección se debe ubicar en la primera página que tenga esta
		//Es decir, no se debe mostrar una sección
//		MoverArriba();
	}
}

//***************************************************************************************************
//Function:	MoverAbajo
//Objetivo:	Se desplaza un item hacia abajo. Si no está visible el elemento NO lo hace visible,
//			simplemente se desplaza un item hacia abajo de lo que el usuario está viendo.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function MoverAbajo()
{
	var objSpan;
	var objIndicador;	
	var objNuevo;
	var objContenedor;

	//En caso de que no exista el objeto actual se sale
	if( null == top.fraIzquierdo.fraBarra.m_objActual ) 
		return;
	
	//Se trata de determinar si el elemento actual tiene otros elementos ('hijos')
	objContenedor = ObtenerElementoHtml(top.fraIzquierdo.fraBarra.m_objActual.parentElement,"DIV","container");

	if(objContenedor != null)
	{
		//Se trata de determinar si los hijos son visibles 
		objIndicador = ObtenerElementoHtml(top.fraIzquierdo.fraBarra.m_objActual.parentElement,"SPAN","indicador");
	
		if(objIndicador != null && objIndicador.state == "Visible")
		{
			var objTemp = ObtenerElementoHtml(objContenedor,"DIV");
			
			//Se obtiene exactamente el hermano mayor a el span actual, pero
			//puede ser que este span tenga los hijos desplegados 
			objSpan = ObtenerElementoHtml(objTemp, "SPAN","label");
		}
		else
		{
			//Se trata de un item que aunque tenga hijos no han sido cargados o no son visibles
			objNuevo = ObtenerHermanoSig(objIndicador.parentElement)
			
			if(objNuevo == null)
			{
				//Se trata del ultimo hijo
				
				//se obtiene el elemento superior en la lista
				//Recuerde Actual: siempre es un span
				//Padre: siempre es un div de clase clsItem que contiene el actual y sus hijos
				//Padre del padre: siempre es un div de type container que tiene los hermanos del actual
				//Padre del abuelo: div que contiene los hermanos del padre
				objNuevo = top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.parentElement.parentElement;
				
				//Se trata del ultimo item en el arbol
				if(objNuevo.type ==  null)
					return false;
				
				objTemp = ObtenerHermanoSig(top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.parentElement)
				
				//Se obtiene exactamente el hermano mayor a el span actual, pero
				//puede ser que este span tenga los hijos desplegados 
				objSpan = ObtenerElementoHtml(objTemp, "SPAN","label");
				
			}
			else
			{
				//Se obtiene exactamente el hermano mayor a el span actual, pero
				//puede ser que este span tenga los hijos desplegados 
				objSpan = ObtenerElementoHtml(objNuevo, "SPAN","label");
			}
		}
		if(objSpan != null)
		{
			//Se actualiza el objeto actual
			SeleccionarItem(objSpan,true,false);
		}
	}
	
}

var objDivContenedorMP;

function CargarSiguientePagina(objSpan)
{
	top.fraOculto2.location.href = "ApoyoDHTML.asp?Funcion=CargarSiguientePagina&BD="+objSpan.BD+"&Item="+objSpan.Item+"&NivelArbol="+objSpan.nivelArbol;
} // function CargarSiguientePagina(objSpan)

function CargarAnteriorPagina(objSpan)
{
	top.fraOculto2.location.href = "ApoyoDHTML.asp?Funcion=CargarAnteriorPagina&BD="+objSpan.BD+"&Item="+objSpan.Item+"&NivelArbol="+objSpan.nivelArbol;
} // function CargarAnteriorPagina(objSpan)


//***************************************************************************************************
//Function:	MoverProximo
//Objetivo:	Se desplaza un item hacia abajo en el árbol. En caso de que el siguiente item no sea
//			visible al usuario se expande la rama. Desciende hasta las hojas si el usuario lo quiere;
//			si tiene que cargar un archivo xml lo hace. Esta función se ejecuta cuando el usuario
//			teclea '>' o [TAB]. A diferencia de MoverDerecha (la cual NO se desplaza entre 'hojas')
//			esta función continua descendiendo incluso moviendose por los hermanos de las 'hojas'
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function MoverProximo()
{
	var objNuevo;
	var objPadre;
	var objHijo;
	var objIndicador;
	var objDivContenedor;
	var objSpan;
	var objHermanos;
	var nI = 0;


	//En caso de que no exista un elemento actual se sale 
	if( null == top.fraIzquierdo.fraBarra.m_objActual )
		return false;
	//Se obtiene el div de clase clsItem padre del span actual
	objPadre = top.fraIzquierdo.fraBarra.m_objActual.parentElement;
	
	//Si el padre no existe o no es de clase clsItem se sale
	if(objPadre != null && objPadre.className == 'clsItem')
	{
		//Se obtiene el span indicador, 'hermano' del span actual
		objIndicador = ObtenerElementoHtml(objPadre,"SPAN","indicador");
		
		if(objIndicador != null)
		{	
			//Primeramente se revisa si el elemento actual es una hoja
			objHijo = ObtenerElementoHtml(objIndicador,"SPAN","hoja")
			if(objHijo != null && objHijo.className == 'clsLeaf')
			{
				//Se debe obtener el siguiente hermano
				objNuevo = ObtenerHermanoSig(objPadre);
				
				if(objNuevo != null)
				{
					//Si existe un hermano siguiente, entonces se busca el span de tipo 'label'
					objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
					//Posteriormente se selecciona dicho item
					SeleccionarItem(objSpan,true,false);
				}
				else
				{
					//En caso de que el elemento actual no tiene hermanos siguientes
					//Se obtiene el 'abuelo' del span actual para seguir con el hermano del padre

					try	
					{
						objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");
						CargarSiguientePagina(objSpan);
						return;
						
						objPadre = top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.parentElement;
						objNuevo = null;

						while(objNuevo == null && objPadre != null)
						{
							objNuevo = ObtenerHermanoSig(objPadre);
							if(objNuevo == null)
								objPadre = objPadre.parentElement.parentElement;
						} // while(objNuevo == null)
					
					}
					catch(e)
					{
						//alert(top.fraIzquierdo.fraBarra.m_objActual.parentElement.parentElement.outerHtml);
						return false;	
					}
					
					
					if(objNuevo != null)
					{
						//Cambio resultado de nuevos requerimientos. Como ahora se ocultan todos los hermanos
						//hay que hacer visible los hermanos del padre para poder seguir navegando.
	
						objHermanos = ObtenerHermanos(objPadre);
						for(nI = 0; nI< objHermanos.length; nI++)
						{
							if(objHermanos[nI].className == "clsItemOculto")
							{
								objHermanos[nI].className = "clsItem";
								
							}
						}
	
						//Nuevo requerimiento: Cuando el usuario navege por una rama diferente a la que tenía anteriormente
						//se debe 'cerrar' la anterior. Para ello se toman los hermano anterior del item actual y se comprime.
					
						//Hay que ocultar su hermano anterior. Solamente el anterior puesto venimos 
						//descendiendo en el árbol. No debería invocarse esta función de otra forma.
						var objHermanoAnt;
						var objIndicadorTemp;
						var objDivTemp;
						//Se obtiene el hermano anterior, el cual hay que ocultarlo
						objHermanoAnt = ObtenerHermanoAnt(objNuevo);
						
						//Solicitamos el div indicador y el div oculto de ese hermano
						objIndicadorTemp = ObtenerElementoHtml(objHermanoAnt,"SPAN","indicador");
						objDivTemp = ObtenerElementoHtml(objHermanoAnt,"DIV","container");
						//se comprime la rama desplegada
						if(objDivTemp != null && objIndicadorTemp != null)
							ComprimirRama(objDivTemp, objIndicadorTemp);
					} // if(objNuevo != null)
					
					if(objNuevo != null)
					{	
						//Se obtiene el span de tipo label
						objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
						//Se cambia de objeto actual 
						SeleccionarItem(objSpan,true,false);
					}				
				}
				//while(top.fraIzquierdo.fraBarra.m_objActual.TipoItem == "S")
				//{
					//Si se trata de una sección se debe ubicar en la primera página que tenga esta
					//Es decir, no se debe mostrar una sección
					//MoverDerecha();
				//}
				//Se sale de la función ya que no tiene que cargar archivo xml
				return false; 
			}
		
			//Se obtiene el div contenedor
			objDivContenedor = ObtenerElementoHtml(objPadre,"DIV","container");
			
			if(objIndicador.state == 'Oculto')
			{
				//Si el indicador esta oculto, hay que mostrarlo y seleccionar el primer hijo
				//Se obtiene el primer hijo
				objNuevo = ObtenerPrimerHijo(objDivContenedor);
				//Se debe indicar que el div es visible
				objIndicador.state == 'Visible';
				//Se indica que esta parte de la rama se expandio
				objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>"
				//Se debe hacer visible el div
				objDivContenedor.className = 'shown';
				
				//Ahora se obtiene el span del título
				objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
				
				if (objSpan == null)
				{
					objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");
					CargarSiguientePagina(objSpan);
					return;
				} // if (objSpan == null)
			}
			else if(objIndicador.state == 'Visible') 
			{
				//Si está visible los hijos del elemento actual, solamente se selecciona el primer hijo
				
				if(objDivContenedor != null)
				{
					//El hijo contiene el span del +/-, el span del título (que debe ser el actual) y un div Contenedor
					objNuevo = ObtenerPrimerHijo(objDivContenedor);
										
					if(objNuevo != null)
					{	
						//Ahora se debe buscar el span del título
						objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
					}
				}
			}
			else if(objIndicador.state == 'NoCargado')
			{
				//Hay que cargar el XML, visualizar los hijos y seleccionar el primer hijo
				
				//Cambio resultado de nuevos requerimientos. Ahora cuando se carga un archivo xml
				//indica que una rama del arbol se va a mostrar, pero las otras hay que ocultarlas

				objHermanos = ObtenerHermanos(objPadre);
				/*for(nI = 0; nI< objHermanos.length; nI++)
				{
					if(objHermanos[nI].className == "clsItem" && objHermanos[nI] != objPadre)
					{
						objHermanos[nI].className = "clsItemOculto";
								
					}
				}				*/
				//Ahora se debe buscar el span del título
				objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");

				//Expande el nodo (lo hace visible)
				if(ExpandirNodo(objDivContenedor, objIndicador) == false)
					return false;
				
				//Carga el archivo XML 
				CargarXML(objSpan,objIndicador,objDivContenedor);
			}
			//En cualquiera de los casos siempre se selecciona el item actual
			if(objSpan != null)
			{
				objDivContenedorMP = objDivContenedor;
				SeleccionarHijo1Item();
				// SeleccionarItem(objSpan,true,false);
				//while(top.fraIzquierdo.fraBarra.m_objActual.TipoItem == "S")
				//{
					//Si se trata de una sección se debe ubicar en la primera página que tenga esta
					//Es decir, no se debe mostrar una sección
					//MoverDerecha();
				//}
			}
		}
	}		
}

function SeleccionarHijo1Item()
{
try {
	var objNuevo = ObtenerPrimerHijo(objDivContenedorMP);
	objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");

	if(objSpan.innerHTML == 'Cargando...')
		window.setTimeout("SeleccionarHijo1Item()", 1);
	else
		SeleccionarItem(objSpan,true,false);
}
catch(e)
{
	window.setTimeout("SeleccionarHijo1Item()", 1);
}
} // function SeleccionarHijo1Item

//***************************************************************************************************
//Function:	MoverDerecha
//Objetivo:	Se desplaza un item hacia la derecha (bajando en el árbol). En caso de que el item
//			actual tenga hijos se ubicará en el primero de ellos. Si estaban ocultos los hace
//			visible o también los carga en caso de que sea necesario. Cuando el item actual no
//			tiene hijos, sino que es una 'hoja', entonces no hace nada. Esa es la diferencia con
//			la función MoverProximo.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function MoverDerecha()
{
	var objNuevo;
	var objPadre;
	var objHijo;
	var objIndicador;
	var objDivContenedor;
	var objSpan;
	var objHermanos;
	var nI = 0;
	
	//En caso de que no exista un elemento actual se sale 
	if( null == top.fraIzquierdo.fraBarra.m_objActual )
		return false;
		
	var objEvento = top.fraIzquierdo.fraBarra.m_objActual;
		
	//Se obtiene el div de clase clsItem padre del span actual
	objPadre = objEvento.parentElement;
	
	//Si el padre no existe o no es de clase clsItem se sale
	if(objPadre != null && objPadre.className == 'clsItem')
	{
		//Se obtiene el span indicador, 'hermano' del span actual
		objIndicador = ObtenerElementoHtml(objPadre,"SPAN","indicador");
		
		if(objIndicador != null)
		{	
			//Primeramente se revisa si el elemento actual es una hoja
			objHijo = ObtenerElementoHtml(objIndicador,"SPAN","hoja")
			if(objHijo != null && objHijo.className == 'clsLeaf')
			{
				//Esta es la diferencia con la función MoverProximo. Aquí no hacemos
				//nada si se trata de una hoja.
				return false; 
			}
			
			//Se obtiene el div contenedor
			objDivContenedor = ObtenerElementoHtml(objPadre,"DIV","container");
			
			if(objIndicador.state == 'Oculto')
			{
				//Si el indicador esta oculto, hay que mostrarlo y seleccionar el primer hijo
				
				//Se obtiene el primer hijo
				objNuevo = ObtenerPrimerHijo(objDivContenedor);
				
				//Se debe indicar que el div es visible
				objIndicador.state == 'Visible';
				//Se indica que esta parte de la rama se expandio
				objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>"
				//Se debe hacer visible el div
				objDivContenedor.className = 'shown';
				
				//Ahora se obtiene el span del título
				objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
			}
			else if(objIndicador.state == 'Visible') 
			{
				//Si está visible los hijos del elemento actual, solamente se selecciona el primer hijo
				
				if(objDivContenedor != null)
				{
					//El hijo contiene el span del +/-, el span del título (que debe ser el actual) y un div Contenedor
					objNuevo = ObtenerPrimerHijo(objDivContenedor);
										
					if(objNuevo != null)
					{	
						//Ahora se debe buscar el span del título
						objSpan = ObtenerElementoHtml(objNuevo,"SPAN","label");
					}
				}
			}
			else if(objIndicador.state == 'NoCargado')
			{
				//Hay que cargar el XML, visualizar los hijos y seleccionar el primer hijo
				
				//Cambio resultado de nuevos requerimientos. Ahora cuando se carga un archivo xml
				//indica que una rama del arbol se va a mostrar, pero las otras hay que ocultarlas

				objHermanos = ObtenerHermanos(objPadre);
				for(nI = 0; nI< objHermanos.length; nI++)
				{
					if(objHermanos[nI].className == "clsItem" && objHermanos[nI] != objPadre)
					{
						objHermanos[nI].className = "clsItemOculto";
								
					}
				}
				
				//Ahora se debe buscar el span del título
				objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");

				//Expande el nodo (lo hace visible)
				if(ExpandirNodo(objDivContenedor, objIndicador) == false)
					return false;
				
				//Carga el archivo XML 
				CargarXML(objSpan,objIndicador,objDivContenedor);
			}
			
			//En cualquiera de los casos siempre se selecciona el item actual
			if(objSpan != null)
				SeleccionarItem(objSpan,true,false);
		}
	}		
}

//***************************************************************************************************
//Function:	ObtenerPrimerHijo
//Objetivo:	Recibe un elemento y devuelve el primer elemento HTML que contiene. Se dice que devuelve
//			el primer hijo, dado que ese control puede contener varios elementos HTML y el que 
//			retorna es el primero, indiferentemente cual sea.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerPrimerHijo(objElemento)
{
	var arrHijos;
	var objResultado = null;
	//Obtiene los hijos del elemento que recibe como parámentro
	arrHijos = objElemento.children;
	//Retorna el primer hijo. Puede devolver null si el elemento no tiene hijos
	objResultado = arrHijos[0];

	return objResultado;
}

//***************************************************************************************************
//Function:	SeleccionarItem
//Objetivo:	Se encarga de seleccionar el item actual. El item actual se pone con otro color de fondo
//			cambiandolo de clase. También se actualiza el objeto Actual, por lo que el objeto 
//			anterior debe volver a su estado original. Se pone el nombre del item seleccionado en
//			la barra de status y en la título de la ventana.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************

var m_bEscritorioRefrescado = false;

function SeleccionarItem(objEvento,bCargar,bForzarScroll)
{
	var m_fraArbol = top.fraIzquierdo.fraArbol;

	if (objEvento.parentElement != m_fraArbol.objUltimoResultBusqInd)
		m_fraArbol.objUltimoResultBusqInd = null;

	if (m_fraArbol.m_bReiniciarVarsRuta)
	{
		var m_lInsertarEn = objEvento.nivelArbol - 1;
		
		m_fraArbol.m_RutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_RutaItemActual[m_lInsertarEn] = objEvento.CodigoItem;
		
		m_fraArbol.m_TituloRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_TituloRutaItemActual[m_lInsertarEn] = objEvento.title;

		m_fraArbol.m_PropiedadRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_PropiedadRutaItemActual[m_lInsertarEn] = objEvento.propiedad;

		m_fraArbol.m_ValorRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_ValorRutaItemActual[m_lInsertarEn] = objEvento.valor;

		m_fraArbol.m_AlcanceRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_AlcanceRutaItemActual[m_lInsertarEn] = objEvento.alcance;

		m_fraArbol.m_TipoRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_TipoRutaItemActual[m_lInsertarEn] = objEvento.TipoItem;

		m_fraArbol.m_HrefRutaItemActual.length = m_lInsertarEn + 1;
		m_fraArbol.m_HrefRutaItemActual[m_lInsertarEn] = objEvento.Href;
		
		m_fraArbol.m_BDActual = objEvento.BD;
		m_fraArbol.m_ItemActual = objEvento.Item;
	} // if (m_fraArbol.m_bReiniciarVarsRuta)
	
	m_fraArbol.m_bEscritorioRefrescado = true;
	
	//Se debe cambiar de clase al objeto que antes de ahora era el actual
	if(top.fraIzquierdo.fraBarra.m_objActual != null)
	//Con ello se vuelve al color y formato original
	top.fraIzquierdo.fraBarra.m_objActual.className = 'clsLabel';
	//Se actualiza la variable global de objeto actual
	top.fraIzquierdo.fraBarra.m_objActual = objEvento;
	//Se le indica que el control HTML actual va a tener el focus
	top.fraIzquierdo.fraBarra.m_objActual.className = "clsCurrentHasFocus";
	//Se pone el nombre del item seleccionado en la barra de status
	window.defaultStatus = top.fraIzquierdo.fraBarra.m_objActual.title;
	//Se pone el nombre del item seleccionado en el titulo de la ventana
    	top.document.title = top.fraIzquierdo.fraBarra.m_objActual.title;
    
	//ScrollHorizontal(objEvento);
	
	//Modificación:  Si se trata de una pagina, entonces no se debe centrar la misma 
	//en el arbol. Solicitado por Eric Orlich el 04/06/2002
	//Cuando se sincroniza el árbol si se debe centrar el item en el scroll
	if(objEvento.TipoItem != "P" || bForzarScroll == true)
	{
		//objEvento.parentElement.scrollIntoView(true);
		ScrollHorizontal(objEvento);
	}
	//Se actualiza el texto principal del frame derecho
	
	if(bCargar == true)
	{
		CargarContenido(objEvento.parentElement);
	}
}

//***************************************************************************************************
//Function:	ScrollHorizontal
//Objetivo:	Crea y corre un scroll horizontal si se está descendiendo mucho en el árbol, de tal
//			manera que el usuario no pierda de vista los items que se van expandiendo. Recibe como
//			parámetro el control HTML sobre el que se hizo click, para determinar en donde se
//			encuentra.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ScrollHorizontal( objEvento )
{
	//Se obtiene el eje Y del elemento actual
   	var iY = objEvento.offsetTop - top.fraIzquierdo.fraArbol.window.document.body.clientHeight/2;
   	//Detalle objEvent.offsetTop siempre es cero ???
   	//alert(iY);
   	//Se obtiene el eje X del elemento actual 
   	var iX = objEvento.offsetLeft - 15;
   	//alert(iX);
   	//Se corre el scroll horizontal
   	top.fraIzquierdo.fraArbol.window.scrollTo( iX , iY );

    return;
}




//***************************************************************************************************
//Function:	CargarContenido
//Objetivo:	Recibe como parámetro la referencia al objeto padre del span de tipo 'label' y el
//			span de tipo 'enlace' con el objetivo de extraer el segundo span y tomara la referencia
//			o link y actualizar el contenido del frame principal del lado derecho.
//			Es decir, actualiza el contenido de la página central.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function CargarContenido(objElemento)
{
    var strHref = "";
    
    var objEnlace;
    var objLabel;
    
    //Se obtiene referencia al objeto 'label'
    objLabel = ObtenerElementoHtml(objElemento,"SPAN","label");
    
    //Se obtiene referencia al span donde se encuentra el link
    objEnlace = ObtenerElementoHtml(objElemento,"SPAN","enlace");
    if (objEnlace != null)
    {
	//El link es un atributo de ese elemento
	strHref = objEnlace.Href;
	
        //Si existe el link
        if(strHref != "")
        {
		//Se actualiza el contenido del frame derecho. 
		//Nótese que el link original no incluye el nombre del proyecto
		//window.open(PROYECTO + strHref,"fraEscritorio");
		top.fraDerecho.fraEscritorio.location.href = PROYECTO + strHref;
        }
    }

    objSpanSeleccionado = objElemento;
    top.fraIzquierdo.fraBarra.m_strItem = objLabel.codigo;
    //Esto no es compatible con Internet Explorer 5.0
    //document.cookie = "strBdItem" + "=" + escape(objLabel.codigo);

}

//***************************************************************************************************
//Function:	ObtenerElementoHtml
//Objetivo:	Busca un elemento HTML específico dentro de otro elemento HTML. Para ello se le debe
//			pasar un elemento padre que contenga al siguiente y devuelve la referencia al segundo.
//			Para identificar al segundo se le pasa el nombre del tag ('DIV', 'A', 'SPAN', etc) y
//			el type del mismo. Esta segunda característica no es propia de los elementos HTML sino
//			que se incluye en esta aplicación para uso propio. 
//			Nota: strTipo puede ser nulo, pero es sensible a mayúsculas si se pasa.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerElementoHtml(objPadre,strTagName,strTipo)
{
	var i = 0;
	var objResultado = null;
	var objHijos = null;
	//Si el padre no es nulo se obtiene los hijos del mismo
	if( null != objPadre )
		objHijos = objPadre.children;
	//Se recorren los hijos

	for (i = 0; objHijos != null && i < objHijos.length; i++)
	{
		//Se compara cada hijo para determinar si tiene el mismo tagName
		//Además se compara el type del control HTML

		if (objHijos[i].tagName.toUpperCase() == strTagName.toUpperCase() && ( strTipo == null || objHijos[i].type == strTipo) )
		{
			//En caso que en objeto padre tenga dos o más elementos con el mismo tagName y tipo, se devuelve solo el primero	
			objResultado = objHijos[i];
			break;
	    }
	}
	return objResultado;
}


//***************************************************************************************************
//Function:	ObtenerHermanoSig
//Objetivo:	Se obtiene el control 'hermano' del que recibe como parámetro. Esta función debe recibir
//			un objeto span de tipo 'label', para devolver el siguiente span 'label'. Aunque esto 
//			funciona con cualquier otro elemento, pero el resto de la aplicación no necesariamente
//			funcionará.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerHermanoSig(objElemento)
{
	var i = 0;
	var arrHermanos;
	var objResultado = null;
	//Se obtiene los hermanos del elemento actual
	arrHermanos = ObtenerHermanos(objElemento);
	//Si no tiene hermanos devuelve null
	if (arrHermanos != null)
	{	
		//Recorre los hermanos
		for (i = 0; i < arrHermanos.length; i++)
		{
			//Busca entre los hijos del padre el mismo objeto que recibe como parámetro
			if ((arrHermanos[i] == objElemento) && (i < (arrHermanos.length - 1)))
			{
				//Pero devuelve el objeto siguiente
				//Ojo: puede ser que devuelva null si el objeto actual es el último padre
				objResultado = arrHermanos[i+1];
				break;
			}
		}
	}
	//Devuelve la referencia al control 'hermano' siguiente
	return objResultado;
}


var objUltimoResultBusqInd = null;
var m_sUltFraseBusq = "";
var m_lUltTipoBusq = -1;

function BuscarEnIndice(sFrase, lTipoBusqueda)
{
	var objRama;
	var m_lDesdeHijo;
	var m_bIncluirPadre;
	var m_bIncluirPrimerHijo;
	var m_bIniciarDesdeRaiz = true;
	var m_fraArbol = top.fraIzquierdo.fraArbol;
	
	if ((m_fraArbol.objUltimoResultBusqInd != null) && (m_fraArbol.m_sUltFraseBusq == sFrase) && (m_fraArbol.m_lUltTipoBusq == lTipoBusqueda))
	{
		try {
			m_bIniciarDesdeRaiz = false;			
			objRama = top.fraIzquierdo.fraArbol.objUltimoResultBusqInd;
			m_lDesdeHijo = ObtenerIndexElemento(objRama);
			objRama = objRama.parentElement;			
			m_bIncluirPadre = false;
			m_bIncluirPrimerHijo = false;
		} // try
		catch(e)
		{
			m_bIniciarDesdeRaiz = true;
		} // catch(e)
	} // if ((m_fraArbol.objUltimoResultBusqInd != null) && (m_fraArbol.m_sUltFraseBusq == sFrase) && (m_fraArbol.m_lUltTipoBusq == lTipoBusqueda))

	if (m_bIniciarDesdeRaiz)
	{
		objRama = top.fraIzquierdo.fraArbol.divRaiz;
		m_lDesdeHijo = 0;
		m_bIncluirPadre = false;
		m_bIncluirPrimerHijo = true;
	} // if (m_bIniciarDesdeRaiz)
	
	var objResult = BuscarEnRama(objRama, sFrase, lTipoBusqueda, m_lDesdeHijo, m_bIncluirPadre, m_bIncluirPrimerHijo);
	if (objResult == null)
	{
		var m_sMensaje = 'No hay más resultados';
		
		if (m_bIniciarDesdeRaiz)
			m_sMensaje = 'No hay resultados';
			
		alert(m_sMensaje);
	} // if (objResult == null)

	else
	{
		var objSpan = ObtenerElementoHtml(objResult,"SPAN","label");
		SeleccionarItem(objSpan,true,true);
	} // else -- if (objResult == null)
	
	m_fraArbol.objUltimoResultBusqInd = objResult;
	m_fraArbol.m_sUltFraseBusq = sFrase;
	m_fraArbol.m_lUltTipoBusq = lTipoBusqueda;
} // function BuscarEnIndice(sFrase, lTipoBusqueda)


function ObtenerIndexElemento(objElemento)
{
	var i = 0;
	var arrHermanos;
	var Resultado = 0;
	arrHermanos = ObtenerHermanos(objElemento);

	if (arrHermanos != null)
	{	
		for (i = 0; i < arrHermanos.length; i++)
		{
			if (arrHermanos[i] == objElemento)
			{
				Resultado = i;
				break;
			} // if (arrHermanos[i] == objElemento)
		} // for (i = 0; i < arrHermanos.length; i++)
	} // if (arrHermanos != null)

	return Resultado;
} // function ObtenerIndexElemento(objElemento)

function BuscarEnRama(objPadre, sFrase, lTipoBusqueda, lDesdeHijo, bIncluirPadre, bIncluirPrimerHijo)
{
	if (bIncluirPadre)
	{
		if (BuscarEnTituloNodo(objPadre, sFrase, lTipoBusqueda))
			return objPadre;
	} // if (bIncluirPadre)

	var arrHijos = null;
	var objDivContenedor = ObtenerElementoHtml(objPadre,"DIV","container");
	
	if (objDivContenedor != null)
		arrHijos = objDivContenedor.children;
	else
		arrHijos = objPadre.children;

	if (arrHijos != null)
	{	
		var i;
		var m_bIncluirPadre = bIncluirPrimerHijo;
		
		for (i = lDesdeHijo; i < arrHijos.length; i++)
		{
			var objResult = BuscarEnRama(arrHijos[i], sFrase, lTipoBusqueda, 0, m_bIncluirPadre, true);
			m_bIncluirPadre = true;

			if (objResult != null)
			{
				if (objDivContenedor != null)
				{
					var objSpan = ObtenerElementoHtml(objPadre,"SPAN","label");
					ExpandirNodoV2(objSpan, false);
				} // if (objDivContenedor != null)
				
				return objResult;
			} // if (objResult != null)			
		} // for (i = lDesdeHijo; i < arrHijos.length; i++)
		
		return null;
	} // if (arrHijos != null)

	else
		return null;
} // function BuscarEnRama(objPadre, sFrase, lTipoBusqueda, lDesdeHijo, bIncluirPadre, bIncluirPrimerHijo)

function BuscarEnTituloNodo(objNodo, sFrase, lTipoBusqueda)
{
	var BUSCAR_PALABRAS_SIMILARES = 0;
	var BUSCAR_FRASE_EXACTA = 2;
	var BUSCAR_PALABRAS_EXACTAS = 3;

	var objSpan = ObtenerElementoHtml(objNodo,"SPAN","label");
	
	if (lTipoBusqueda == BUSCAR_PALABRAS_SIMILARES)
		return BuscarPalabrasSimilares(objSpan.title, sFrase);
		
	if (lTipoBusqueda == BUSCAR_FRASE_EXACTA)
		return BuscarFraseExacta(objSpan.title, sFrase);
	
	if (lTipoBusqueda == BUSCAR_PALABRAS_EXACTAS)
		return BuscarPalabrasExactas(objSpan.title, sFrase);
} // function BuscarEnTituloNodo(objNodo, sFrase, lTipoBusqueda)

function BuscarPalabrasSimilares(sTitulo, sFrase)
{
	return BuscarPalabrasSimilaresExactas(sTitulo, sFrase, 0);
} // function BuscarPalabrasSimilares(sTitulo, sFrase)

function BuscarFraseExacta(sTitulo, sFrase)
{
	var m_sTitulo = Trim(sTitulo.toLowerCase());
	var m_sFrase = Trim(sFrase.toLowerCase());

	if ((m_sFrase.length > 0) && (m_sTitulo.indexOf(m_sFrase) >= 0))
		return true;
	else
		return false;
} // function BuscarFraseExacta(sTitulo, sFrase)

function BuscarPalabrasExactas(sTitulo, sFrase)
{
	return BuscarPalabrasSimilaresExactas(sTitulo, sFrase, 1);
} // function BuscarPalabrasExactas(sTitulo, sFrase)

function BuscarPalabrasSimilaresExactas(sTitulo, sFrase, lTipo)
{
	var m_sFrase = Trim(sFrase);
	var arrPalabras = m_sFrase.split(' ');
	var m_sPalabra;
	var m_sTitulo = Trim(sTitulo.toLowerCase());
	var m_bResult = false;
	
	for(i = 0; i < arrPalabras.length; i++)
	{
		m_sPalabra = arrPalabras[i];
		m_sPalabra = m_sPalabra.toLowerCase();
		
		if (lTipo == 0)
			m_sPalabra = m_sPalabra.substr(0, 6);
		
		if (m_sPalabra.length > 0)
		{
			m_bResult = true;

			if (m_sTitulo.indexOf(m_sPalabra) < 0)
			{
				m_bResult = false;
				break;
			} // if (m_sTitulo.indexOf(m_sPalabra) < 0)
		} // if (m_sPalabra.length > 0)
	} // for(i = 0; i < arrPalabras.length; i++)
	
	return m_bResult;
} // function BuscarPalabrasSimilares(sTitulo, sFrase)

//******************************************************************************************
//Function:	SoloBlancos
//Objetivo:	Devuelve true si la hilera que le pasan por parámetro
//			solamente está compuesta de espacios en blanco.
//******************************************************************************************
function SoloBlancos(str)
{
	var nCuantos = str.length;
	if(nCuantos == 0)
		return true;
	var blancos = /^[\s]+$/;
	return blancos.test(str);
}
	

//*****************************************************************************************
//Function:	Trim
//Objetivo:	Trunca los espacios en blanco a la izquierda y a la 
//			derecha de la hilera que se le pasa por parámetro.
//			Devuelve la hilera modificada, por lo cual cuando se
//			invoca esta función se debe asignar a la variable con
//			que se quiere trabajar.
//****************************************************************************************
function Trim(str)
{
	var n = str.length;
	if(n == 0) 
		return "";
	if(SoloBlancos(str))
		return "";
	
	while (str.substr(0,1) == " ")
	{
		str = str.substr(1);
	}
	n = str.length;
	
	while (str.substr(n -1,1) == " ") 
	{
		str = str.substr(0,n-1);
		n = str.length;
	}
	return str;
}

//***************************************************************************************************
//Function:	ComprimirRama
//Objetivo:	Simplemente se oculta una parte del arbol que estaba visible al usuario. Para ello
//			lo que hace es cambiar de clase. No borra el contenido del div contenedor para no
//			tener que cargar el archivo XML otra vez y además se respete la rama como la dejó
//			el usuario.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ComprimirRama(objDivOculto, objIndicador)
{
	if(objDivOculto == null || objIndicador == null)
		return false; 

	//Cambiando a clase 'hide' se oculta el div contenedor
	if(objDivOculto.className == "shown")
		objDivOculto.className = "hide";
	//Nótese que no se borra el contenido de ese div, para mantener esa información
	//y no volver a cargar el XML

	//Se le cambia el estado al objeto indicador, especificando que ahora está oculto
	if(objIndicador.state == "Visible")
		objIndicador.state = "Oculto";
	//Se cambia el '-' por el '+'
	objIndicador.innerHTML = "<SPAN class='clsCollapse'>+</SPAN>";
}


//***************************************************************************************************
//Function:	ObtenerHermanoAnt
//Objetivo:	Toma un elemento y busca el tag o control HTML que está anterior a el. Esta función se
//			llama cuando se está utilizando la flecha UP y se quiere retroceder en el árbol. Es
//			importante que esta función reciba el elemento div de clase clsItem para poder identificar
//			el item anterior, si recibe el objeto actual (el cual siempre es el span label) no 
//			funcionará, dado que el 'hermano' anterior a ese span es el span indicador.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerHermanoAnt(objElemento)
{
	var j = 0;
	var arrHermanos;
	var objResultado = null;

	//Se obtienen los controles HTML 'hermanos' al que recibe como parámetro
	arrHermanos = ObtenerHermanos(objElemento);

	//Si tiene algún hermano
	if (arrHermanos != null)
	{
		//Se recorren los hermanos 
		for (j = 0; j < arrHermanos.length; j++)
		{
			//Buscando cual es idéntico al que se recibió como parámetro
			if (arrHermanos[j] == objElemento && j > 0)
			{
				//Se devuelve el item anterior al encontrado
				objResultado = arrHermanos[j-1];
				break;
			}
		}
	}
	//Se devuelve un solo hijo, puede ser null
	return objResultado;
}

//***************************************************************************************************
//Function:	ObtenerUltimoHijo
//Objetivo:	Recibe un elemento y devuelve el ultimo elemento HTML que contiene. Se dice que devuelve
//			el ultimo hijo, dado que ese control puede contener varios elementos HTML y el que 
//			retorna es el ultimo, indiferentemente cual sea. Puede ser que el último sea el mismo
//			que el primero o que no existan hijos.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerUltimoHijo(objElemento)
{
	var arrHijos;
	var objResultado = null;

	//Obtiene los hijos del elemento que recibe como parámentro
	arrHijos = objElemento.children; 
	//Puede devolver null si el elemento no tiene hijos
	if(arrHijos == null)
		return null;
	//Retorna el ultimo control HTML que contenga. 
	objResultado = arrHijos[arrHijos.length-1];

	return objResultado;
}

//***************************************************************************************************
//Function:	ObtenerHermanos
//Objetivo:	Devuelve los elementos 'hermanos' del que recibe como parámetro. Son hermanos si están
//			bajo el mismo 'padre'. (La relación hermanos, padre, etc es posicional, es decir,depende
//			de la posición en el documento). 
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ObtenerHermanos(objEvento)
{
	var objPadre;
	var objResultado = null;
	var bSalir = false;

	//Obtiene el elemento padre del objeto
//	objPadre = objEvento.parentElement;

	try
	{
	  objPadre = objEvento.parentElement;
	}
	catch(e)
	{
		return null; 
	}
	
	//Si el padre no es nulo
	if ( objPadre != null )
		//Retorna los hijos del mismo, incluyendo al objeto que recibe como parámetro
		objResultado = objPadre.children
	
	return objResultado;
}

//***************************************************************************************************
//Function:	Revisar
//Objetivo:	Se toma el evento click para determinar si se debe expander o comprimir una parte
//			del árbol de base de datos. Además puede cargar una página en el frame central, siempre
//			y cuando la segunda variable que reciba como parámetro indique 'true'.
//Nota:		Si tiene que MODIFICAR esta función, tal vez tenga que hacer lo mismo con RevisarRapido
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************

function Revisar(objEvento, bActualizarEscritorio)
{
	var objPadre;			//Objeto padre del anterior
	var objDivOculto;		
	var objIndicador;
	var objHoja;	
	var bCargar = false;	
	var bOcultarBDs = false;

try {
	if(objEvento == null)
		return;

	objPadre = objEvento.parentElement;
	
	//No nos interesa los elementos que no tienen padre, porque la estructura no debería 
	//permitir eso.
	if(objPadre == null)
		return;
	
	//Si el control no tiene una clase definida no nos interesa
	if(objEvento.className == null)
		return;

	//Si el usuario hizo click en el '+', '-' o '.' se cambia el control HTML por el label
	//que tiene el texto. Esto para que si el usuario hace click en esos elementos también
	//se pueda navegar por el arbol


	if(objEvento.className == 'clsCollapse' || objEvento.className == 'clsExpand'  || objEvento.className == 'clsLeaf' || objEvento.className == 'clsSpace')
	{
	
		if(objEvento.className != 'clsSpace')
		{	//Si la clase no es clsSpace entonces se debe cambiar de padre, ya que el padre de
			//esos span es clsSpace y ocupamos al padre de este último
			objPadre = objPadre.parentElement;
		}
		//Se obtiene el span del label
		objEvento = ObtenerElementoHtml(objPadre,"SPAN","label");
		//Si no se encuentra un span de label se sale 
		if(objEvento == null)
			return;
	}

	objIndicador = ObtenerElementoHtml(objPadre,"SPAN","indicador");
	objDivOculto = ObtenerElementoHtml(objPadre,"DIV","container");
	objHoja = ObtenerElementoHtml(objIndicador,"SPAN","hoja")

	if(objEvento.type == 'label')
	{
		if (objHoja != null || objDivOculto.className != "hide")
			SeleccionarItem(objEvento,bActualizarEscritorio,false);
	} // if(objEvento.type == 'label')

	if(objHoja == null)
	{
		//Si el indicador especifica que el div contenedor está oculto, entonces no hay
		//que volver a cargar el xml
		//if(objIndicador.state == 'NoCargado')
		if(!m_bSincronizando)
			bCargar = true;

		//Se expande o se comprime el nodo. No carga XML, solo hace visible u oculta div contenedor
		//Además de cambiar el '+' por el '-' o viceversa
		if(objDivOculto.className == "hide")
		{
			if(ExpandirNodo(objDivOculto,objIndicador) == false)
				return false;
				else
			{
				//Si el archivo ya está cargado entonces solamente se muestra

				if(bCargar == true)
				{
					//Cargar el archivo XML y reemplazar el div con los nuevos datos
					SeleccionarItem(objEvento,false,false);
					top.fraIzquierdo.fraBarra.m_strItem = objEvento.codigo;
					CargarXML(objEvento, objIndicador, objDivOculto);
				}
				else
					SeleccionarItem(objEvento,bActualizarEscritorio,false);
			}
		}
		else
			ComprimirRama(objDivOculto,objIndicador);
	}
} catch(e) {}
}

function Revisar1(objEvento, bActualizarEscritorio)
{
	var objPadre;			//Objeto padre del anterior
	var objDivOculto;		
	var objIndicador;
	var objHoja;	
	var bCargar = false;	
	var bOcultarBDs = false;

	//Se obtiene el padre del padre al que pertenece el elemento HTML actual. El mismo puede ser null
	//Para entender esto vea la forma en que está compuesto el ordenamiento de los tag HTML
	if(objEvento == null)
		return;
		
	objPadre = objEvento.parentElement;
	
	//No nos interesa los elementos que no tienen padre, porque la estructura no debería 
	//permitir eso.
	if(objPadre == null)
		return;
	
	//Si el control no tiene una clase definida no nos interesa
	if(objEvento.className == null)
		return;

	//Si el usuario hizo click en el '+', '-' o '.' se cambia el control HTML por el label
	//que tiene el texto. Esto para que si el usuario hace click en esos elementos también
	//se pueda navegar por el arbol

	if(objEvento.className == 'clsCollapse' || objEvento.className == 'clsExpand'  || objEvento.className == 'clsLeaf' || objEvento.className == 'clsSpace')
	{
	
		if(objEvento.className != 'clsSpace')
		{	//Si la clase no es clsSpace entonces se debe cambiar de padre, ya que el padre de
			//esos span es clsSpace y ocupamos al padre de este último
			objPadre = objPadre.parentElement;
		}
		//Se obtiene el span del label
		objEvento = ObtenerElementoHtml(objPadre,"SPAN","label");
		//Si no se encuentra un span de label se sale 
		if(objEvento == null)
			return;
	}
	
	//Se obtiene el elemento de tipo indicador (el que tiene el + o el -)
	objIndicador = ObtenerElementoHtml(objPadre,"SPAN","indicador");
	//Se obtiene el div que se contiene el resto del arbol (hijos del elemento actual)
	//Este elemento puede estar oculto

	objDivOculto = ObtenerElementoHtml(objPadre,"DIV","container");
	if(objIndicador == null || objDivOculto == null)
		return false;
		
	//Nuevo requerimiento: Cuando el usuario navege por una rama diferente a la que tenía anteriormente
	//se debe 'cerrar' la anterior. Para ello se toman los hermanos del item actual y se comprimen todos
	//En caso de que se trate de item actual no se hace nada. Tampoco hace nada si el item es página
	if(objEvento.TipoItem != "P" && top.fraIzquierdo.fraBarra.m_bCompactar == true)
	{
		//Hay que COMPRIMIR (no ocultar) sus hermanos
		var objHermanos;
		var nHermanos = 0;
		var objIndicadorTemp;
		var objDivTemp;
		var nI = 0;
		//Se obtienen los hermanos del padre del item actual
		objHermanos = ObtenerHermanos(objPadre);
		
		//Nuevo requerimiento: se quiere que los hermanos del que he seleccionado
		//se oculten. Esto con el objetivo de minimizar el tamaño del indice y 
		//dejarlo parecido a lo de MasterLex 2000. En caso de que se quiera que solo
		//la parte de las bases de datos se quita el comentario en la siguiente linea.
		//if(objEvento.TipoItem == "E1")
		{
			bOcultarBDs = true;
		}
		
		//Determinamos cuantos hermanos son
		nHermanos = objHermanos.length;
		for(nI == 0; nI < nHermanos; nI++)
		{
			//Solicitamos el div indicador y el div oculto de cada hermano
			objIndicadorTemp = ObtenerElementoHtml(objHermanos[nI],"SPAN","indicador");
			objDivTemp = ObtenerElementoHtml(objHermanos[nI],"DIV","container");
			//Si el item no es el actual ...
			if(objDivTemp != objDivOculto)
			{
				//se comprime la rama desplegada
				ComprimirRama(objDivTemp, objIndicadorTemp);
				
				//Nuevo requerimiento: se desea que cuando el usuario abra un base de datos
				//se OCULTEN (no solo se compriman) las demas bases.Esto solo aplica al primer nivel del arbol
				//el cual indica las base de datos y se distinguen porque la propiedad TipoItem vale E1.
				if(bOcultarBDs == true)
				{
					if(objIndicador.state == 'Visible')
					{
						//Si el indicador es visible entonces el usuario lo que va a hacer es comprimir la 
						//base de datos y por lo tanto hay que presentar todas las que pueda ver.
						if(objHermanos[nI].className == "clsItemOculto")
						{
							objHermanos[nI].className = "clsItem";
						}
					}
					else
					{
						if(objHermanos[nI].className == "clsItem")
						{
							objHermanos[nI].className = "clsItemOculto";
						}
					}
				}
			}
		}
	}
	//Se revisa si el elemento es simplemente una hoja
	objHoja = ObtenerElementoHtml(objIndicador,"SPAN","hoja")
	if(objHoja == null)
	{
		//Si el indicador especifica que el div contenedor está oculto, entonces no hay
		//que volver a cargar el xml
		//if(objIndicador.state == 'NoCargado')
		if(!m_bSincronizando)
			bCargar = true;

		//Se expande o se comprime el nodo. No carga XML, solo hace visible u oculta div contenedor
		//Además de cambiar el '+' por el '-' o viceversa
		if(objDivOculto.className == "hide")
		{
			if(ExpandirNodo(objDivOculto,objIndicador) == false)
				return false;
				else
			{
				//Si el archivo ya está cargado entonces solamente se muestra

				if(bCargar == true)
				{
					//Cargar el archivo XML y reemplazar el div con los nuevos datos
					CargarXML(objEvento, objIndicador, objDivOculto);
				}
			}
		}
		else
			ComprimirRama(objDivOculto,objIndicador);
	}

	if(objEvento.type == 'label')
	{
		//Se actualiza el objeto actual, se le pasa la misma variable que se recibe como segundo parámetro
		//que indica si debe refrescar la página del frame central o no.
		SeleccionarItem(objEvento,bActualizarEscritorio,false);
		
		//while(top.fraIzquierdo.fraBarra.m_objActual.TipoItem == "S" && objIndicador.state == "Visible")
		//{
			//Si se trata de una sección se debe ubicar en la primera página que tenga esta
			//Es decir, no se debe mostrar una sección
		//	MoverDerecha();
		//}
	}
}


//***************************************************************************************************
//Function:	ExpandirNodo
//Objetivo:	Recibe como parámetro una referencia al div contenedor para mostrarlo u ocultarlo
//			Dicho div contiene una 'rama' del arbol. En caso de que la información de dicha rama
//			no se haya cargado, se invoca a la función para cargar el XML.
//			Además cambia el '+' por el '-' o viceversa; para ello toma en cuenta la referencia
//			del segundo parámetro (que debe indicar el span de type=indicador).
//			Retorna true si pudo terminar todas sus funciones, false si alguno de los objetos 
//			de la referencia es nulo.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function ExpandirNodo( objDivOculto, objIndicador)
{
	if(objDivOculto == null || objIndicador == null)
		return false; 

	//Si el estado de ese div es oculto entonces se debe mostrar
	if(objDivOculto.className == null || objDivOculto.className == "hide")
	{
		//Se cambia la clase de dicho div, lo que lo hará visible
		objDivOculto.className = "shown";
	}
	else
	{
		alert('Error logico');
		//En caso de que el elemento ya se ha mostrado, se oculta
		objDivOculto.className = "hide";
		//Nótese que no se borra el contenido de ese div, para mantener esa información
		//y no volver a cargar el XML
	}
		
	//****************************************************************************
	//Cambiar el span que contiene el '+' o el '-' (Expandido o comprimido)
	//****************************************************************************
	//Originalmente ningún div contenedor está cargado, pero en el transcurso
	//se pueden ir cargando. Esto se hace con el objetivo de no volver a cargar
	//el archivo XML y además dejar esa parte del árbol como la tenía el usuario.

	if(objIndicador.state == "NoCargado" || !m_bSincronizando)
	{

		//Se pone un texto que dice 'Cargando...' por mientras, luego
		//se cambia por el contendio del item actual
		objDivOculto.innerHTML = strTexto_Hoja + ">" + m_strCargando + strCierre;
		
		//window.defaultStatus = m_strCargando;
	}
	//En caso de que el div contenedor esté oculto, significa que ya se había cargado
	//por lo tanto sólo se debe mostrar (cambiando la clase)
	else if(objIndicador.state == "Oculto")
	{
		//Se le cambia el estado al objeto indicador, especificando que ahora es visible
		objIndicador.state = "Visible";
		//Se cambia el '+' por el '-'
		objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>";
	}
	else if(objIndicador.state == "Visible")
	{
		//Se le cambia el estado al objeto indicador, especificando que ahora está oculto
		objIndicador.state = "Oculto";
		//Se cambia el '-' por el '+'
		objIndicador.innerHTML = "<SPAN class='clsCollapse'>+</SPAN>";
	}

	//Resultado de la función si todo salió bien
	return true;
}

function report_error(msg, url, line)
{
	alert(msg);
	alert(url);
	alert(line);
}
// now register the error handler
window.onerror = report_error;

//***************************************************************************************************
//Function:	CargarXML
//Objetivo:	Se encarga de crear un objeto XMLDom y carga el archivo para presentarlo en el índice
//			para ello forma una serie de código HTML previamente establecido y luego le pasa todo
//			ese código al div contenedor o div Oculto.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************

function CargarXML(objEvento, objIndicador, objDivOculto)
{
	//Si no se encuentra oculto el indicador
	//if(objIndicador.state == "NoCargado")
	//{			
		objDivOcultoRefrescar = objDivOculto;
		objIndicadorRefrescar = objIndicador;
		top.fraIzquierdo.fraArbol.m_bEscritorioRefrescado = true;
		//top.fraOculto2.location.href = "ApoyoDHTML.asp?Funcion=CargarHijosVisiblesNodo&BD="+objEvento.BD+"&Item="+objEvento.Item+"&NivelArbol="+objEvento.nivelArbol;
		top.fraOculto2.location.href = "ApoyoDHTML.asp?Funcion=SincronizarArbol&BD="+objEvento.BD+"&Item="+objEvento.Item+"&ItemSincronizar="+objEvento.Item+"&CargarContenido=S"+"&NivelArbol="+objEvento.nivelArbol;
	//}
}

function CargarXML1(objEvento, objIndicador, objDivOculto)
{
	//Si no se encuentra oculto el indicador
	if(objIndicador.state == "NoCargado")
	{					
		var strHTML = "";
		var m_Verificaciones = new ActiveXObject("DMInternet.CVerificaciones");
		var m_rst = m_Verificaciones.CargarHijosVisiblesNodo(objEvento.BD, objEvento.Item);
				
		//Recorre los hijos (nodos)
		while (!m_rst.eof)
		{
			var m_lBD = m_rst("itm_bd");
			var m_lItem = m_rst("itm_item");
			var m_sCodigo = "bd_" + m_lBD + "_" + m_lItem;
			var m_lConsecutivo = m_rst("itm_consecutivo");
			var m_sTitulo = m_rst("itm_titulo");
			var m_sTipo = m_rst("itm_tipo");
			var m_sHref= "indice.asp?nBD=" + m_lBD + "&nItem=" + m_lItem + "&nModo=2"
			
			//Se escribe el nuevo texto HTML que contendrá el nuevo div
			//En caso de que el item sea hoja se debe especificar un span con un .
			if(m_sTipo == 'P')
			{
				strHTML += strTexto_Hoja;
			}
			else
			{
				strHTML += strTexto;
			}
			
			strHTML += " BD='" + m_lBD + "' Item='" + m_lItem + "' TipoItem='" + m_sTipo + "' title='" + m_sTitulo + "' codigo='" + m_sCodigo + "' consecutivo='" + m_lConsecutivo + "'>" + m_sTitulo;
			strHTML += "</SPAN><SPAN class='clsSpace' type='enlace' Href='" + m_sHref + "'>" + strCierre;
			
			m_rst.MoveNext;
		}	
		//Se crea un elemento div en el cliente
		var newDIV = document.createElement("DIV");
		//Se le indica que el contenido del mismo
		newDIV.innerHTML = strHTML;
		//Se le debe indicar que ese div es contenedor a la vez
		newDIV.type = "container";
		//Se le debe indicar al div nuevo la clase (asignarle un formato)
		newDIV.className = "shown";
		
		//Se cambia el div que estaba oculto por el nuevo
		objDivOculto.innerHTML = strHTML;
		objDivOculto.type = "container";
		objDivOculto.className = "shown";

		//Si el indicador existe
		if(objIndicador != null)
		{	
			//Se le debe indicar que ya está visible
			objIndicador.state = "Visible";
			//Se cambia el '+' por el '-'
			objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>";
		}
	}
}

function GenerarRepresentacionArbol(objElemento)
{
	var objDivContenedor;
	var m_sRepresentacion = "";

	if (objElemento == null)
		var objDivContenedor = top.fraIzquierdo.fraArbol.document.all("divRaiz");
	else
	{
		m_sRepresentacion = m_sRepresentacion + "<LI>" + objElemento.title;
		objDivContenedor = ObtenerElementoHtml(objElemento.parentElement,"DIV","container");
	} // if (objElemento == null)

	if(objDivContenedor != null)
	{
		var objHijos = objDivContenedor.children;
		var nHijos = objHijos.length;
		var nI = 0;

		if (nHijos > 0)
		{
			m_sRepresentacion = m_sRepresentacion + "<UL>";
				
			for(nI = 0; nI < nHijos; nI++)
			{
				//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
				var objSpan = ObtenerElementoHtml(objHijos[nI],"SPAN","label");

				if (objSpan != null)
					m_sRepresentacion = m_sRepresentacion + GenerarRepresentacionArbol(objSpan);
					
			} // for(nI = 0; nI < nHijos; nI++)

			m_sRepresentacion = m_sRepresentacion + "</UL>";
		} // if (nHijos > 0)
	} // if(objDivContenedor != null)
	
	return m_sRepresentacion;
} // function GenerarRepresentacionArbol()

function ExpandirNodoV2(objElemento, bScroll)
{
	try {
	var objDivContenedor = ObtenerElementoHtml(objElemento.parentElement,"DIV","container");

	if(objDivContenedor == null)
		return;

	var objIndicador = ObtenerElementoHtml(objElemento.parentElement, "SPAN","indicador");

	if(objIndicador == null)
		return;

	var objHoja = ObtenerElementoHtml(objIndicador,"SPAN","hoja")
	
	if(objHoja == null)
		objIndicador.innerHTML = "<SPAN class='clsExpand'>-</SPAN>";

	if (bScroll)
	{
		//var objFocus = ObtenerElementoHtml(objElemento.parentElement,"SPAN","label");
		//objFocus.scrollIntoView(true);
		//ScrollHorizontal(objFocus);

		if (m_bCargarContenido)
			CargarContenido(objElemento.parentElement);
	} // if (bScroll)

	objDivContenedor.className = "shown";
	} catch(e) {}
} // function ExpandirNodoV2(objElemento)

//***************************************************************************************************
//Function:	SincronizarTemp
//Objetivo:	Esta función toma la página que se está mostrando en el frame central (fraEscritorio)
//			y la busca en el árbol, seleccionandola. Para ello, se fija en una variable definida en
//			el frame fraBarra, llamada m_strItem. Esa variable indica quien es la página que
//			está cargada en la página central. Luego comienza a recorrer el árbol en búsqueda del
//			item de la base de datos y luego el registro del item actual. 
//NOTA:		Para mayor eficiencia antes de invocar esta función se debe cargar el árbol de nuevo (reload)
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************

var objSpanST;
var nBDST;
var nSincItemST;
var lIndexRutaItem;
var m_bCargarContenido;
var m_bReiniciarVarsRuta = true;
var m_bSincronizando = false;

function SincronizarTemp(bCargarContenido)
{

	var objRaiz;				//Referencia al div llamado 'divRaiz'
	var nBD;					//Código de la base de datos a buscar
	var strBuscar;				//Código a buscar entre los items iniciales del árbol
	var nItem = '';				//Código del item o página a buscar en el índice
	var nPosicion, nPosicion2;	
	var nI;
	var objHijos;			
	var nHijos = 0;
	var objSpan;				//Referencia al span de clase clsLabel encontrado

	m_bCargarContenido = bCargarContenido;
	//m_bSincronizando = true;

	//var nSincItem = top.fraDerecho.fraEscritorio.fraEncabezado.nItemConsecutivo; 
	var nSincItem = 0;

	//Se averigua cual es el item cargado en el frame central
	var strItem = top.fraIzquierdo.fraBarra.m_strItem;

	//Si no se indica nada se sale, no hay que sincronizar nada
	if(strItem == '' || strItem == null)
		return;
	
	//El item viene con un formato como: bd_5_343 donde el primer número es la base de datos
	//y el segundo el número de item. Puede ser que el segundo número no venga (si es una referencia
	//a la raiz de una base de datos). Entonces extraemos esos dos posibles números.
	nPosicion = strItem.indexOf("_");

	// Modificación por Manuel Vargas. 02/marzo/2004. Listado de Modificaciones: 1
	// nPosicion2 = strItem.lastIndexOf("_");
	nPosicion2 = strItem.indexOf("_", nPosicion+1)
	// Fin de modificación por Manuel Vargas

	if(nPosicion == -1)
		return;
	if(nPosicion == nPosicion2)
	{
		//Solo indica Base de datos
		nBD = strItem.substr(nPosicion+1);
	}
	else
	{
		//Indica la base de datos y el índice
		nBD = strItem.substring(nPosicion+1,nPosicion2);
		nItem = strItem.substr(nPosicion2+1);
	}
	
	//Primero vamos a buscar la base de datos en el árbol
	strBuscar = "bd_" + nBD + "_";

	//Obtenemos la referencia al div inicial que tiene todo el árbol
	objRaiz = top.fraIzquierdo.fraArbol.document.all("divRaiz");

	if(objRaiz == null)
		return;
	else
	{
		//Se obtienen los items padres, aquellos divs que son de clase clsItem
		objHijos = objRaiz.children;
		//Se identifican cuantos son
		nHijos = objHijos.length;

		//Se recorre todas las bases de datos (items iniciales que aparecen en el índice)
		//Recuerde que sólo eso debe estar cargado y no las demás enciclopedias o documentos.
		for(nI = 0; nI < nHijos; nI++)
		{
			//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
			objSpan = ObtenerElementoHtml(objHijos[nI],"SPAN","label")

			if(objSpan != null)
			{
				//Se pregunta por el código del item actual para ver si es el mismo al que buscamos

				if(objSpan.codigo.indexOf(strBuscar) == 0)
				{
					if(nItem == '')
					{
						//Solo hay que seleccionar la base de datos	
						SeleccionarItem(objSpan,false,true);
					}
					else
					{
						//Ya encontramos la base de datos, ahora hay que buscar de forma recursiva el item
						//Revisar(objSpan,false);

						//Seleccionamos el item encontrado
						objSpanST = objSpan;
						nBDST = nBD;
						nSincItemST = nSincItem;
						lIndexRutaItem = 1;

						if (lIndexRutaItem == top.fraIzquierdo.fraArbol.m_RutaItemActual.length)
							SeleccionarItem(objSpan,false,true);

						ResincronizarHijoTemp();
						//SincronizarHijoTemp(objSpan,nBD,nItem);
						return;
					}
				}
			}
		}
	}
}

var m_bArbolYContenidoSincronizados = false;

function SincronizarTemp2(nBD, nItem, bCargarContenido)
{
	var objRaiz;				//Referencia al div llamado 'divRaiz'
	var strBuscar;				//Código a buscar entre los items iniciales del árbol
	var nI;
	var objHijos;			
	var nHijos = 0;
	var objSpan;				//Referencia al span de clase clsLabel encontrado
	
	strBuscar = "bd_" + nBD + "_" + nItem;
	objRaiz = top.fraIzquierdo.fraArbol.document.all("divRaiz");

	if(objRaiz == null)
		return;
	else
	{
		//Se obtienen los items padres, aquellos divs que son de clase clsItem
		var objHijos = objRaiz.children;
		//Se identifican cuantos son
		var nHijos = objHijos.length;

		//Se recorre todas las bases de datos (items iniciales que aparecen en el índice)
		//Recuerde que sólo eso debe estar cargado y no las demás enciclopedias o documentos.

		for(nI = 0; nI < nHijos; nI++)
		{
			//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
			objSpan = ObtenerElementoHtml(objHijos[nI],"SPAN","label")

			if(objSpan != null)
			{
				//Se pregunta por el código del item actual para ver si es el mismo al que buscamos

				if(objSpan.codigo == strBuscar)
				{
					SeleccionarItem(objSpan, bCargarContenido, true);					
					top.fraIzquierdo.fraArbol.m_bArbolYContenidoSincronizados = true;
					nI = nHijos;
				} // if(objSpan.codigo == strBuscar)
			} // if(objSpan != null)
		} // for(nI = 0; nI < nHijos; nI++)
	} // else -- if(objRaiz == null)
} // function SincronizarTemp2(nBD, nItem, bCargarContenido)

function ResincronizarHijoTemp()
{
try{
	if (lIndexRutaItem < top.fraIzquierdo.fraArbol.m_RutaItemActual.length)
	{
		ExpandirNodoV2(objSpanST, false);
		nSincItemST = top.fraIzquierdo.fraArbol.m_RutaItemActual[lIndexRutaItem];
		SincronizarHijoTemp(objSpanST,nBDST,nSincItemST);
		lIndexRutaItem = lIndexRutaItem + 1;
	} // if (lIndexRutaItem < top.fraIzquierdo.fraArbol.m_RutaItemActual.length)
	else
		ExpandirNodoV2(objSpanST, true);
}
catch(e)
{
	window.setTimeout("ResincronizarHijoTemp()", 1);
}
} // function ResincronizarHijoTemp()

//********************************************************************************************************
//Function:	SincronizarHijoTemp
//Objetivo:	Esta función busca de forma recursiva un item en específico. Recibe la referencia de 
//			quien es el item 'padre' que lo contiene y lo busca dentro de él. En caso de que no sea
//			hijo directo del item 'padre', lo busca entre alguno de sus hijos. Para determinar entre
//			cual de sus hijos se basa en el código del item. Esta función sólo es llamada por Sincronizar
//			la cual trata de localizar en el árbol la referencia a la página que está en el frame central.
//NOTA:		Las referencias entre los diversos hijos del índice deben estar en forma ORDENADA en forma
//			ascendente. Esta función es recursiva.
//Fecha:	Abril 2002
//Autor:	Christian Sandoval Moya (S-COM)
//********************************************************************************************************
function SincronizarHijoTemp(objElemento,nBD,nItem)
{

	var objRaiz;
	var nBD;
	var strBuscar;
	var objDivContenedor;
	var nPosicion, nPosicion2;
	var nJ, nJ2, nI;
	var objItems;
	var objElemento;
	var objHijos, nHijos2;
	var strCodigo = '';
	var nHijos = 0;
	var objSpan;
	var nNuevaBD, nNuevoItem;

	if(objElemento == null)
		return;
	//Se obtiene referencia al div contenedor del padre del objeto actual.
	//El objeto que recibe como parámetro siempre es un span clsLabel, obteniendo el 
	//div contenedor, obtenemos referencia a los 'hijos' del item actual

	objDivContenedor = ObtenerElementoHtml(objElemento.parentElement,"DIV","container");

	if(objDivContenedor == null)
		return;

	//Se arma el código que hay que buscar. Ej: bd_123_5487
	strBuscar = "bd_" + nBD + "_" + nItem;

	//Se obtienen los items padres, aquellos divs que son de clase clsItem
	objItems = objDivContenedor.children;
	//Se identifican cuantos son los hijos
	nHijos = objItems.length;
	//Se recorren los hijos del item 'padre' que recibimos como parámetro

	for(nI = 0; nI < nHijos; nI++)
	{
		//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
		objSpan = ObtenerElementoHtml(objItems[nI],"SPAN","label")

		if(objSpan != null)
		{
			//Se obtiene el código del span que estoy recorriendo ...
			strCodigo = objSpan.codigo;
			//Para identificar cual es la base de datos a la que pertence y cual es su item
			
			nPosicion = strCodigo.indexOf("_");
			
			// Modificación por Manuel Vargas. 23/julio/2004
			// nPosicion2 = strCodigo.lastIndexOf("_");
			nPosicion2 = strCodigo.indexOf("_", nPosicion+1)
			// Fin de modificación por Manuel Vargas
			
			if(nPosicion == nPosicion2)
			{
				//Solo indica Base de datos
				nNuevaBD = strCodigo.substr(nPosicion+1);
			}
			else
			{
				//Indica la base de datos y el índice
				nNuevaBD = strCodigo.substring(nPosicion+1,nPosicion2);
				nNuevoItem = parseInt(strCodigo.substr(nPosicion2+1),10);
			}

			//Si ya encontramos el item, perfecto, hasta aquí llegamos, 

			if(objSpan.codigo == strBuscar)
			{

				if (lIndexRutaItem == top.fraIzquierdo.fraArbol.m_RutaItemActual.length-1)
				{
					//Revisar(objSpan,false)
					SeleccionarItem(objSpan,false,true);
					ExpandirNodoV2(objSpan, true);
					return;
				} // if (lIndexRutaItem == top.fraIzquierdo.fraArbol.m_RutaItemActual.length-1)

				else {
					//Revisar(objSpan,false);
					//SeleccionarItem(objSpan,false,false);
					//Llamado recursivo con el span clsLabel.
					objSpanST = objSpan;
					nBDST = nBD;
					nSincItemST = nItem;
					lIndexRutaItem = lIndexRutaItem + 1;
					ResincronizarHijoTemp();
					//SincronizarHijoTemp(objSpan,nBD,nItem);
					//NO ocupamos hacer nada después, nos salimos del todo
					return;
				} // else
			}
			//En el caso de que el item buscado sea 'hijo' del último item buscado, también debemos
			//hacer llamado recursivo a esta función
			if(nI +1 == nHijos)
			{	
				//Hay que buscar con el último 'padre'
				objSpan = ObtenerElementoHtml(objItems[nI],"SPAN","label")
				//Primeramente se debe cargar esa parte del índice, extrayendola del archivo XML
				Revisar(objSpan,false);

				//Llamado recursivo con el span clsLabel
				objSpanST = objSpan;
				nBDST = nBD;
				nSincItemST = nItem;
				ResincronizarHijoTemp();

				//SincronizarHijoTemp(objSpan,nBD,nItem);
				return;
			}
		}
	}
}



function Sincronizar()
{
	var objRaiz;				//Referencia al div llamado 'divRaiz'
	var nBD;					//Código de la base de datos a buscar
	var strBuscar;				//Código a buscar entre los items iniciales del árbol
	var nItem = '';				//Código del item o página a buscar en el índice
	var nPosicion, nPosicion2;	
	var nI;
	var objHijos;			
	var nHijos = 0;
	var bSalir = false;
	var objSpan;				//Referencia al span de clase clsLabel encontrado

	//Se averigua cual es el item cargado en el frame central
	var strItem = top.fraIzquierdo.fraBarra.m_strItem;
	var strPadre = top.fraIzquierdo.fraBarra.m_strPadre;

	//Si no se indica nada se sale, no hay que sincronizar nada
	if(strPadre == null || strPadre == '')
		return;
	
	//El item viene con un formato como: 5_1_2_4_78_90, donde el primer número indica la base de datos
	//el último el número de item de la página a mostrar y los números intermedios los diferentes 'padres'
	//que tiene el item página hasta llegar a la raíz. 
	nPosicion = strPadre.indexOf("_");
	
	if(nPosicion == -1)
		return;
		
	//Se obtiene el número de base de datos
	nBD = strPadre.substr(0,nPosicion);
	//Se elimina ese número de la hilera, para que queden sólo padres.
	strPadre = strPadre.substr(nPosicion+1)
	
	//Primero vamos a buscar la base de datos en el árbol
	strBuscar = "bd_" + nBD;

	//Obtenemos la referencia al div inicial que tiene todo el árbol
	objRaiz = top.fraIzquierdo.fraArbol.document.all("divRaiz");
	if(objRaiz == null)
		return;
	else
	{
		//Se obtienen los items padres, aquellos divs que son de clase clsItem
		objHijos = objRaiz.children;
		//Se identifican cuantos son
		nHijos = objHijos.length;
		
		//Se recorre todas las bases de datos (items iniciales que aparecen en el índice)
		//Recuerde que sólo eso debe estar cargado y no las demás enciclopedias o documentos.
		//for(nI = 0; nI < nHijos; nI++)
		nI = 0;
		while(bSalir == false)
		{
			//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
			objSpan = ObtenerElementoHtml(objHijos[nI],"SPAN","label")
						
			if(objSpan != null)
			{
				//Se pregunta por el código del item actual para ver si es el mismo al que buscamos
				if(objSpan.codigo == strBuscar)
				{
					if(strPadre == '')
					{
						//Solo hay que seleccionar la base de datos	
						SeleccionarItem(objSpan,false,true);
						bSalir = true;
					}
					else
					{
						//Ya encontramos la base de datos, ahora hay que buscar de forma recursiva el item
						RevisarRapido(objSpan,false);
						//El formato del padre siempre viene con el número 1 como primer elemento
						//después de la base de datos, ese número hay que eliminarlo, ya que no
						//nos sirve para nada en esta ocasión.
						nPosicion = strPadre.indexOf("_");
						if(nPosicion == -1)
							return;
							
						strPadre = strPadre.substr(nPosicion+1)
						//Ahora se deben buscar los diferentes padres y el item página
						SincronizarHijo(objSpan,strBuscar,strPadre);
						bSalir = true;
					}
				}
			}
			nI++;
			if(nI == nHijos)
				bSalir = true;
		}
	}
}


function SincronizarHijo(objElemento,strBuscarInicio,strPadre)
{
	var objRaiz;
	var nBD;
	var strBuscar;
	var objDivContenedor;
	var nPosicion, nPosicion2;
	var nJ, nJ2, nI, nItem;
	var objItems;
	var objElemento;
	var objHijos, nHijos2;
	var strCodigo = '';
	var nHijos = 0;
	var objSpan;
	var nNuevaBD, nNuevoItem;
	if(objElemento == null)
		return;
	
	//Se obtiene referencia al div contenedor del padre del objeto actual.
	//El objeto que recibe como parámetro siempre es un span clsLabel, obteniendo el 
	//div contenedor, obtenemos referencia a los 'hijos' del item actual
	objDivContenedor = ObtenerElementoHtml(objElemento.parentElement,"DIV","container");
		
	if(objDivContenedor == null)
		return;

	while(strPadre != "")
	{
		//Se arma el código que hay que buscar. Ej: bd_123_5487
		//Donde el primer número indica siempre la base de datos y viene especificado en el parámetro
		//strBuscarInicio
		nPosicion = strPadre.indexOf("_");
			
		if(nPosicion == -1)
		{
			//Si no encuentra '_' significa que strPadre tiene el número de página
			nItem = strPadre;
			strPadre = "";
		}
		else
		{		
			//Se toma el item a buscar y...
			nItem = strPadre.substr(0,nPosicion);
			//Se va recortando la hilera de los items a buscar
			strPadre = strPadre.substr(nPosicion+1)
		}
		strBuscar = strBuscarInicio + "_" + nItem;
		
//		alert(strBuscar);
			
		//Se obtienen los items padres, aquellos divs que son de clase clsItem
		objItems = objDivContenedor.children;
		//Se identifican cuantos son los hijos
		nHijos = objItems.length;

		//Se recorren los hijos del item 'padre' que recibimos como parámetro
		for(nI = 0; nI < nHijos; nI++)
		{
			//Ahora se busca entre todos los hijos, aquel span de clase clsLabel
			objSpan = ObtenerElementoHtml(objItems[nI],"SPAN","label")
			
			if(objSpan != null)
			{
				//Se obtiene el código del span que estoy recorriendo ...
				strCodigo = objSpan.codigo;

				//Si ya encontramos el item, perfecto, hasta aquí llegamos, 
				if(strCodigo == strBuscar)
				{
					//Se selecciona el item
					RevisarRapido(objSpan,false);
					SeleccionarItem(objSpan,false,true);
					//Se cambia de div contenedor, por el item encontrado. Para ir descendiendo en el árbol
					objDivContenedor = ObtenerElementoHtml(objSpan.parentElement,"DIV","container");
				}
				
			}
		}
	}
}


//***************************************************************************************************
//Function:	RevisarRapido
//Objetivo:	Esta función es muy parecida a Revisar, con varias excepciones. Esta función recibe
//			como parámetro un span de tipo label, en el cual se sabe que se le debe cargar su
//			contenido y por lo tanto no es necesario que: se comprima sus hermanos, o carge la
//			página del frame central. Esto porque esta función solamente se debe llamar cuando
//			se sincroniza el árbol con el contenido del escritorio. Por lo tanto, se sabe que
//			la página central ya está cargada y además, estamos comenzando a cargar el árbol 
//			del índice y todo hay que expandirlo. Esta función se hace aparte para mayor eficiencia
//			a la hora de sincronizar. Otra cosa que no hace es desplazarse a sus hijos en caso de
//			que el objeto actual sea una sección.
//Fecha:	Mayo 2002
//Autor:	Christian Sandoval Moya (S-COM)
//***************************************************************************************************
function RevisarRapido(objEvento, bActualizarEscritorio)
{
	var objPadre;			//Objeto padre del anterior
	var objDivOculto;		
	var objIndicador;
	var objHoja;	
	var bCargar = false;	

	//Se obtiene el padre del padre al que pertenece el elemento HTML actual. El mismo puede ser null
	//Para entender esto vea la forma en que está compuesto el ordenamiento de los tag HTML en el indice
	if(objEvento == null)
		return;
		
	objPadre = objEvento.parentElement;
	
	//No nos interesa los elementos que no tienen padre, porque la estructura no debería permitir eso.
	if(objPadre == null)
		return;
	
	//Si el control no tiene una clase definida no nos interesa
	if(objEvento.className == null)
		return;
	
	//Se obtiene el elemento de tipo indicador (el que tiene el + o el -)
	objIndicador = ObtenerElementoHtml(objPadre,"SPAN","indicador");
	//Se obtiene el div que se contiene el resto del arbol (hijos del elemento actual)
	//Este elemento puede estar oculto
	objDivOculto = ObtenerElementoHtml(objPadre,"DIV","container");
	if(objIndicador == null || objDivOculto == null)
		return false;
	
	//Nuevo requerimiento: Cuando el usuario navege por una rama diferente a la que tenía anteriormente
	//se debe 'cerrar' la anterior. Para ello se toman los hermanos del item actual y se comprimen todos
	//En caso de que se trate de item actual no se hace nada. Tampoco hace nada si el item es página
	if(objEvento.TipoItem != "P" && top.fraIzquierdo.fraBarra.m_bCompactar == true)
	{
		//Hay que COMPRIMIR (no ocultar) sus hermanos
		var objHermanos;
		var nHermanos = 0;
		var objIndicadorTemp;
		var objDivTemp;
		var nI = 0;
		//Se obtienen los hermanos del padre del item actual
		objHermanos = ObtenerHermanos(objPadre);
		
		//Nuevo requerimiento: se quiere que los hermanos del que he seleccionado
		//se oculten. Esto con el objetivo de minimizar el tamaño del indice y 
		//dejarlo parecido a lo de MasterLex 2000. En caso de que se quiera que solo
		//la parte de las bases de datos se quita el comentario en la siguiente linea.
		//if(objEvento.TipoItem == "E1")
		{
			bOcultarBDs = true;
		}
		
		//Determinamos cuantos hermanos son
		nHermanos = objHermanos.length;
		for(nI == 0; nI < nHermanos; nI++)
		{
			//Solicitamos el div indicador y el div oculto de cada hermano
			objIndicadorTemp = ObtenerElementoHtml(objHermanos[nI],"SPAN","indicador");
			objDivTemp = ObtenerElementoHtml(objHermanos[nI],"DIV","container");
			//Si el item no es el actual ...
			if(objDivTemp != objDivOculto)
			{
				//se comprime la rama desplegada
				ComprimirRama(objDivTemp, objIndicadorTemp);
				
				//Nuevo requerimiento: se desea que cuando el usuario abra un base de datos
				//se OCULTEN (no solo se compriman) las demas bases.Esto solo aplica al primer nivel del arbol
				//el cual indica las base de datos y se distinguen porque la propiedad TipoItem vale E1.
				if(bOcultarBDs == true)
				{
					if(objIndicador.state == 'Visible')
					{
						//Si el indicador es visible entonces el usuario lo que va a hacer es comprimir la 
						//base de datos y por lo tanto hay que presentar todas las que pueda ver.
						if(objHermanos[nI].className == "clsItemOculto")
						{
							objHermanos[nI].className = "clsItem";
						}
					}
					else
					{
						if(objHermanos[nI].className == "clsItem")
						{
							objHermanos[nI].className = "clsItemOculto";
						}
					}
				}
			}
		}
	}
	//Fin de modicacion
	
	//Se revisa si el elemento es simplemente una hoja
	objHoja = ObtenerElementoHtml(objIndicador,"SPAN","hoja")
	if(objHoja == null)
	{

		//Si el indicador especifica que el div contenedor está oculto, entonces no hay
		//que volver a cargar el xml
		if(objIndicador.state == 'NoCargado')
			bCargar = true;

		//Se expande o se comprime el nodo. No carga XML, solo hace visible u oculta div contenedor
		//Además de cambiar el '+' por el '-' o viceversa
		if(objDivOculto.className == "hide")
		{
			if(ExpandirNodo(objDivOculto,objIndicador) == false)
				return false;
			else
			{
				//Si el archivo ya está cargado entonces solamente se muestra
				if(bCargar == true)
				{
					//Cargar el archivo XML y reemplazar el div con los nuevos datos
					CargarXML(objEvento, objIndicador, objDivOculto)
				}
			}
		}
		else
			ComprimirRama(objDivOculto,objIndicador);
	}

	if(objEvento.type == 'label')
	{
		//Se actualiza el objeto actual, se le pasa la misma variable que se recibe como segundo parámetro
		//que indica si debe refrescar la página del frame central o no.
		SeleccionarItem(objEvento,bActualizarEscritorio,true);
		
	}
}
