﻿// global constants
var mainMenuId = "navigation";  // Must contain the main menu.
var subMenuId = "subNavigation";  // Must contain ALL sub-menus.
var menuStr = "menu"; // All menu classNames must start with this.
var doHoverMe = true; // NO-ACCESSIBILITY false; // IE<7 should override.
var hoverMenuStr = "menu"; // Identifies a multi-level menu.
var hoverClass = "hoverme";
var r = /hoverme\s*/;

window.onload = doit; // Attach to window's onload. <===

// Our main function, called when window is loaded.
function doit()
{
  if (!document.getElementById)
    return; // Ancient javascript -- forget it.
  initmenu(mainMenuId);
}

function initmenu(mainMenuId)
{
  var mainMenuTag = document.getElementById(mainMenuId);
  if (!mainMenuTag)
    return; // No menu div.
  var hoverMenu = initHover(mainMenuTag); // FIRST, so detect whether hovering.
  markMenuForThisPage(mainMenuId, subMenuId, hoverMenu);
}

var currentHover = null;

function setHoverMe(tag)
{
  // Clear any old hover.
  if (currentHover)
    clearHoverMe(currentHover);
    
  //amIAlive();
  c=tag.className;
  tag.className=(c? hoverClass+' '+c: hoverClass);
  tag.getElementsByTagName("ul")[0].style.visibility = "visible";
  currentHover = tag;
}

function clearHoverMe(tag)
{
  c=tag.className;
  tag.className=(c? c.replace(r,''): '');
  tag.getElementsByTagName("ul")[0].style.visibility = "hidden";
  if (currentHover == tag)
    currentHover = null;
}

function initHover(mainMenuTag)
{
  var hoverMenu = findHoverMenu(mainMenuTag);
  // CAUTION: if rename mainMenu to match drop-down's menu,
  // then need some way to know whether sub-menu's are drop-down.
  if (hoverMenu && doHoverMe)
  {
    var liTags = mainMenuTag.getElementsByTagName("li");
    for (i = 0; i < liTags.length; i++)
    {
      var tag = liTags[i];
      // Only do to top-level li's.
      var ulTag = tag.parentNode;
      var maybeMainTag = ulTag.parentNode;
      if (maybeMainTag==hoverMenu)
      {
        var c = tag.className;
        var newClass = (c ?  c+' '+hoverClass :  hoverClass);
        // prepend class "hoverme", and make sub-menu visible.
        // TBD: If multi-level, is the child <ul> always first??
        tag.onmouseover=function(){ setHoverMe(this); };
        tag.onmouseout=function(){ clearHoverMe(this); };
        
        // (drop-down menu only.)
        // ACCESSIBILITY: catch focus on main <a> link w/i this <li>.
        // CAUTION: author might have omitted <a> link, in which case
        // the sub-menu cannot be reached via keyboard tabbing.
        var childNodes = tag.childNodes;
        var aTag = findTagByTag(childNodes, "a");
        if (aTag)
        {
          aTag.onfocus=function(){ setHoverMe(this.parentNode); };
          //NO, hides when tab to submenu item aTag.onblur=function(){ clearHoverMe(this.parentNode); };
        }
      }
    }

    // Hide submenus (non-main <ul>s).
    var ulTags = mainMenuTag.getElementsByTagName("ul");
    for (i = 0; i < ulTags.length; i++)
    {
      var ulTag= ulTags[i];
      var parentTag = ulTag.parentNode;
      if (parentTag!=hoverMenu) // TBD: I'd like to check that it isn't an <li>.
      {
        ulTag.style.position="absolute"; // Stop occupying layout space.
        ulTag.style.visibility="hidden";
      }
    }
  }
  return hoverMenu;
}

function findHoverMenu(mainMenuTag)
{
  var divTags = mainMenuTag.getElementsByTagName("div");
  // multi-level identified with div "menu" rather than "mainMenu".
  for (i = 0; i < divTags.length; i++)
  {
    var tag = divTags[i];
    var tagClass = tag.className;
    if (!tagClass)
      continue;
    if (tagClass == hoverMenuStr)
    {
      return tag;
    }
  }
  return null;
}

function markMenuForThisPage(mainMenuId, subMenuId, hoverMenu)
{
  // Find tag containing menu, and pageName.
  var mainMenuTag = document.getElementById(mainMenuId);
  var subMenuTag = document.getElementById(subMenuId);
  var pageName = extractPageName(mainMenuTag.className, menuStr);
  if (pageName == "")
  { // Try to find on container of sub-menus.
	 	if (subMenuTag)
	    pageName = extractPageName(subMenuTag.className, menuStr);
    if (pageName == "")
      return;
  }

  // List both main- and sub- items.
  var mainLiTags = mainMenuTag.getElementsByTagName("li");
  //var subLiTags = mainLiTags;//new Array(0);//(subMenuTag ?  subMenuTag.getElementsByTagName("li") : new Array(0));
  var subLiTags = (subMenuTag ?  subMenuTag.getElementsByTagName("li") : new Array(0));
  //var liTags = mainLiTags;//.concat(subLiTags);   // TBD
  var liTags = myconcat(mainLiTags, subLiTags);
  
  // Find matching menu element.
  //var itemTag = findTagByClass(liTags, thisPage);
  var itemTag = findTagByClass(liTags, pageName);
  if (itemTag != null)
  {
   // Mark this item by appending a special class.
    itemTag.className = itemTag.className + " " + "currentPageMenuItem";
    
    var mainName = markMainMenuForThisPage(mainMenuTag, itemTag, pageName);
    if (subMenuTag)
      hideOtherSubmenus(subMenuTag, mainName);  // if null, will hide ALL sub-menus.
    // Allow sub-menus to be in same container as main-menu.
    if (!hoverMenu) // only hide if not doing drop-down.
      hideOtherSubmenus(mainMenuTag, mainName);
  }
}

