/***
*       A huge thanks to Dean Parkinson for the help with this widget
*/
/************************************************************************************************************
@fileoverview
Slide out menu
Copyright (C) 2007  Dean Parkinson

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Alf Magne Kalleland, 2007
Owner of DHTMLgoodies.com


************************************************************************************************************/       
var MENUDIV_ID = "dhtmlgoodies_menu";
var SUBMENU_CLASS = 'dhtmlgoodies_subMenu';
var menuItems;
var slideSpeed_out = 10;       // Steps to move sub menu at a time ( higher = faster)
var slideSpeed_in = 10;
var delayMenuClose = 950;       // Microseconds from mouseout to close of menu
var slideTimeout_out = 25;       // Microseconds between slide steps ( lower = faster)
var slideTimeout_in = 10;       // Microseconds between slide steps ( lower = faster)
var xOffsetSubMenu = 0;        // Offset x-position of sub menu items - use negative value if you want the sub menu to overlap main menu

/* Don't change anything below here */

var indeces = new Array();
indeces[0] = 0;
var isMSIE = navigator.userAgent.indexOf('MSIE')>=0?true:false;
var browserVersion = parseInt(navigator.userAgent.replace(/.*?MSIE ([0-9]+?)[^0-9].*/g,'$1'));
if(!browserVersion)browserVersion=1;

function mouseOn(obj) {
       var mi = findNode(getSearchIdFromObj(obj));
       if (mi) mi.mouseOn();
}

function mouseOff(obj) {
       var mi = findNode(getSearchIdFromObj(obj));
       if (mi) mi.mouseOff();
}

function getSearchIdFromObj(obj) {
       // pull the postfix off the A link or LI tag id and return the menu item ID
       var objId = obj.id;
       var idx = objId.indexOf('_');
       if (idx>=0) {
              return "MenuItem" + objId.substring(idx);
       }
       return null;
}

function slideChildMenu(aId) {
       var mi = findNode(aId);
       if (mi) mi.slideChildMenu();
}

function findNode(searchId) {
       var result;
       for (var no=0;no<menuItems.length;no++) {
              result = menuItems[no].findNode(searchId);
              if (result) return result;
       }
       return null;
}

function getNextIndex(lvl) {
       var result = 0;
       if (indeces.length<=lvl) {
              indeces[lvl] = 1;
       } else {
              result = indeces[lvl];
              indeces[lvl]++;
       }
       return result;
}

