// *** CROSS-BROWSER COMPATIBILITY ***

var isDOM = false, isNS4 = false;
if (document.all) var isDOM = true, docObj = 'document.all.', styObj = '.style';
else if (document.layers) var isNS4 = true, docObj = 'document.', styObj = '';


// *** MOUSEOVER/OUT CONTROL FUNCTIONS ***

// Hide timeout.
var popTimer = 0;
// Array showing highlighted menu items.
var litNow = new Array();

function popOver(menuNum, itemNum)
{
 clearTimeout(popTimer);

 // Hide all other menus & dim old highlighted items, still showing this menu.
 hideAllBut(menuNum);

 // Get tree of parent menu items and light them up - global variable for hideAllBut!
 litNow = getTree(menuNum, itemNum);
 changeCol(litNow, true);

 // Get target menu to show - if it's nonzero, position & show it.
 targetNum = menu[menuNum][itemNum].target;
 if (targetNum > 0)
 {
  targetName = menu[targetNum][0].id;
  menuName = menu[menuNum][0].id;
 
  // Get current menu position.
  menuRef = eval(docObj + menuName + styObj);
  thisX = parseInt(menuRef.left);
  thisY = parseInt(menuRef.top);

  // Add onto this the position of the trigger item within the menu.
  itemPath = docObj;
  if (isNS4) itemPath += menuName + '.document.';
  itemRef = eval(itemPath + menuName + itemNum.toString() + styObj);
  thisX += parseInt(itemRef.left);
  thisY += parseInt(itemRef.top);

  // Add those to the target's offset to set the target's position, show it.
  with (eval(docObj + targetName + styObj))
  {
   left = parseInt(thisX + menu[targetNum][0].x);
   top = parseInt(thisY + menu[targetNum][0].y);
   visibility = 'visible';
  }
 }
}

function popOut(menuNum, itemNum)
{
 // Hide menu in 1/2 sec, *UNLESS* another mouseover clears the timeout!
 popTimer = setTimeout('hideAllBut(0)', 500);
}

function getTree(menuNum, itemNum)
{
 // Array index is the menu number. The contents are null (if that menu is not a parent)
 // or the item number in that menu that is an ancestor (to light it up).
 itemArray = new Array(menu.length);

 while(1)
 {
  itemArray[menuNum] = itemNum;
  // If we've reached the top of the hierarchy, return.
  if (menuNum == 0) return itemArray;
  itemNum = menu[menuNum][0].parentItem;
  menuNum = menu[menuNum][0].parentMenu;
 }
}

// Pass an array and a boolean to specify colour change, true = over colour.
function changeCol(changeArray, isOver)
{
 // Cycle through array searching for items to change.
 for (menuCount = 0; menuCount < changeArray.length; menuCount++)
 {
  // If item number is present, change its colour.
  if (changeArray[menuCount])
  {
   // Get ID's of selected menu in array.
   thisMenu = menu[menuCount][0].id;
   thisItem = thisMenu + changeArray[menuCount].toString();
   newCol = isOver ? menu[menuCount][0].overCol : menu[menuCount][0].backCol;

   // Change the colours of the div/layer background and rewrite text.
   if (isDOM) document.all[thisItem].style.backgroundColor = newCol;
   if (isNS4) document[thisMenu].document[thisItem].bgColor = newCol;
  }
 }
}

function hideAllBut(menuNum)
{
 // Get array of parent menus (item numbers irrelevant, just pass '1').
 var keepMenus = getTree(menuNum, 1);

 // ...and work through it, hiding menus that are not its ancestors/itself.
 for (count = 0; count < menu.length; count++)
  if (!keepMenus[count])
   eval(docObj + menu[count][0].id + styObj + '.visibility = "hidden"');

 // Dim all the items in litNow array.
 changeCol(litNow, false);
}


// *** MENU CONSTRUCTION FUNCTIONS ***


// Variable to end a div or layer based on browser.
var endDL = isDOM ? '</div>' : '</layer>';

function Menu(id, x, y, width, overCol, backCol, borderCol, itemClass)
{
 this.id = id;
 this.x = x;
 this.y = y;
 this.width = width;
 // Colours of menu and items.
 this.overCol = overCol;
 this.backCol = backCol;
 this.borderCol = borderCol;
 // The stylesheet class used for item text.
 this.itemClass = itemClass;
 // Parent menu and item numbers, indexed later.
 this.parentMenu = null;
 this.parentItem = null;
}

