﻿/* 
	menuDesplegable.js
	Héctor Paúl Cervera García
	Digitápolis
	Onofre Producciones
	Julio 2008
	
	
	Contenido: 
	Clase ElementoMenu 
		Resumen: Cada uno de los conceptos representados en el menu dinámico
			* nombre: el texto que saldra por pantalla
			* enlace: el enlace al que irá, en caso de ser clicable
			* clase: clase CSS del elemento
			* clicable: si se puede hacer clic sobre él para ir a algún enlace, o bien servirá para abrir otro nivel por ejemplo sin permitir el clic
			* menuHijos: objeto de clase Menu para un posible subMenu que cuelgue de éste elementoMenu
			* eventoOver: acción a ejecutar con onMouseOver. Por defecto mira si tiene un menuHijos y lo construye.
			
			[*] construirElementoMenu: crea un objeto de etiqueta LI con los datos de la clase, si tuviera menús dependientes
				los construiría, y devuelve el objeto LI
	
	Clase Menu 
		Resumen: El menú dinámico creado, con posibilidad de n niveles
			* id: el id del menú generado (del objeto de etiqueta UL)
			* clase: clase CSS del UL
			* elementos: vector de objetos de tipo ElementoMenu de los que se vaya a componer el menú
			* idSoporte: id del objeto DOM dentro del cual se vaya a generar el menú
			* invocador: objeto DOM que activa este menú
			
			[*] construirMenu: fabrica el objeto UL con los atributos de la clase y sus elementos correspondientes, 
				vacía aquellos elementos UL que hubiera previamente en el objeto DOM cuyo id es idSoporte,
				los muestra por pantalla en dicho objeto DOM, y le añade la acción de mouseOut
				
				¡ATENCIÓN! la acción mouseOut que hay aquí deberá variar en funcion de la web
			[*] generarMenu: fabrica el objeto UL con los atributos de la clase y sus elementos correspondientes
			
BIS -> ¡ATENCIÓN! la acción mouseOut que hay aquí deberá variar en funcion de la web
	
*/
	

	
var menuActivo = null;


function ElementoMenu( nombre, enlace, clase, clicable, menuHijos, eventoOver )
{
	this.nombre = nombre;
	this.enlace = enlace;
	this.clase = clase;
	this.clicable = clicable || true;
	this.menuHijos = menuHijos || null;
	this.eventoOver = eventoOver || null;
	
	this.construirElementoMenu = function construirElementoMenu( )
		{
			var li = document.createElement( "li" );
			//li.setAttribute( "class", this.clase );
			li.className = this.clase;
			var texto = document.createTextNode( this.nombre );
			
			if( clicable == true )
			{
				var a = document.createElement("a");
				a.setAttribute( "href", this.enlace );
				a.setAttribute( "title", this.enlace );
				a.appendChild( texto );
				li.appendChild( a );
			}
			else
				li.appendChild( texto );
			
			if( this.eventoOver != null && li != null )
				addEvent( li, "mouseover", this.eventoOver );
			else if( this.menuHijos != null && li != null )
				{
					addEvent( li, "mouseover", this.menuHijos.construirMenu() );
				}
			
			return li;
		};
	
}


