// Author: Joseba Alonso
// Reference : http://www.sidedev.net/jsoop/dropdowns
// Version: 1.0 beta 2
// LastChange: 1-2-2005
//
// Version beta 2 changes:
// - Ahora se utilizan 2 clases una para el menu y otra para los items. Esto contamina menos el objeto document y es las claro.
// - Parametros de constructor
// - Comportamiento en click o en rollover
// - Propiedad velocidad
// - Navegacion basica con el teclado
// - Ahora funciona tambien con ul

//  [TODO]
//  Bug: A veces el menu se despliega de golpe
//	Bug: Entornos no-css si-js
// 	Feature: Manejo zIndex
//  Feature: Navegacion con teclado mas avanzada (cursor keys)
//  Feature: Namespace?

/****************************************
*
* Enum DropDownBehavior
* 
****************************************/

var DropDownBehavior = new Object();
DropDownBehavior.click = 1;
DropDownBehavior.rollover = 2;

/****************************************
*
* Clase DropDownMenu
* 
****************************************/

function DropDownMenu(velocidad,behavior){
	this.velocidad = (velocidad) ? velocidad : 10;
	this.behavior = (behavior) ? behavior : DropDownBehavior.click;
	this.menuOffsetTop = 0 // ajuste superior con la altura del menu
	this.menuOffsetBottom = 0 // ajuste inferior con la altura del menu
	var minHeight =  0;
	var maxHeight = 0;
	// Inicializacion
	this.activeMenu = null;
	this.easingEc = null;
	this.activos = new Array();
	this.submenus = new Array();
	
	for(var i=0;i<this.childNodes.length;i++){
		var node = this.childNodes[i]
		if(node.nodeName.toLowerCase()=="li"){
			this.submenus.push(node);
			Object.registerClass(node,DropDownMenuItem,[this]);
			if(node.subMenu && node.subMenu.clientHeight > maxHeight){
				maxHeight = node.subMenu.clientHeight;
			}
			if(node.boton && node.boton.clientHeight > minHeight){
				minHeight = node.boton.clientHeight;
			}
		}
	}
	if(!this.submenus || this.submenus.length==0){
		alert("No se pudo aplicar la clase porque el elemento menu no tiene la estructura adecuada.");
		return;
	}
	this.menuClosedHeight = 2+minHeight+"px"; 
	this.menuOpenedHeight = (5+maxHeight+minHeight+this.menuOffsetTop)+"px";
	this.style.height = this.menuClosedHeight;
}
// Interface
DropDownMenu.prototype.setBehavior = function(newBehavior){
	for(var i=0;i<this.submenus.length;i++){
		this.submenus[i].attachEvents(newBehavior);
		//this.submenus[i].hide(true);
	}
}
		
DropDownMenu.prototype.setActive = function(menuitem){
	this.activeMenu = menuitem;
	this.activos.push(menuitem);
}
DropDownMenu.prototype.setInactive = function(menuitem){
	for(var i=0;i<this.activos.length;i++){
		if(this.activos[i]==menuitem){
			this.activos.splice(i,1);
			break;
		}
	}
	this.checkActive();
}
DropDownMenu.prototype.activate = function(menu){
	if(menu.show){
		menu.show();
	}
	else if(!isNaN(menu)){
		this.submenus[menu].show();
	}
}
DropDownMenu.prototype.deactivate = function(rapido){
	if(this.activeMenu){
		this.activeMenu.hide(rapido);
		this.activeMenu = null;
	}
}
DropDownMenu.prototype.checkActive = function(){
	if(this.activos.length == 0){
		this.style.height = this.menuClosedHeight;
	}
}


/****************************************
*
* Clase DropDownMenuItem
* 
****************************************/

