//// Navigation menu code for Cadar 2008 site ////

// CONFIG ITEMS...
// prefixes for drop down menus and menu (navigation) items...
var prefixMenu = "mnu";
var prefixNav = "nav";
// menu configuration vars...
var menuOffsetX = -40;
var menuOffsetY = 4;
var navDelay = 350;   // milliseconds before drop menu closes
// End of Config Items ////////

// INTERNAL VARIABLES...
// arrays of navigation item base names...
var maxLevels = 4;
var navTimer = 0;   // timer for menu hiding
// individual menu items...  (Base name, Level, Open, Close);
var arrMenu = new Array();
var MID = 0;    // really a const!
var LVL = 1;
var OPN = 2;
var CLS = 3;
// End of Internal Variables ////////

///////////////////////////////////////////////
// Trace()
//
// write a trace message into an element with id="debug"
function Trace(sMsg)
  {
  var elemDebug = document.getElementById("debug");
  if (elemDebug === false)
    return;
  var s = elemDebug.innerHTML;
  s = s + sMsg + "; ";
  elemDebug.innerHTML = s;
  }

///////////////////////////////////////////////
//
// initMenus()
//
// Pulls out <ul> elements to find menus with 
// class id of 'navx' where x is the submenu 
// level: 1, 2, 3 etc.
// Compiles these into the arrMenu array above.
//
function initMenus()
  {
  //dbg alert("initMenus()");
  // get all UL elements - they might be menus...
  var elems = document.getElementsByTagName("ul");
  var nLvl = 0;
  var nFound = 0;
  //dbg alert("Found " + elems.length + " possible menu elements");
  // first check class name should be 'mnu' + something or other..
  for (var i in elems)
    {
    //dbg alert(i + ":\n" + elems[i].innerHTML);
    var attr = elems[i].attributes;
    // IE BUG WARNING: must use construction: attr['class'] rather than attr.class
    //                 as IE seems to treat class as a reserved word in javascript.
    //                 You can get away with using it in a string but not as a 
    //                 variable name or an element of a structure.
    if (typeof(attr) != "undefined" && typeof(attr['class']) != "undefined")
      {
      var clss = attr['class'].value;     // can't be var class in IE!
      if (clss.match(prefixMenu) == prefixMenu)
        {
        //dbg alert("class=" + clss);
        // we found a mnu element so add it to arrMenu...
        nLvl = clss.substr(prefixMenu.length, 1);
        if (nLvl > 0 && typeof(attr.id) != "undefined")
          {
          var sID = attr.id.value.substr(prefixMenu.length);
          arrMenu.push(new Array(sID, nLvl, false, false));
          nFound++;
          
          //dbg alert(i + " menu: id=" + sID + ", level=" + nLvl);
          }
        }
      }
    }
  }
  
///////////////////////////////////////////////
// openMenu()
//
// Drops open a menu and marks it as open
// sID: string: the base ID name of the menu item to open
//
function openMenu(sID)
  {
  //DEBUG  Trace("<br />openMenu("+sID+")");
  // check the menu exists...
  var sNavID = prefixNav + sID;
  var sMenuID = prefixMenu + sID;
  var ndx = getMenuIndex(sID);
  //DEBUG alert("openMenu('" + sID + "'), sNavID='" + sNavID + "', sMenuID='" + sMenuID + "', nMenu=" + nMenu);
  if (ndx < 0 || arrMenu[ndx][MID] == "")
    return;

  var elemNav = document.getElementById(sNavID);
  var elemMenu = document.getElementById(sMenuID);
  if (elemNav && elemMenu)
    {
    // cancel any pending menu closures in this or earlier levels...
    for (var i in arrMenu)
      if (arrMenu[i][LVL] <= arrMenu[ndx][LVL])
        arrMenu[i][CLS] = false;
    // work out where to open the new menu...
    elemMenu.style.left = findPosX(elemNav)+ elemNav.offsetWidth + menuOffsetX + "px";
    elemMenu.style.top = findPosY(elemNav) + menuOffsetY + "px";
    //DEBUG alert(elemNav.id+": posX="+findPosX(elemNav)+", width=+"+elemNav.offsetWidth);
    // hide any other drop down menus at this level or higher...
    shutAllMenus(arrMenu[ndx][LVL]);
    // drop this menu...
    //elemMenu.style.display = "block";
    elemMenu.style.visibility = "visible";
    // and mark it as open...
    arrMenu[ndx][OPN] = true;
    }
  return true;   // allows browser to display link target
  }

