// menu.js - code-free pop-up menus
// version 0.3 [beta], 13-Dec-2001
// written by Andrew Clover <and@doxdesk.com>, use freely

// menu open/close delay in milliseconds
menu_open= 100
menu_close= 600

// cross-browser layer show/hide function
function menu_state(el, vis) {
  var n= menu_getnode(el);
  if (n && n.style) n.style.visibility= vis ? 'visible':'hidden';
  else if (n && n.visibility) n.visibility= vis ? 'show':'hide';
}

function menu_getnode(el) {
  if (document.getElementById) return document.getElementById(el);
  if (document.all) return document.all[el];
  if (document.layers) return document.layers[el];
  return null;
}

// queue holding a list of open/close events to happen soon.
// Each entry is an array of the element name and a boolean
// (true for open, false for close). An element name of ''
// indicates a cancelled event if the boolean is true, or an
// event that has already happened, if false
menu_queue= new Array();

// push new event onto queue, unless an event on the same menu is
// already on the queue, waiting to happen. If there is an event
// on the queue featuring that menu but is open instead of close
// or vice-versa, cancel that event
function menu_push(el, vis) {
  var i;
  for (i= 0; i<menu_queue.length; i++) {
    if (menu_queue[i][0]==el) {
      if (menu_queue[i][1]!=vis) {
        menu_queue[i][0]= '';
        menu_queue[i][1]= true;
      }
  } }
  var delay= vis ? menu_open:menu_close;
  setTimeout('menu_pop('+menu_queue.length+');', delay);
  menu_queue[menu_queue.length]= new Array(el, vis);

  // parent chaining
  var n= menu_getnode(el);
  if (n && n.className) {
    var classes= n.className.split(' ');
    for (var i= classes.length; i-->0;)
      if (classes[i].substring(0, 5)=='menu-')
        menu_push(classes[i], vis);
  }
}

// take a specified event off the queue, enact it, and if
// there are no events left in the queue, throw the queue
// away to save memory
function menu_pop(q) {
  var i;
  if (menu_queue[q][0]!='')
    menu_state(menu_queue[q][0], menu_queue[q][1]);
  menu_queue[q][0]= '';
  menu_queue[q][1]= false;
  for (i= 0; i<menu_queue.length; i++)
    if (menu_queue[i][0]!='' || menu_queue[i][1])
      return;
  menu_queue.length= 0;
}

// receive events from link
function menu_linkover() {
  menu_push(this.hash.substring(1), true);
}
function menu_linkout() {
  menu_push(this.hash.substring(1), false);
}
function menu_click() {
  return false;
}
function menu_layerover() {
  menu_push(this.id, true);
}
function menu_layerout() {
  menu_push(this.id, false);
}

// scan document for menu-activating links
function menu_bind_doc(d) {
  var i; var lk;
  for (i= 0; i<d.links.length; i++) {
    lk= d.links[i];
    if (lk.hash.substring(1, 6)=='menu-') {
      menu_state(lk.hash.substring(1), false);
      lk.onmouseover= menu_linkover;
      lk.onmouseout= menu_linkout;
      lk.onclick= menu_click;
      menu_bind_layer(lk.hash.substring(1));
  } }
  if (d.layers)
    for (i= 0; i<d.layers.length; i++)
      menu_bind_doc(d.layers[i].document);
}

// scan layers for links that should keep their own layer open
function menu_bind_layer(l) {
  if (document.getElementById) {
    document.getElementById(l).onmouseover= menu_layerover;
    document.getElementById(l).onmouseout= menu_layerout;
  }
  if (document.all) {
    document.all[l].onmouseover= menu_layerover;
    document.all[l].onmouseout= menu_layerout;
  }
  else if (document.layers) {
    document.layers[l].onmouseover= menu_layerover;
    document.layers[l].onmouseout= menu_layerout;
  }
}

// process menus immediately when the script is imported
// (this could be moved to <body onload> if you want)
menu_bind_doc(document);
