function getAbsOffsetLeft(ele) {
  var offset = 0;
  var sl = (window.pageXOffset ? window.pageXOffset : document.body.scrollLeft);
  do { offset += ele.offsetLeft; if (ele.style.position=='fixed') { offset+=sl }; ele = ele.offsetParent; } while (ele!=null)
  return offset;
}

function hasClass(el, className) {
  return (" " + el.className + " ").indexOf(className) > -1;
}

function getBorders(element) {
  var ltrb = ["Left","Top","Right","Bottom"];
  var result = {};
  for (var i in ltrb) {
    if (element.currentStyle)
      var value = parseInt(element.currentStyle["border"+ltrb[i]+"Width"]);
    else if (window.getComputedStyle)
      var value = parseInt(window.getComputedStyle(element, "").getPropertyValue("border-"+ltrb[i].toLowerCase()+"-width"));
    else
      var value = parseInt(element.style["border"+ltrb[i]]);
    result[ltrb[i].toLowerCase()] = isNaN(value) ? 0 : value;
  }
  return result;
}

var closeDelay = 750;
var closeDelayTimer = null;
var closeItem = null;

function MenuItem(idOrElement, parent) {
  var menuItem = this;
  this.type = "menu-item";
  this.subMenu;
  this.init(idOrElement, parent);
  if (this.subMenu) {
    this.element.onmouseover = function() {
      if (closeDelayTimer) window.clearTimeout(closeDelayTimer);
      menuItem.subMenu.open(); 
    }
  } else {
    this.element.onmouseover = function() {
      menuItem.parentMenu.closeAll();
    }
  }
  var linkTag = this.element.getElementsByTagName("A")[0];
  if (linkTag) linkTag.onfocus = this.element.onmouseover;

  if (this.subMenu) {
    this.element.onmouseout = function() {
      if (closeDelayTimer) window.clearTimeout(closeDelayTimer); 
      closeItem = menuItem;
      closeDelayTimer = window.setTimeout("closeItem.subMenu.close()", closeDelay); 
    }
  }
}

MenuItem.prototype = Menu.prototype;

MenuItem.prototype.closeItem = function(trigger) {
  if (this.subMenu) { 
    if (this.subMenu != trigger) this.subMenu.close(); 
  }
}

MenuItem.prototype.openItem = function() {
  if (this.subMenu) { this.subMenu.open(); }
}

function Menu(idOrElement, parent) {
  var menu = this;
  this.type = "menu";
  this.menuItems = [];
  this.init(idOrElement, parent);
  if (hasClass(this.element, "dropdown")) this.menuType = "dropdown";
  else if (hasClass(this.element, "flyout")) this.menuType = "flyout";
  else if (hasClass(this.element, "horizontal")) this.menuType = "horizontal";
  else this.menuType = "standard";
}

Menu.prototype.init = function(idOrElement, parent) {
  this.element = (typeof idOrElement == "string") ? document.getElementById(idOrElement) : idOrElement;
  this.parent = parent;
  this.parentMenu = (this.type == "menu") ? ((parent) ? parent.parent : null) : parent;
  this.id = this.element.id;

  var childNodes = this.element.childNodes;
  if (childNodes == null) return;
  
  for (var i = 0; i < childNodes.length; i++) {
    var node = childNodes[i];
    if (node.nodeType == 1) {
      if (this.type == "menu") {
        if (node.tagName.toLowerCase() == "li") {
          this.menuItems.push(new MenuItem(node, this));
        }
        
      } else {
        if (node.tagName.toLowerCase() == "ul") {
          this.subMenu = new Menu(node, this);
        }
      }
    }
  }
}

Menu.prototype.open = function() {
  this.parentMenu.closeAll(this);
  this.element.style.visibility = "visible";
  if (this.menuType == "dropdown") {
    this.element.style.top = this.parent.element.offsetTop + this.parent.element.offsetHeight + "px";
    this.element.style.left = this.parent.element.offsetLeft + 168 + "px";
  } else if (this.menuType == "flyout") {
    var parentMenuBorders = getBorders(this.parentMenu.element);
    var thisBorders = getBorders(this.element);
    if ((getAbsOffsetLeft(this.parentMenu.element) + this.parentMenu.element.offsetWidth + this.element.offsetWidth + 20) > (window.innerWidth ? window.innerWidth : document.body.offsetWidth))
      this.element.style.left = - this.element.offsetWidth + "px";
    else 
      this.element.style.left = this.parentMenu.element.offsetWidth - parentMenuBorders["left"] - thisBorders["left"] + "px";      
    this.element.style.top = this.parent.element.offsetTop - parentMenuBorders["top"] + "px";
  }
}

Menu.prototype.close = function() {
  this.element.style.visibility = "hidden";
  this.closeAll();
}

Menu.prototype.closeAll = function(trigger) {
  for (var i in this.menuItems) { 
    this.menuItems[i].closeItem(trigger);
  }
}

function initMenu() {
  var menu = new Menu('menu-root');
}

onload = initMenu;