function DropDownMenuItem(menu){
	this.owner = menu;
	this.desplegado = false;
	this.subMenu = this.__findChild("ol");
	if(!this.subMenu)this.subMenu = this.__findChild("ul");
	if(!this.subMenu)return;
	this.boton = this.__findChild("a");
	this.attachEvents(menu.behavior);
	this.timeout = null;
	this.actual = -this.subMenu.clientHeight-5;
	this.subMenu.style.marginTop = this.actual+"px";
}
// Public interface
DropDownMenuItem.prototype.attachEvents = function(behavior){
	if(!this.subMenu)return
	this.boton.onfocus = null;
	this.boton.onblur = null;
	this.boton.onmouseover = null;
	this.boton.onmouseout = null;
	this.boton.onclick = null;
	this.subMenu.onmouseover = null;
	this.subMenu.onmouseout = null;
	if(behavior == DropDownBehavior.rollover){
		this.boton.onfocus = this.boton.onmouseover = function(){
			this.parentNode.show();
		}
		this.subMenu.onmouseover = function(){
			clearTimeout(this.parentNode.timeout);
		}
			
		this.subMenu.onmouseout = this.boton.onmouseout = this.boton.onblur = function(){
			var scope = this;
			clearTimeout(this.parentNode.timeout);
			this.parentNode.timeout = setTimeout(function(){scope.parentNode.hide()},200);
		}
	}
	else{
		this.boton.onclick = function(e){
			if(!e)e = event;
			e.cancelBubble = true;
			if(this.parentNode.desplegado){
				this.parentNode.hide();
			}
			else{
				this.parentNode.show();
			}
			return false;
		}
	}
	var ref = this;
	document.onclick = function(){
		ref.owner.deactivate(true);
	}
}
DropDownMenuItem.prototype.show = function(){
	if(this.desplegado)return;
	this.owner.style.height = this.owner.menuOpenedHeight;
	if(this.owner.activeMenu != this)this.owner.deactivate();
	this.owner.setActive(this);
	this.subMenu.style.visibility = "visible";
	this.desplegado = true;
	this._init = this.actual
	this._finaly=-this._init+this.owner.menuOffsetTop;
	this._t = 0;
	this._ec = (this.owner.easingEc) ? this.owner.easingEc : this.easeInOutSine;
	// [TODO] No estoy demasiado seguro de que este calculo sea correcto
	this.tiempo = Math.max(10,Math.abs(this._finaly/this.owner.velocidad));
	FrameServer.getInstance().addListener(this,"time");
}
DropDownMenuItem.prototype.hide = function(rapido){
	if(rapido){
		FrameServer.getInstance().removeListener(this,"time");
		this.actual =-this.subMenu.clientHeight-this.boton.clientHeight-this.owner.menuOffsetTop+this._init+18;
		this.subMenu.style.marginTop = this.actual+"px";
		this.subMenu.style.visibility = "hidden";
		this.owner.setInactive(this);
		this.desplegado = false;
	}
	else{
		if(!this.desplegado)return;
		this.desplegado = false;
		this._init = this.actual;
		// porque, porque, porque 18
		this._finaly=-this.subMenu.clientHeight-this.boton.clientHeight-this.owner.menuOffsetTop+this._init+18;
		this._t = 0;
		this._ec = (this.owner.easingEc) ? this.owner.easingEc : this.easeInOutSine;
		FrameServer.getInstance().addListener(this,"time");
	}
}
// Private methods
DropDownMenuItem.prototype.easeInOutSine = function (t, b, c, d) {
    return c/2 * (1 - Math.cos(t/d * Math.PI)) + b;
};
DropDownMenuItem.prototype.__findChild = function(tagname){
	var hijos = this.childNodes;
	if(hijos){
		for(var i=0;i<hijos.length;i++){
			if(hijos[i].nodeName && hijos[i].nodeName.toLowerCase() == tagname){
				return hijos[i];
			}
		}
	}
	return null;
}
DropDownMenuItem.prototype.time = function(){
	this.actual = this._ec(this._t++,this._init,this._finaly,this.tiempo);
	if(this._t>this.tiempo){
		FrameServer.getInstance().removeListener(this,"time");
		this.actual = (this._init+this._finaly);
		this.subMenu.style["marginTop"] = this.actual+"px";
		if(!this.desplegado){
			this.subMenu.style.visibility = "hidden";
			this.owner.setInactive(this);
		}
		else{
		}
	}
	else{
		this.subMenu.style["marginTop"] = this.actual+"px";
	}
}	