// -- 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

var delayFactor = 500;				// multiplier to get seconds
var menuDelay   = 1 * delayFactor;	// delay until menus autoclose. I like 3-4
// NOTE:  The delay is actually, 1/2 a second.

// There's a nuance to how nesting menus close that should be fixed: basically 
// a higher-level menu shouldn't be allowed to close if the child menu is still
// open. The challenge of implementing this is to ensure that if you select a
// sequence like 1->2->3 that when 3 times out, 2 does, then 1 does, etc. It's 
// not as easy as it sounds... 

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 menuOnAtCursor()
{ 
  // same as menuOn() but uses current cursor location. NOTE that there
  // are some bugs with IE 6 that I haven't worked out yet...

  id = menuOnAtCursor.arguments[0];
  evt = menuOnAtCursor.arguments[1];
  xOffset=0;yOffset=0;
  if (menuOnAtCursor.arguments.length >=3) {
	xOffset = menuOnAtCursor.arguments[2];
  }
  if (menuOnAtCursor.arguments.length >=4) {
	yOffset = menuOnAtCursor.arguments[3];
  }
  var myMenu = getObj(id);
  positionMenu(evt, id,xOffset,yOffset);
  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()
{
  // 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.
  
  level = newMenu.arguments[0];
  id    = newMenu.arguments[1];
  xVal  = newMenu.arguments[2];
  yVal  = newMenu.arguments[3];
  
  if (newMenu.arguments.length > 4) {
    css = newMenu.arguments[4];
  } else {
    css = "menu" + level;
  }
  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; 
  
  document.write  ("<DIV CLASS=\"" + css + "\" ID=\"" + id + "\" ");
  document.write  ("STYLE=\"top:"+yVal+"px; left:"+xVal+"px\" ");
  document.write  ("onMouseOver=\"clearTimer('"+id+"');\" ");
  document.writeln("onMouseOut=\"timedClose('" + id + "');\">");
}

function addMenuSep ()
{
  if (addMenuSep.arguments.length > 0) {
    hrSize=addMenuSep.arguments[0];
  } else {
    hrSize=1;
  }
  document.write ("<div class=\"WSsepDiv\"><hr class=\"WSsep\"></div>");
}

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++;

  onMouseOver  = "onmouseover='window.status=\""+label+"\";";
  onMouseOver += "closeMenus("+currentLevel+");";
  onMouseOver += "clearTimer(\""+parentid+"\");'";
  
  onMouseOut   = "onmouseout=\"window.status=''\"";

  document.write ("<div class=\"WSmenuitemDiv\" id=\"" + id + "\" ");
  document.write (onMouseOver + " " + onMouseOut + ">");
  document.write ("<a class=\"WSmenuitem\" href=\"" + url + "\" " + onMouseOver + " " + onMouseOut + ">");
  document.write (label + "</a></div>");

}

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++;
  
  onMouseOver  = "onmouseover='window.status=\""+label+"\";";
  onMouseOver += "closeMenus(\"" + currentLevel +"\");";
  onMouseOver += "clearTimer(\"" + parentid + "\");";
  onMouseOver += "menuOn(\"" + submenuId + "\");'";
  
  document.write ("<div class=\"WSsubmenuDiv\" id=\"" + id + "\" ");
  document.write (onMouseOver);
  document.write ("><a class=\"WSsubmenu\" href=\"#\" id=\"" + id + "\" ");
  document.write (onMouseOver);
  document.write (">" + label + "</a></div>");
}
  
function addMenuTitle(label)
{
  // add an inactive menu element (title) to the menu
  var id = "menuTitle" + menuItemId;
  menuItemId++;
  
  document.writeln("<DIV CLASS=\"WSmenutitle\" ID='" + id + "'>");
  document.writeln(label + "</DIV>");
}

function positionMenu()
{
  evt = positionMenu.arguments[0];
  id = positionMenu.arguments[1];
  xOffset = 0;
  yOffset = 0;
  if (positionMenu.arguments.length >= 3) {
	xOffset = positionMenu.arguments[2];
  }
  if (positionMenu.arguments.length >= 4) {
	yOffset = positionMenu.arguments[3];
  }
  // 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, add the offset.
  leftEdge += xOffset;
  topEdge  += yOffset;
  
  // 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);
}

/* example of use: 

newMenu(1, "mainMenu", 100, 75);
addMenuTitle("Holmes Adventures");
addMenuItem("case-of-identity.html", "A Case of Identity");
endMenu();

then

<A HREF="#" onMouseOver="menuOn('mainMenu');">menu</A>
*/

