/* Javascript by Daniel Cohen Gindi (c) danielgindi@gmail.com 054-5655765 */
/* Version: 2010-06-27 */

/* requires: ajax.js */

function Mlulm() {
  var thisObj = this;
  this.init.apply(this, arguments);
  return this;
}
Mlulm.prototype = {
  init: function(elUl, params) {
    if (!document.isDomLoaded && (window.ie && !(/loaded|complete/.test(document.readyState)))) {
      var thisObj = this;
      var args = arguments;
      if (window.ie) ajax.events.register(window, 'load', function() { thisObj.init.apply(thisObj, args) });
      else ajax.events.register(document, 'dom:onLoad', function() { thisObj.init.apply(thisObj, args) });
      return;
    }
    if (typeof elUl == typeof '') elUl = document.getElementById(elUl);
    if (!elUl) return;

    if (!params) params = {};

    this.itemTag = (params.itemTag || 'li').toLowerCase();
    this.menuTag = (params.menuTag || 'ul').toLowerCase();
    this.itemClass = params.itemClass;
    this.menuClass = params.menuClass;
    this.timeOut = params.timeOut;
    this.absolutePositions = params.absolutePositions || [];

    this._element = elUl;

    this._prepareMenuElement(this._element, null, null, -1);
  },
  _prepareMenuElement: function(elMenu, elParentMenu, elParentMenuItem, level) {
    if (!elMenu) return;
    elMenu.$parentMenu = elParentMenu || null;
    elMenu.$parentMenuItem = elParentMenuItem || null;
    elMenu.$menuLevel = level == undefined ? null : level;
    if (elMenu.$menuLevel != -1 &&
      this.absolutePositions[elMenu.$menuLevel]) {
      var posParams = this.absolutePositions[elMenu.$menuLevel];
      if (posParams.mode == 'clickable') {
        if (posParams.classHover && elParentMenuItem.className == posParams.classHover) {
          if (!elParentMenu.$curOpen) elParentMenu.$curOpen = elParentMenuItem;
        }
        else if (posParams.classHoverAdd) {
          var classes = elParentMenuItem.className.split(' ');
          if (classes.contains(posParams.classHoverAdd)) {
            elParentMenuItem.$originalClassName = classes.remove(posParams.classHoverAdd).join(' ');
            if (!elParentMenu.$curOpen) elParentMenu.$curOpen = elParentMenuItem;
            else elParentMenuItem.className = elParentMenuItem.$originalClassName;
          }
        }
        if (elParentMenu.$curOpen != elParentMenuItem) elMenu.style.display = 'none';
      }
      else elMenu.style.display = 'none';
      if (posParams.position && posParams.position == 'absolute') {
        var parentNode = elMenu.parentNode;
        parentNode.removeChild(elMenu);
        document.body.appendChild(elMenu);
      }
    }

    var items = Array.fromElement(elMenu.getElementsByTagName(this.itemTag));

    var subMenus = null;
    var subMenu = null;
    items.iterate(function(item, idx) {
      var thisObj = this;
      if (this.itemClass &&
        (
         (this.itemClass.length == 0 && item.className && item.className.length > 0)
         || (this.itemClass.length > 0 && !item.className.split(' ').contains(this.itemClass))
        )
         ) return;

      subMenu = null;
      subMenus = item.getElementsByTagName(this.menuTag);
      if (subMenus && subMenus.length > 0) {
        subMenu = subMenus[0];
        if (this.menuClass && !subMenu.className.split(' ').contains(this.menuClass))
          subMenu = null;
      }

      if (subMenu == null) {
        if (items.length>idx+1 
            && (this.menuClass && items[idx+1].className.split(' ').contains(this.menuClass))
            && (this.menuTag == this.itemTag))
            subMenu=items[idx+1];
      }
      
      if (subMenu) {
        var menuLevel = level + 1;
        var posParams = this.absolutePositions[menuLevel] || null;
        this._prepareMenuElement(subMenu, elMenu, item, menuLevel);
        item.$subMenu = subMenu;
        item.$parentMenu = elMenu;

        if (posParams.mode == 'clickable') {
          ajax.events.register(item, 'click', function(e) { thisObj._FItemClick(item, e || event); });
        }
        else {
          ajax.events.register(item, 'mouseover', function(e) { thisObj._FItemMouseOver(item, e || event); });
          ajax.events.register(item, 'mouseout', function(e) { thisObj._FItemMouseOut(item, e || event); });
          ajax.events.register(subMenu, 'mouseover', function(e) { thisObj._FMenuMouseOver(item.$subMenu, e || event); });
          ajax.events.register(subMenu, 'mouseout', function(e) { thisObj._FMenuMouseOut(item.$subMenu, e || event); });
        }
      }
    }, this);
  },
  _FItemMouseOver: function(item, evt) {
    var event = new ajax.events.Event(evt);
    if (item.$parentMenu.$closing) item.$parentMenu.$closing = false;
    if (event.relatedTarget == item || ajax.layout.elementHasChild(item, event.relatedTarget)) return;
    event.stop();
    this._ShowMenu(item);
    this._NotifyParentMenuOver(item.$parentMenu);
  },
  _FItemMouseOut: function(item, evt) {
    var event = new ajax.events.Event(evt);
    if (event.relatedTarget == item || ajax.layout.elementHasChild(item, event.relatedTarget)) return;
    event.stop();
    item.$subMenu.$closing = true;
    var thisObj = this;
    item.$subMenu.$timeOut = setTimeout(function() { thisObj._HideMenu(item); }, this.timeOut);
    this._NotifyParentMenuOut(item.$parentMenu);
  },
  _FItemClick: function(item, evt) {
    var event = new ajax.events.Event(evt);
    if (event.relatedTarget == item || ajax.layout.elementHasChild(item, event.relatedTarget)) return;
    if (ajax.layout.elementHasChild(item.$subMenu, event.target)) return;
    if (item.$parentMenu.$curOpen) {
      this._HideMenu(item.$parentMenu.$curOpen);
      this._NotifyParentMenuOut(item.$parentMenu);
      if (item.$parentMenu.$curOpen == item) {
        item.$parentMenu.$curOpen = null;
        return;
      }
    }
    if (this.absolutePositions[item.$subMenu.$menuLevel] 
    	&& this.absolutePositions[item.$subMenu.$menuLevel].suppressFurtherEvents)
    {
    	event.stop();
    }
    this._ShowMenu(item);
    this._NotifyParentMenuOver(item.$parentMenu);
    item.$parentMenu.$curOpen = item;
  },
  _FMenuMouseOver: function(menu, evt) {
    var event = new ajax.events.Event(evt);
    if (event.relatedTarget == menu || ajax.layout.elementHasChild(menu, event.relatedTarget)) return;
    event.stop();
    if (menu.$closing) menu.$closing = false;
    if (menu.$timeOut) {
      clearTimeout(menu.$timeOut);
      menu.$timeOut = null;
    }
    this._NotifyParentMenuOver(menu.$parentMenu);
  },
  _FMenuMouseOut: function(menu, evt) {
    var event = new ajax.events.Event(evt);
    if (event.relatedTarget == menu || ajax.layout.elementHasChild(menu, event.relatedTarget)) return;
    event.stop();
    menu.$closing = true;
    var thisObj = this;
    menu.$timeOut = setTimeout(function() { thisObj._HideMenu(menu.$parentMenuItem); }, this.timeOut);
    this._NotifyParentMenuOut(menu.$parentMenu);
  },
  _NotifyParentMenuOver: function(elParentMenu) {
    if (elParentMenu.$menuLevel == -1) return;
    elParentMenu.$subOver = true;
    if (elParentMenu.$timeOut) {
      clearTimeout(elParentMenu.$timeOut);
      elParentMenu.$timeOut = null;
    }
  },
  _NotifyParentMenuOut: function(elParentMenu) {
    if (elParentMenu.$menuLevel == -1) return;
    elParentMenu.$subOver = false;
    if (elParentMenu.$closing) {
      var thisObj = this;
      elParentMenu.$timeOut = setTimeout(function() { thisObj._HideMenu(elParentMenu.$parentMenuItem); }, this.timeOut);
    }
  },
  _ShowMenu: function(item) {
    if (item.$subMenu.$closing) item.$subMenu.$closing = false;
    if (item.$subMenu.$timeOut) {
      clearTimeout(item.$subMenu.$timeOut);
      item.$subMenu.$timeOut = null;
    }
    if (!item.$isShowing) {
      item.$isShowing = true;
      var posParams = this.absolutePositions[item.$subMenu.$menuLevel];
      if (posParams) {
        if (posParams.position && posParams.position == 'absolute') {
          item.$subMenu.style.position = 'absolute';
        }
        if (!posParams.offset) {
          posParams.offset = [posParams.x, posParams.y];
        }

        var elParentOffset = ajax.layout.offset(item);
        if (posParams.absoluteWidth == '100%') item.$subMenu.style.width = ajax.layout.totalWidth(item) + 'px';
        if (posParams.halignCenter) {
          var popW = posParams.absoluteWidth;
          if (popW == '100%') popW = null;
          if (!popW) popW = ajax.layout.totalWidth(item.$subMenu);
          if (posParams.halignRight) item.$subMenu.style.right = ((window.getClientWidth() - elParentOffset[0]) - ajax.layout.totalWidth(item) - (popW - ajax.layout.totalWidth(item)) / 2 + posParams.offset[0]) + 'px';
          else item.$subMenu.style.left = (elParentOffset[0] - (popW - ajax.layout.totalWidth(item)) / 2) + posParams.offset[0] + 'px';
        }
        else if (posParams.halignRight) item.$subMenu.style.right = ((window.getClientWidth() - elParentOffset[0]) - ajax.layout.totalWidth(item) + posParams.offset[0]) + 'px';
        else item.$subMenu.style.left = (elParentOffset[0] + posParams.offset[0]) + 'px';
        if (posParams.valignBottom) item.$subMenu.style.bottom = ((window.getClientHeight() - elParentOffset[1]) + posParams.offset[1]) + 'px';
        else item.$subMenu.style.top = (elParentOffset[1] + posParams.offset[1]) + 'px';
        item.$subMenu.style.display = '';
        item.$subMenu.style.visibility = 'visible';
        item.$subMenu.style.zIndex = '5000';

        if (posParams.classHover != null) {
          item.$originalClassName = item.className || '';
          item.className = posParams.classHover;
        }
        else if (posParams.classHoverAdd != null) {
          item.$originalClassName = item.className || '';
          item.className += ' ' + posParams.classHoverAdd;
        }
      }
      item.$subMenu.style.display = '';
    }
  },
  _HideMenu: function(item) {
    var elMenu = item.$subMenu;
    elMenu.$timeOut = null;
    elMenu.$parentMenuItem.$isShowing = null;
    if (elMenu.$subOver) return;
    elMenu.style.display = 'none';
    if (elMenu.$parentMenuItem && elMenu.$parentMenuItem.$originalClassName != undefined) elMenu.$parentMenuItem.className = elMenu.$parentMenuItem.$originalClassName;
    elMenu.$closing = false;
  }
}

