//crossbrowser helper
function getElem(name) {
  if (document.all) return document.all(name);
  else return document.getElementById(name);
}

//menu item abstraction
function MenuItem(oHTMLEntity, sDisplayStyle) {
  this.displayStyle = sDisplayStyle;
  this.HTMLEntity = oHTMLEntity;
  this.hideStyle = 'display';
  this.parent = null;
}

//browser dependent!!!! (hope it's fine)
MenuItem.prototype.show = function () {
  if (this.hideStyle == 'display') {
    this.HTMLEntity.style.display = this.displayStyle;
  } else {
    this.HTMLEntity.style.visibility = 'visible';
  }
}

//browser dependent!!!! (hope it's fine)
MenuItem.prototype.hide = function () {
  if (this.hideStyle == 'display') {
    this.HTMLEntity.style.display = 'none';
  } else {
    this.HTMLEntity.style.visibility = 'hidden';
  }
}

//menu abstraction
function Menu(sMyName, oHTMLEntity, sDisplayStyle, sContainerDisplayStyle) {
  this.myName = sMyName;
  this.HTMLEntity = oHTMLEntity;
  if (this.HTMLEntity != null) {
    this.HTMLEntity.onmouseover = new Function ('e', this.myName + '.onMouseOver(e);');
    this.HTMLEntity.onmouseout =  new Function ('e', this.myName + '.onMouseOut(e);');
  }
  this.displayStyle = sDisplayStyle;
  this.items = new Array();
  this.subMenuContainerHTMLEntity = null;
  this.containerDisplayStyle = sContainerDisplayStyle;
  this.containerXDelta = null;
  this.containerYDelta = null;
  this.mouseOverShowDelay = null;
  this.hideTimer = null;
  this.showTimer = null;
  this.subMenuShown = false;
  this.hideStyle = 'display';
  this.parent = null;
  this.persistentSubMenu = false;
  this.onmouseover = null;
  this.onmouseout = null;
}

Menu.prototype.setContainer = function(oContainer) {
  this.subMenuContainerHTMLEntity = oContainer;
  this.subMenuContainerHTMLEntity.onmouseover = new Function ('e', this.myName + '.onMouseOver(e);');
  this.subMenuContainerHTMLEntity.onmouseout =  new Function ('e', this.myName + '.onMouseOut(e);');
}

Menu.prototype.addItem = function (oMenuItem) {
  ni = this.items.length;
  this.items[ni] = oMenuItem;
  this.items[ni].parent = this;
  return this.items[ni];
}

Menu.prototype.initialize = function () {
  ini = this.items.length;

  for (ii = 0; ii < ini; ii++) {
    var iitem = this.items[ii];
    if (iitem.hideSubMenu != null)
      iitem.hideSubMenu();
  }
}

Menu.prototype.setSubMenuPersistent = function (yes) {
  this.persistentSubMenu = yes;
  this.subMenuShown = yes;
}

//browser dependent... (hope it's fine)
Menu.prototype.show  = function () {
  if (this.hideStyle == 'display') {
    this.HTMLEntity.style.display = this.displayStyle;
  } else {
    this.HTMLEntity.style.visibility = 'visible';
  }
  //when i show menu, i don't show its submenu...
  if (!this.persistentSubMenu) this.hideSubMenu();
}

//browser dependent... (hope it's fine)
Menu.prototype.hide = function () {
  if (this.hideStyle == 'display') {
    this.HTMLEntity.style.display = 'none';
  } else {
    this.HTMLEntity.style.visibility = 'hidden';
  }

  this.hideSubMenu();
}

//browser dependent (hope it's fine)
Menu.prototype.showSubMenu = function () {

  if (this.onMouseOverShowDelay == null) {
    //hide my siblings
    if (this.parent != null) {
      len = this.parent.items.length;
      for (psi = 0; psi < len; psi++) {
        var pitem = this.parent.items[psi];
        if (pitem.hideSubMenu != null && !pitem.persistentSubMenu) pitem.hideSubMenu();
      }
    }
  }

  //show my direct children
  slen = this.items.length;
  for (si = 0; si < slen; si++) {
    var sitem = this.items[si];
    sitem.show();
  }

  if (!this.subMenuShown) {
    if (this.containerXDelta != null)
      this.subMenuContainerHTMLEntity.style.left = this.containerXDelta + 'px';

    if (this.containerYDelta != null)
      this.subMenuContainerHTMLEntity.style.top = this.containerYDelta + 'px';

    if (this.hideStyle == 'display') {
      this.subMenuContainerHTMLEntity.style.display = this.containerDisplayStyle;
    } else {
      this.subMenuContainerHTMLEntity.style.visibility = 'visible';
    }

    this.subMenuShown = true;
  }
}

Menu.prototype.hideSubMenu = function () {
  hlen = this.items.length;
  for(hi = 0; hi < hlen; hi++) {
    var hitem = this.items[hi];
    if (!hitem.persistentSubMenu) hitem.hide();
  }

  if (this.hideStyle == 'display') {
    this.subMenuContainerHTMLEntity.style.display = 'none';
  } else {
    this.subMenuContainerHTMLEntity.style.visibility = 'hidden';
  }
    
  this.subMenuShown = false;
}

Menu.prototype.onMouseOver = function(e) {
  //let's cancel that bubble!!!
  if (e != null && e != 'undefined') {
    e.stopPropagation();
  }

  if (document.all) {
    window.event.cancelBubble = true;
  }

  clearTimeout(this.hideTimer);
  this.hideTimer = null;

  var p = this.parent;
  while (p != null) {
    clearTimeout(p.hideTimer);
    p.hideTimer = null;
    p = p.parent;
  }

  clearTimeout(this.showTimer);
  if (this.mouseOverShowDelay == null || this.persistentSubMenu) return;

  //i "share" onmouseovers
  var p = this;
  while (p != null) {
    if (p.onmouseover != null)
      eval(p.onmouseover);
    p = p.parent;
  }
  this.showTimer = setTimeout(this.myName + '.showSubMenu();', this.mouseOverShowDelay);
}

Menu.prototype.onMouseOut = function (e) {
  clearTimeout(this.showTimer);
  this.showTimer = null;
  clearTimeout(this.hideTimer);
  if (this.mouseOverShowDelay == null || this.persistentSubMenu) return;

    if (this.onmouseout != null)
      eval(this.onmouseout);

  this.hideTimer = setTimeout(this.myName + '.hideSubMenu();', this.mouseOverShowDelay);

  //hide all parent menus
  var p = this.parent;
  while (p != null) {
    p.onMouseOut(e);
    p = p.parent;
  }

  if (e != null && e != 'undefined') {
    e.stopPropagation();
  }

  if (document.all) {
    window.event.cancelBubble = true;
  }
}

Menu.prototype.onClick = function (e) {
  clearTimeout(this.hideTimer);
  this.hideTimer = null;
  clearTimeout(this.showTimer);
  this.showTimer = null;

  if (!this.subMenuShown)
    this.showSubMenu();
  else this.hideSubMenu();
}