function MenuItem(divref, ulref, liref, lvlnum, parentref) {
       this.parent = parentref;
       this.div = divref;
       this.ul = ulref;
       this.width = this.ul.offsetWidth;
       // this.left = div.style.left.replace(/[^0-9]/g,'');
       this.li = liref;
       this.alink = this.li.getElementsByTagName('A')[0];
       this.lvl = lvlnum;
       this.idx = getNextIndex(this.lvl);
       this.children;
       this.subUL = this.li.getElementsByTagName('UL')[0];
       this.children;
       this.isMouseOnMe = false;
       // note: if !isOpen && !isClosed then I am animating a slide
       this.isChildMenuOpen = false;
       this.isChildMenuClosed = true;

       // Constructor
       // if a node does not have an A tag but it's children do then we need
       // null out this node's alink field...
       if (this.alink) {
              if (this.alink.parentNode!=this.li) this.alink = null;
       }
       if (this.subUL) {
              this.children = new Array();
              var subLI = this.subUL.getElementsByTagName('LI')[0];
              while(subLI) {
                     if(subLI.tagName && subLI.tagName.toLowerCase()=='li') {
                            this.children[this.children.length] = new MenuItem(null, this.subUL, subLI, this.lvl + 1, this);
                     }
                     subLI = subLI.nextSibling;
              }
       }

       this.getPostfix = function() {
              return '_' + this.idx + '_' + this.lvl;
       }
       
       this.getId = function() {
              return "MenuItem" + this.getPostfix();
       }

       this.hasChildren = function() {
              return (this.children!=null);
       }

       this.getTopPos = function() {
              var origDisp = this.div.style.display;
              this.div.style.display = "";
              var obj = this.li;
              var result = obj.offsetTop;
              while((obj = obj.offsetParent) != null) result += obj.offsetTop;
              this.div.style.display = origDisp;
              return result;
       }

       this.getLeftPos = function() {
              var origDisp = this.div.style.display;
              this.div.style.display = "";
              var obj = this.li;
              var result = obj.offsetLeft;
              while((obj = obj.offsetParent) != null) result += obj.offsetLeft;
              this.div.style.display = origDisp;
              return result;
       }

       this.renderNode = function() {
              // set node properties
              this.li.id = "menuItemLI" + this.getPostfix();
              this.ul.style.position = "relative";
              if (this.alink) {
                     this.alink.id = "menuItemA" + this.getPostfix();
                     this.alink.onmouseover = function() {mouseOn(this);};
                     this.alink.onmouseout = function() {mouseOff(this);};
              } else {
                     this.li.onmouseover = function() {mouseOn(this);};
                     this.li.onmouseout = function() {mouseOff(this);};
              }

              // set sub-menu nodes
              if (this.hasChildren()) {
                     var mi = this.children[0];
                     var subdiv = document.createElement('DIV');
                     subdiv.className=SUBMENU_CLASS;
                     document.body.appendChild(subdiv);
                     subdiv.id = "menuItemDIV" + mi.getPostfix();
                     this.subUL.id = "menuItemUL" + mi.getPostfix();
                     subdiv.appendChild(this.subUL);
                     subdiv.style.left = this.getLeftPos() + this.width + xOffsetSubMenu + 'px';
                     subdiv.style.top = this.getTopPos() + 'px';
                     subdiv.style.visibility = "hidden";
                     subdiv.style.display = "none";
                     subdiv.style.zindex = "1000";
                     for (var no=0;no<this.children.length;no++) {
                            var mi = this.children[no];
                            mi.div = subdiv;
                            mi.renderNode();
                     }
              }
              return this.li;
       }

       this.findNode = function(searchId) {
              var result;
              if (this.getId() == searchId) {
                     result = this;
              } else {
                     if (this.hasChildren()) {
                            for (var no=0;no<this.children.length;no++) {
                                   var mi = this.children[no];
                                   result = mi.findNode(searchId);
                                   if (result!=null) break;
                            }
                     }
              }
              return result;
       }

       this.mouseOn = function() {
              this.isMouseOnMe = true;
              if (this.hasChildren() && this.isChildMenuClosed) {
                     this.initiateChildMenuOpen();
              }
       }

       this.mouseOff = function() {
              this.isMouseOnMe = false;
              if (this.hasChildren() && !this.isChildMenuClosed) {
                     this.initiateChildMenuClose();
              } else if (this.parent) {
                     this.parent.mouseOff();
              }
       }

       this.isMouseOnChild = function() {
              if (this.isMouseOnMe) return true;
              if (this.hasChildren()) {
                     for (var no=0;no<this.children.length;no++) {
                            if (this.children[no].isMouseOnChild()) return true;
                     }
              }
              return false;
       }

       this.initiateChildMenuOpen = function() {
              this.isChildMenuClosed = false;
              var childDiv = this.children[0].div;
              childDiv.style.width = "0px";
              childDiv.style.visibility = "visible";
              childDiv.style.display = "";
              this.slideChildMenu();
       }

       this.initiateChildMenuClose = function() {
              this.isChildMenuOpen = false;
              // we have to wait to close the menu
              // allow the mouse to navigate over the child menu
              setTimeout("slideChildMenu('" + this.getId() + "')", delayMenuClose);
       }

       this.slideChildMenu = function() {
              var divref = this.children[0].div;
              var ulref = this.children[0].ul;
              var maxwidth = this.children[0].width;
              var nextWidth;
              if (this.isMouseOnMe  || this.isMouseOnChild()) {
                     nextWidth = divref.offsetWidth + slideSpeed_out;
                     if (nextWidth >= maxwidth) {
                            this.finishOpeningChild(divref, ulref, maxwidth);
                     } else {
                            ulref.style.left = nextWidth - maxwidth + "px";
                            divref.style.width = nextWidth + "px";
                            setTimeout("slideChildMenu('" + this.getId() + "')", slideTimeout_out);
                     }
              } else {
                     nextWidth = divref.offsetWidth - slideSpeed_in;
                     if (nextWidth <= 0) {
                            this.finishClosingChild(divref, ulref, maxwidth);
                     } else {
                            ulref.style.left = nextWidth - maxwidth + "px";
                            divref.style.width = nextWidth + "px";
                            setTimeout("slideChildMenu('" + this.getId() + "')", slideTimeout_out);
                     }
              }
       }

       this.finishOpeningChild = function(divref, ulref, maxwidth) {
              this.isChildMenuOpen = true;
              this.isChildMenuClosed = false;
              ulref.style.left = "0px";
              divref.style.width = maxwidth + "px";
       }

       this.finishClosingChild = function(divref, ulref, maxwidth) {
              this.isChildMenuOpen = false;
              this.isChildMenuClosed = true;
              divref.style.visibility = "hidden";
              divref.style.display = "none";
              divref.style.width = maxwidth + "px";
              if (this.parent) this.parent.mouseOff();
       }

}

function collectMenuNodes(menuObj) {
     if (!menuObj) return null;

     var results = new Array();
     var menuUL = menuObj.getElementsByTagName('UL')[0];
     var menuLI = menuUL.getElementsByTagName('LI')[0];
     while(menuLI) {
        if(menuLI.tagName && menuLI.tagName.toLowerCase()=='li') {
              results[results.length] = new MenuItem(menuObj, menuUL, menuLI, 0, null);
        }
        menuLI = menuLI.nextSibling;
     }
     return results;
}

function initMenu() {
       var mainDiv = document.getElementById(MENUDIV_ID);
       menuItems = collectMenuNodes(mainDiv);
       if (menuItems) {
              for (var no=0;no<menuItems.length;no++) {
                     var mi = menuItems[no];
                     mi.renderNode();
              }
              mainDiv.style.visibility = 'visible';
       }
       // window.onresize = resetPosition;
}

window.onload = initMenu;