function Menu( id, clase, elementos, idSoporte, invocador, separador )
{
	this.id = id;
	this.clase = clase;
	this.elementos = elementos;
	this.idSoporte = idSoporte;
	this.invocador = invocador || null;
	this.separador = separador || null;
	
	this.construirMenu = function construirMenu()
		{
			if( this.idSoporte != null )
			{
				var soporte = document.getElementById( idSoporte );
				if( soporte != null )
				{
					// limpiamos el elemento soporte
					//alert( "soporte no es nulo");
					var hijosAntiguos = soporte.childNodes;
					var hijo = null;
					for(var i = hijosAntiguos.length - 1; i > -1; i-- )
					{
						hijo = hijosAntiguos[ i ];
						if( hijo.tagName == "UL" )
							soporte.removeChild( hijo );
					}
					if( soporte.style.visibility == "hidden" )
						soporte.style.visibility = "visible";
					// insertamos el nuevo menú
					var menu = this.generarMenu();
					soporte.insertBefore( menu, soporte.firstChild );
					var padre = null;
					if( this.invocador != null )
					{
						//var invocador = this.invocador;
						var padre = cogerPadre( this.invocador );
					}
					
					// Función específica de la web digitápolis
					var eventoSoporte = function(e)
					{ 
						// Comprobación de que el evento se ejecute realmente dejando la capa del menú
						// La causa: la gestión hacia afuera (bubble) de eventos
						// Sacado de http://www.quirksmode.org/js/events_mouse.html
						
						// tg es el elemento de donde viene el puntero
						// reltg es el elemento a donde va
						if (!e) e = window.event;
						var tg = (window.event) ? e.srcElement : e.target;
						//var soporteId = soporte.id;
						while (tg != soporte && tg.nodeName != 'BODY')
							tg = cogerPadre(tg);
						
						if( tg.nodeName == 'BODY' ) return;
						
						var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
					
						if( padre != null )
						{
							while (reltg != tg && reltg.nodeName != 'BODY' && reltg != padre)
								reltg = cogerPadre(reltg);
							if (reltg == padre ) return;
						}
						else
							while (reltg != tg && reltg.nodeName != 'BODY')
								reltg = cogerPadre(reltg);
						
						if (reltg == tg) return;
						
						
						// Si llega hasta aquí, es correcto
						if( menuActivo != null )
						{								
							menuActivo.construirMenu();
						}
						else
						{
							if( soporte != null )
								soporte.style.visibility = "hidden";
						}
						
						e.cancelBubble = true;
						if (e.stopPropagation)	{e.stopPropagation();}
					} ;
					//removeEvent( soporte, "mouseout", eventoSoporte );
					//addEvent( soporte, "mouseout", eventoSoporte );
					soporte.onmouseout = eventoSoporte;
					
					// Controla que si sales del padre (menú verde) y está activado el submenú (morado), 
					// desaparezca éste último si no había menú inicial (menuActivo por defecto)
					if( padre != null )
					{
						var eventoPadre = function(e)
							{ 
								if (!e) e = window.event;
								var tg = (window.event) ? e.srcElement : e.target;
								
								var padreId = padre.id;
								while (tg.id != padreId && tg.nodeName != 'BODY')
									tg = cogerPadre(tg);
								
								if( tg.nodeName == 'BODY' ) return;
								
								var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
								
								while (reltg != tg && reltg.nodeName != 'BODY' && reltg != soporte)
										reltg = cogerPadre(reltg);
								
								if (reltg == tg || reltg == soporte ) return;
								
								
								
								if( menuActivo != null )
								{
									menuActivo.construirMenu();
								}
								else
								{
									if( soporte != null)
										soporte.style.visibility = "hidden";
								}
								
								e.cancelBubble = true;
								if (e.stopPropagation) e.stopPropagation();
								
								
								
							};
						padre.onmouseout = eventoPadre;
						//removeEvent( padre, "mouseout", eventoPadre);
						//addEvent( padre, "mouseout", eventoPadre);
					}
				}
				
			}
			
		};
	
	
	this.generarMenu = function generarMenu()
		{
			var ul = document.createElement( "ul" );
			ul.setAttribute("id", this.id);
			//ul.setAttribute("class", this.clase);
			ul.className = this.clase;
			
			for( i = 0; i < this.elementos.length; i++ )
			{
				var elementoMenu = this.elementos[ i ].construirElementoMenu( );
				ul.appendChild( elementoMenu );
				
				if( this.separador != null && i < this.elementos.length - 1)
				{	
					var li = document.createElement( "li" );
					li.appendChild( document.createTextNode( this.separador ) );
					ul.appendChild( li );
				}
				
			}
			return ul;
		};
}


