/*
21 Octubre de 2009:

La nueva "clase" ahora incluye un manejador del "evento" que permite evitar
o permitir la propagación del evento al elemento padre.

Al final del documento hay un ejemplo que tendríamos que eliminar para la 
implementación. Los comentarios deberían dejar claro el resto.
*/

/*
Esta es la clase principal: el asignador de eventos... Contiene un array de
eventos que usaremos para limpiar, un par de referencias a si mismo, funciones
y la clase "bloque_evento", que comentaremos cuando lleguemos
*/

function Asignador_eventos()
{
	this.asignador=Array();	//Un array de bloque_eventos
	var aquello=this;
	var padre_asignador=this;

	//Esta es la interfaz principal para poner un evento. En el ejemplo se puede ver claramente su uso.
	this.poner_evento=function(p_elemento, p_tipo, p_funcion, p_propagacion, p_ambito)
	{		
		if(p_elemento)
		{
			var temp=new aquello.Bloque_eventos(p_elemento, p_tipo, p_funcion, p_propagacion, p_ambito);		
			aquello.asignador.push(temp);	
		}
	}

	//Se limpia uno sólo...
	this.limpiar_evento=function(indice)
	{
		aquello.asignador[indice].limpiar();
		aquello.asignador.splice(indice, 1);
	}

	//Esta es la función a la que llamaríamos al terminar con la acción de la página, para liberar los eventos.
	this.limpiar_eventos=function()
	{
		var x=0;
		for(x; x<aquello.asignador.length; x++)
		{
			aquello.asignador[x].limpiar();
			aquello.asignador.splice(x, 1);
		}
	}

	//Esta es una función auxiliar que nos permite evitar que los eventos se propaguen al padre del llamador.
	this.detener_propagacion=function(evento)
	{
		if(!evento)	//Para Explorer: Si no hay evento se maneja con window.Event.
		{
			var evento=window.event;
			evento.cancelBubble=true;	//También para para explorer....
		}
	
		if(evento.stopPropagation) 	//Y ahora para fireFox...
		{
			evento.stopPropagation();
		}
	}

	this.localizar_elemento=function(elemento)
	{
		var resultado=-1;
		var i=0;

		for(i; i<aquello.asignador.length; i++)
		{
			if(elemento==aquello.asignador[i].elemento)
			{
				resultado=i;
				break;
			}
		}

		return resultado;
	}

	/*
	Esta es la clase Bloque_eventos, que contiene todo lo que tiene que ver
	con el manejo del evento propiamente dicho... Se accede a ella mediante
	interfaces de la clase padre y mediante ella relacionamos elementos 
	del documento con funciones
	*/
	this.Bloque_eventos=function(p_elemento, p_tipo, p_funcion, p_propagacion, p_ambito)
	{
		this.elemento=p_elemento;
		this.tipo=p_tipo;
		this.funcion=p_funcion;
		this.propagar_eventos=p_propagacion;
		this.ambito=p_ambito ? p_ambito : null;		

		var aquello=this;

		this.asignar=function()
		{
			//Primero generamos una función: será la misma para todos los eventos.
			var funcion_interna=function(event)
			{
				//Si vamos a propagar eventos....
				if(!aquello.propagar_eventos) 
				{
					padre_asignador.detener_propagacion(event);
				}

				//Finalmente ponemos la función de turno...

				if(aquello.ambito)
				{			
					aquello.funcion.call(aquello.ambito);
				}
				else
				{
					aquello.funcion();
				}

				if(!aquello.propagar_eventos)
				{
					return false; //Evitamos la propagación para un link
				}
			}		

			//Ahora si que asignamos el evento.
			switch(aquello.tipo)
			{
				case 'onclick':	aquello.elemento.onclick=funcion_interna; break;
				case 'onmouseover': aquello.elemento.onmouseover=funcion_interna; break;
				case 'onmouseout': aquello.elemento.onmouseout=funcion_interna; break;
				case 'onchange': aquello.elemento.onchange=funcion_interna; break;						
				default: alert('Evento desconocido'); break;
			}	
		}

		this.limpiar=function()
		{			
			switch(aquello.tipo)
			{
				case 'onclick': aquello.elemento.onclick=null; break;
				case 'onmouseover': aquello.elemento.onmouseover=null; break;
				case 'onmouseout': aquello.elemento.onmouseout=null; break;
				case 'onchange': aquello.elemento.onchange=null; break;						
				default: alert('Evento desconocido'); break;

				aquello.funcion=null;
				aquello.tipo=null;
			}	
		}

		this.asignar();	//Cuando se crea un bloque de evento se hace con new, haciendo que esta función se ejecute.
	}
}