///////////////////////////////////////////////
// keepMenuOpen()
//
// Clears the CLS flag of a menu scheduled for closure
// so it remains open.  Also keeps open any menu at
// a lower level.
// sID: string: the base ID name of the menu item to open
//
function keepMenuOpen(sID)
  {
  //DEBUG  Trace("keepMenuOpen("+sID+")");
  var ndx = getMenuIndex(sID);
  if (ndx < 0 || arrMenu[ndx][MID] == "")
    return;
  for (var i in arrMenu)
    if (arrMenu[i][LVL] <= arrMenu[ndx][LVL])
      arrMenu[i][CLS] = false;
  }

///////////////////////////////////////////////
// closeMenu()
//
// Schedules the closure of all open menus.
// Allows menu to remain open while mouse is moved
// from nav item to a menu just dropped and to cope
// with minor mouse movement errors
// sID: string: the base ID name of the menu item to close
//
function closeMenu(sID)
  {
  //DEBUG  Trace("closeMenu("+sID+")");
  // mark and schedule menu closure...
  for (var i in arrMenu)
    if (arrMenu[i][OPN])
      arrMenu[i][CLS] = true;
  navTimer = setTimeout("hideMenus()", navDelay);
  //DEBUG Trace("setTimeout(), " + navTimer);
  }

///////////////////////////////////////////////
// hideMenus()
//
// Internal function to shut a open menus that have been
// marked for closure.  Used via setTimeout() to delay the
// closing of a menu for a short while after a mouseout event
// closes it.
// ndx: int: the array index of the menu item to close
//
function hideMenus()
  {
  //DEBUG  Trace("hideMenus()");
  for (var i in arrMenu)
    {
    if (arrMenu[i][CLS])
      {
      var elem = document.getElementById(prefixMenu + arrMenu[i][MID]);
      if (elem)
        {
        //elem.style.display = "none";
        elem.style.visibility = "hidden";
        }
      arrMenu[i][CLS] == false;
      arrMenu[i][OPN] == false;
      }
    }
  }

///////////////////////////////////////////////
// shutMenu()
//
// Closes an open menu immediately and marks it closed.
// Used to close a menu before opening another one.
// sID: string: the base ID name of the menu item to close
//
function shutMenu(sID)
  {
  //DEBUG  Trace("shutMenu("+sID+")");
  var ndx = getMenuIndex(sID);
  if (ndx < 0 || arrMenu[ndx][MID] == "")
    return;
  hideMenu(ndx);
  }

///////////////////////////////////////////////
// shutAllMenus()
//
// Close open menus on this level and higher before opening another one.
//
function shutAllMenus(nLevel)
  {
  //DEBUG  Trace("shutAllMenus("+nLevel+")");
  var elem;
  for (var i in arrMenu)
    {
    if (arrMenu[i][LVL] >= nLevel)
      {
      elemMenu = document.getElementById(prefixMenu + arrMenu[i][MID]);
      //elemMenu.style.display = "none";
      elemMenu.style.visibility = "hidden";
      arrMenu[i][CLS] = arrMenu[i][OPN] = false;
      }
    }
  }

///////////////////////////////////////////////
// getMenuIndex()
//
// Internal function to calc index of a specified
// base ID name.
// sID: string: base ID name of menu to find
// nLevel: integer: which level of the array to
//          look in.
//
function getMenuIndex(sID)
  {
  for (var i in arrMenu)
    {
    if (arrMenu[i][MID] == sID)
    return i;
    }
  // if we're here we didn't find the menu...
  return -1;
  }

// functions to find the position of an element...
// updated 2/9/2007, MT
// fixes IE offsetParent problem
function findPosX(obj)
  {
  var curleft = obj.offsetLeft;
  while (obj.offsetParent)
    {
    obj = obj.offsetParent;
    curleft += obj.offsetLeft;
    }
  return curleft;
  }

function findPosY(obj)
  {
  var curtop = obj.offsetTop;
  while (obj.offsetParent)
    {
    obj = obj.offsetParent;
    curtop += obj.offsetTop;
    }
  return curtop;
  }


//
///// End of File ///////////////////////////////////////