function Item(text, href, height, spacing, target)
{
 this.text = text;
 this.href = href;
 this.height = height;
 this.spacing = spacing;
 this.target = target;
}

// This returns a string comprising the opening tag of a div or layer.

function startDL(id, x, y, width, height, vis, back, border, zIndex, extraProps)
{
 // Write a div in IE that resembles a layer's settings, or a layer in NS.
 if (isDOM)
 {
  str = '<div id="' + id + '" style="position: absolute; left: ' + x + '; top: ' + y +
   '; width: ' + width + '; height: ' + height + '; visibility: ' + vis + '; ';
  if (back) str += 'background: ' + back + '; ';
  if (border) str += 'padding: 3px; border: 1px solid ' + border + '; ';
  if (zIndex) str += 'z-index: ' + zIndex + '; ';
  // End style declaration.
  str += '" ';
 }
 if (isNS4)
 {
  str = '<layer id="' + id + '" left="' + x + '" top="' + y + '" width="' + width +
   '" height="' + height + '" visibility="' + vis + '" ';
  if (back) str += 'bgcolor="' + back + '" ';
  if (border) str += 'style="border: 1px solid ' + border + '" ';
  if (zIndex) str += 'z-index="' + zIndex + '" ';
 }

 return str + extraProps + '>'; 
}

// Returns the onMouseOver and onMouseOut attributes

function mouseProps(currMenu, currItem)
{
 return 'onMouseOver="popOver(' + currMenu + ',' + currItem + ')" onMouseOut="popOut(' +
     currMenu + ',' + currItem + ')"';
}

function writeMenus(customRoot, popInd)
{
 for (currMenu = 0; currMenu < menu.length; currMenu++)
 {
  // Don't write the root menu 0 if a custom first menu has been specified.
  showMenu = true;
  if ((currMenu == 0) && customRoot)
  {
   document.write(customRoot);
   showMenu = false;
  }

  // Work with the properties of the main menu description object, i.e. id, x, y.
  with (menu[currMenu][0])
  {
   // Start generating a div with position offset - no dimensions, colours, mouseovers.
   // This position is only relevant for root menu anyway as all others are altered later.
   menuHTML = startDL(id, x, y, 0, 0, 'hidden', null, null, 100, '');

   // Bring properties out of object and into local variables for use later.
   // Width is less padding (3 left & right) and border (1 left & right).
   var back = backCol, bord = borderCol, currWidth = width - 8, itemSty = itemClass;
  }

  // Y-position of next item, increase if you want a menu header.
  itemPos = 0;

  // Remember, items start from 1 in the array (0 is menu object itself, above).
  for (currItem = 1; currItem < menu[currMenu].length; currItem++)
  {
   // Auto-generate ID's in numerical sequence.
   trigID = menu[currMenu][0].id + currItem.toString();

   // Now, work with properties of individual menu items.
   with (menu[currMenu][currItem])
   {
    // Start a menu item positioned vertically, with mouse events and colours.
    // Thanks to Paul Maden (www.paulmaden.com) for helping debug this in IE4, apparently
    // the width must be a miniumum of 3 for it to work in that browser.
    menuHTML += startDL(trigID, 0, itemPos, 3, 0, 'inherit', back, bord, 100,
     mouseProps(currMenu, currItem)) +
     // Add contents of item (default: table with link inside).
     '<table width="' + currWidth + '" border="0" cellspacing="0" cellpadding="0">' +
     '<tr><td align="left" height="' + (height - 7) + '"><a class="' + itemSty + '" href="' +
     href + '">' + text + '</a></td>';

    if (target > 0)
    {
     // Add a popout indicator.
     menuHTML += '<td class="' + itemSty + '" align="right">' + popInd + '</td>';

     // Set target's parents to this menu item.
     menu[target][0].parentMenu = currMenu;
     menu[target][0].parentItem = currItem;
    }

    // Finish off table and item.
    menuHTML += '</tr></table>' + endDL;

    // Move next item position down by this item's height and any additional spacing.
    itemPos += height + spacing;
   }
  }

  // Write this menu to the document.
  if (showMenu) document.write(menuHTML + endDL);

  // Fill in litNow array now with blanks as none are lit up yet.
  litNow[currMenu] = null;
 }
}