// Each sub-menu has <ul class="menuX">,
// where "menuX" is the mainMenuName of the sub-menu.
// CAUTION: mainMenuName==null to hide ALL sub-menus.
function hideOtherSubmenus(menuTag, mainMenuName)
{
  // Find all ul's w/i the navigation structure.
  // A ul with no class is left untouched -- assumed to be main menu.
  var ulTags = menuTag.getElementsByTagName("ul");
  for (i = 0; i < ulTags.length; i++)
  {
    var tag = ulTags[i];
    var tagClass = tag.className;
    if (!tagClass)
      continue;
    if (tagClass == mainMenuName)
    {
      // Current sub-menu. Leave it visible.
    }
    else
    { // Other sub-menu. Hide it.
      tag.style.display = "none";
    }
  }
}

// IF "pageName" is a sub-menu name; e.g. "menu1-1",
// THEN locate and mark the corresponding main-menu element.
// RETURN mainMenuName if it is a submenu name, else return null.
// TBD: Suppose we can't locate the corresponding main menu?
// FOR NOW: return name anyway; maybe there is still other work for client to do.
function markMainMenuForThisPage(menuTag, itemTag, pageName)
{
  // Better approach is to check <ul>'s class.
  // For a sub-menu, that has the mainMenuName.
  var ulTag = itemTag.parentNode;
  var mainMenuName = ulTag.className;
  if (!mainMenuName)
    return null;
  
  // TBD: main menu might be under a different menuTag.
  var liTags = menuTag.getElementsByTagName("li");
  var itemTag = findTagByClass(liTags, mainMenuName);
  if (itemTag != null)
  {
   // Mark this item by appending a special class.
    itemTag.className = itemTag.className + " " + "currentPageMenuItem";
  }
  
  return mainMenuName;
}

// className might be a series of classes separated by spaces.
// the class starting with "menu" is the one we want.
// CAUTION: "menu" could be in the middle of a name.
// RETURNS "" if not found.
function extractPageName(className, menuStr)
{
  if (className == null)
    return "";
  if (className == "")
    return className;
    
  // Search for "menu".  But make sure isn't in middle of a name.
  var iMenuStr = className.indexOf(menuStr);
  if (iMenuStr < 0)
    return "";
    // EXCEPT at the start, check if previous char is a blank.
  if (iMenuStr != 0)
  {
    var previousChar = className.charAt(iMenuStr - 1);
    if (previousChar == " ")
    {
      // GOOD, that's what we want.
    }
    else
    {
      // Find another "menu".  THIS time we can include the initial " ".
      iMenuStr = className.indexOf(" " + menuStr, iMenuStr);
      if (iMenuStr < 0)
        return "";
      // Remove the initial " ".
      iMenuStr = iMenuStr + 1;
    }
  }
  
  // Chop any preceding chars.
  if (iMenuStr > 0)
    className = className.substring(iMenuStr);
  
  // NOTE: "className" has been trimmed to start with the menu item.
  // Check for any following blank, which would terminate the menu name.
  var iBlank = className.indexOf(" ");
  if (iBlank > -1)
  {
    className = className.substring(0, iBlank);
  }
  
  return className;
}

function findTagByTag(tags, tagNameWant)
{
  if (tags && (tags.length >= 1))
  {
    var tag = tags[0];
    for (var i = 0; i < tags.length; i++)
    {
      var tag = tags[i];
      var tagNameActual = tag.nodeName.toLowerCase();
      if (tagNameActual == tagNameWant)
        return tag;
    }
  }
  return null;
}

function findTagByClass(tags, className)
{
  for (i = 0; i < tags.length; i++)
  {
    var tag = tags[i];
    if (tag.className == className)
      return tag;
  }
  return null;
}

// TBD: I couldn't get "mainLiTags.concat(subLiTags)" to work,
// so wrote my own concat.
// CAUTION: Might be modifying array1 --
// I don't know if javascript is call-by-value or by-reference.
function myconcat(array1, array2)
{
  var iResult = 0;
  var result = new Array(array1.length + array2.length);
  for (iSrc = 0; iSrc < array1.length; iSrc++)
  {
    result[iResult++] = array1[iSrc];
  }
  for (iSrc = 0; iSrc < array2.length; iSrc++)
  {
    //array1.put(array2[i]);
    result[iResult++] = array2[iSrc];
  }
  return result;
}


