// 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(){
// document.getElementById('MainContainer').style.zIndex=100;
 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");
 }
// document.getElementById('MainContainer').style.zIndex=0;
}
// 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";
 }
}