// -- cascading menu library tied into crashcourse.js and as 
//    demonstrated in Dynamic HTML Weekend Crash Course

var maxDepth = 4;
var menuItemId = 1;
var menunames  = new Array;
menunames[0] = new Array("");
menunames[1] = new Array("");
menunames[2] = new Array("");
menunames[3] = new Array("");
var menucounts = new Array(0,0,0,0,0);

var canCloseMenu = new Array("");
var timeoutID    = new Array("");

var delayFactor = 1000;				// multiplier to get seconds
var menuDelay   = 5 * delayFactor;	// delay until menus autoclose. I like 3-4

function timedClose(id)
{
  // set up a timer to close the specified menu
  clearTimer(id);  // clear any old timers for this particular menu
  canCloseMenu["'" + id + "'"] = 1;  // at this point we can close it
  timeoutID["'" + id + "'"] = setTimeout("smartClose('" + id + "')", menuDelay);
}

function clearTimer(id)
{
  if (canCloseMenu["'" + id + "'"] == 1)   // if it was queued to close
    clearTimeout(timeoutID[ "'" + id + "'"]); // kill old timer
}

function smartClose(id)
{
  // close menu, but only if allowed based on system state
  if (canCloseMenu["'" + id + "'"] == 1) { 
    menuOff(id); 
  }
  canCloseMenu["'" + id + "'"] = 0;
}

function menuOn(id)
{ 
  var myMenu = getObj(id);
  myMenu.visibility="visible";   
  timedClose(id);		// onMouseOver will kill this timer... 
}

function menuOnAtCursor(id, evt)
{ 
  // same as menuOn() but uses current cursor location. NOTE that there
  // are some bugs with IE 6 that I haven't worked out yet...
  var myMenu = getObj(id);
  positionMenu(evt, id);
  myMenu.visibility="visible";   
  timedClose(id);		// onMouseOver will kill this timer... 
}

function menuOff(id)
{
  obj = getObj(id);
  obj.visibility="hidden";
}

function closeMenus(level)
{
  // closes all menus at any level higher than that specified
  for (var lvls = level; lvls < maxDepth; lvls++) {
    for (var i=0; i < menucounts[lvls]; i++) {
      menuOff(menunames[lvls][i]);
    }
  }
}

function newMenu(level, id, xVal, yVal)
{
  // create a new menu element. Call this with level specifying the relative
  // depth of the menu (1 = topmost, 2 = submenu, etc), id indicating the name
  // you'll use for future references to the menu, and xVal, yVal for the 
  // absolute position of the menu on the screen.
  
  if (level > maxDepth)
    return( alert("Too deep: newMenu("+id+") called with level > max depth") );
    
  menunames[level][ menucounts[level]++ ] = id; // remember new ID in level array
  currentLevel = level+1;						//  and increment counter
  parentid = id;			// global variable used for addMenuItem calls
  
  output = "<DIV CLASS=\"menu\" ID=\"" + id + "\" " +
      "STYLE=\"top:"+yVal+";left:"+xVal+"\" " +
      "onMouseOver=\"clearTimer('"+id+"');\" " +
      "onMouseOut=\"timedClose('" + id + "');\">";
  document.writeln(output);
}

function endMenu()
{
  document.writeln("</DIV>");
}

function addMenuItem(url, label)
{
  // call this with a url and display label for all regular menu entries.
  // use addSubmenu() to add submenu items to a menu instead.
  
  var id = "menuItem" + menuItemId;
  menuItemId++;
  
  output = "<DIV CLASS=\"mi\" ID='" + id + "'" +
    " onMouseOver=\"setBgColor('" + id + "', '#069');" +
    " window.status='" + label + "';" +
    " closeMenus(" + currentLevel + ");clearTimer('"+parentid+"');\"" +
    " onClick=\"location.href=\'" + url + "'\"" +
    " onMouseOut=\"setBgColor('" + id + "', '#33C');window.status='';\">" +
    label + "</DIV>";
  document.write(output);
}

function addSubmenu(submenuId, label)
{
  // call this to add a submenu link to a menu. submenuId should be the
  // ID name that'll be used to create the new menu, and label is the
  // display text for the menu. It's encouraged that submenu labels have
  // an ellipses (...) or similar visual element to denote their status.
  
  var id = "menuItem" + menuItemId;
  menuItemId++;
  
  document.writeln("<DIV CLASS=\"mi\" ID='" + id + "'");
  document.write  (" onMouseOver=\"setBgColor('" + id + "', '#069');");
  document.write  (" window.status='" + label + "';");
  document.writeln(" closeMenus(" + currentLevel + ");clearTimer('"+parentid+"');");
  document.writeln(" menuOn('" + submenuId + "');\"");
  document.writeln(" onMouseOut=\"setBgColor('" + id + "', '#33C')\">");
  document.writeln(label + "</DIV>");
}
  
function addMenuTitle(label)
{
  // add an inactive menu element (title) to the menu
  var id = "menuTitle" + menuItemId;
  menuItemId++;
  
  document.writeln("<DIV CLASS=\"mt\" ID='" + id + "'>");
  document.writeln(label + "</DIV>");
}

function positionMenu(evt, id)
{
  // display a pop-up window immediately below the cursor, adjusting to 
  // ensure that the pop-up isn't horizontally offscreen
   var myObj = getObj(id);
   
   // now let's compute the width and centerpoint of the menu itself
   var menuWidth = 250, halfMenuWidth = 125, winWidth = windowWidth();
   
   // where did the user click their mouse?
   if ((! MSIE) && (evt != null)) event = evt;  // keeps Netscape happy
   leftEdge = getEventX(event) - halfMenuWidth - 5;
   topEdge  = getEventY(event) + 1;
   
   // now let's tweak the location to ensure that the menu isn't offscreen
   
   if ((leftEdge + menuWidth + 10) > winWidth)
     leftEdge = winWidth - menuWidth - 5;
   if (leftEdge < 5) leftEdge = 5;
   
   moveObj(id, leftEdge, topEdge);
}

newMenu(1, "mainMenu", 200,105);
addMenuTitle("Holmes Adventures");
addMenuItem("case-of-identity.html", "A Case of Identity");
addMenuItem("scandal-bohemia.html", "A Scandal in Bohemia");
addMenuItem("beryl-coronet.html", "The Adventure of the Beryl Coronet");
addMenuItem("blue-carbuncle.html", "The Adventure of the Blue Carbuncle");
addMenuItem("copper-beeches.html", "The Adventure of the Copper Beeches");
addMenuItem("engineers-thumb.html", "The Adventure of the Engineers Thumb");
addMenuItem("noble-bachelor.html", "The Adventure of the Noble Bachelor");
addMenuItem("speckled-band.html", "The Adventure of the Speckled Band");
addMenuItem("boscombe-valley.html", "The Boscombe Valley Mystery");
addMenuItem("five-orange-pips.html", "The Five Orange Pips");
addMenuItem("twisted-lip.html", "The Man with the Twisted Lip");
addMenuItem("red-headed-league.html", "The Red-headed League");
endMenu();

newMenu(1, "linksMenu",250,105);
addMenuTitle("Holmsian Web Sites");
addMenuItem("http://www.bakerstreet221b.de/main.htm", 
  "Camden House");
addMenuItem("http://www.sherlockian.net/", "Sherlockian Net");
addMenuItem("http://www.evo.org/sherlock/international", 
  "Sherlock Holmes International");
addMenuItem("http://www.sherlock-holmes.co.uk/", 
  "The Sherlock Holmes Museum");
addMenuItem("http://www.holmes-sherlock.com/", "Yoxley Old Place");
endMenu();
