/** DROPDOWN MENU IMPLEMENTATION **********************************************/
// Dec 17, 2004 - v1: First implementation.
// Dec 30, 2004 - v2: Submenu position can now be set.
// Dec 31, 2004 - v3: Added positionBox function to add-in custom positioning.
// Jan 2, 2005  - v4: Bugfix: level of onMouseOutItem was sometimes 1 too high.
// Mar 15, 2005 - v5: Added openDelay variable

var ddm_itemToHandler = new Array(); // key=itemID/boxID, value=DropDownMenu
var ddm_overBox = new Array();
var ddm_overItem = new Array();
var ddm_openBoxes = new Array(); // key=level, value=xxMenuBox name
var ddm_handleEventsTO = null;

var ddm_allItemsHash = new Array(); // key=itemID, value=Div
var ddm_allBoxesHash = new Array(); // key=boxID, value=xxMenuBox
var ddm_itemInBox = new Array(); // key=itemID, value=xxMenuBox

/*
 * Instantiates a new DropDownMenu
 */
function DropDownMenu(boxPrefix,itemPrefix) // MenuHandler
{
  // Menu settings and overridable functions
  this.onMouseOverBox  = function(elementDiv,level) {}
  this.onMouseOutBox   = function(elementDiv,level) {}
  this.onMouseOverItem = function(elementDiv,level) {}
  this.onMouseOutItem  = function(elementDiv,level) {}
  this.subOffsetX = -4;
  this.subOffsetY = 0;
  this.openDelay = 0;
  this.positionBox = function(boxDiv,level,parentDiv) { return false; } // returns true when box was positioned, false when positioning should be done by default method

  var tree = new DDMenuBox(this,0,boxPrefix,itemPrefix,null);
  if (tree.div == null)
  {
    //alert("Menu root '"+boxPrefix+"' not found!");
    return;
  }
  else if (tree.items.length == 0)
  {
    //alert("Menu '"+boxPrefix+"' is empty!");
    return;
  }
  //setInterval("ddm_printOver()",200);
}

function ddm_printOver()
{
  var str = "Box:";
  for (var idx in ddm_overBox)
    if (ddm_overBox[idx]) str += idx+" ";
  str += "   Item:";
  for (var idx in ddm_overItem)
    if (ddm_overItem[idx]) str += idx+" ";
  window.status = str;
}

// private function
function ddm_handleEvents()
{
  var boxName = null;
  for (var idx in ddm_overBox)
    if (ddm_overBox[idx])
    {
      boxName = idx;
      break;
    }
  var itemName = null;
  for (var idx in ddm_overItem)
    if (ddm_overItem[idx])
    {
      itemName = idx;
      break;
    }
  if (itemName != null)
  {
    var box = ddm_itemInBox[itemName];
    box = box.children[itemName];
    if (box != null) ddm_openBox(ddm_allItemsHash[itemName],box.name);
    else
    {
      var level = itemName.split("_").length;
      ddm_closeBox(level);
    }
  }
  else if (boxName == null && itemName == null) // close all
  {
    ddm_closeBox(0);
  }
}

// private function
function ddm_onMouseOverBox()
{
  clearTimeout(ddm_handleEventsTO);
  var name = this.getAttribute("id");
  ddm_overBox[name] = true;
  var box = ddm_allBoxesHash[name];
  var ddm = ddm_itemToHandler[name];
  ddm.onMouseOverBox(box.div,box.level);
  ddm_handleEventsTO = setTimeout("ddm_handleEvents()",ddm.openDelay);
}

// private function
function ddm_onMouseOutBox()
{
  clearTimeout(ddm_handleEventsTO);
  var name = this.getAttribute("id");
  ddm_overBox[name] = null;
  var box = ddm_allBoxesHash[name];
  var ddm = ddm_itemToHandler[name];
  ddm.onMouseOutBox(box.div,box.level);
  ddm_handleEventsTO = setTimeout("ddm_handleEvents()",ddm.openDelay);
}

// private function
function ddm_onMouseOverItem()
{
  clearTimeout(ddm_handleEventsTO);
  var name = this.getAttribute("id");
  ddm_overItem[name] = true;
  var div = ddm_allItemsHash[name];
  var box = ddm_itemInBox[name];
  var ddm = ddm_itemToHandler[name];
  ddm.onMouseOverItem(div,box.level);
  if (box.level > 0)
  {
    var b = box;
    do
    {
      ddm.onMouseOverItem(b.parentItem,b.level-1);
      b = ddm_itemInBox[b.parentItem];
    }
    while (b != null);
  }
  ddm_handleEventsTO = setTimeout("ddm_handleEvents()",ddm.openDelay);
}

// private function
function ddm_onMouseOutItem()
{
  clearTimeout(ddm_handleEventsTO);
  var name = this.getAttribute("id");
  ddm_overItem[name] = null;
  var div = ddm_allItemsHash[name];
  var box = ddm_itemInBox[name];
  var ddm = ddm_itemToHandler[name];
  ddm.onMouseOutItem(div,box.level);
  ddm_handleEventsTO = setTimeout("ddm_handleEvents()",ddm.openDelay);
}

// private function
function ddm_openBox(parentItem,name)
{
  var box = ddm_allBoxesHash[name];
  if (ddm_openBoxes[box.level] == name) return;
  if (ddm_openBoxes[box.level] != null) ddm_closeBox(box.level);
  var ddm = ddm_itemToHandler[name];
  if (!ddm.positionBox(box.div,box.level,parentItem))
  {
    if (box.level == 1)
    {
      box.div.div.style.left = parentItem.getX()+"px";
      box.div.div.style.top = (parentItem.getY()+parentItem.getHeight())+"px";
    }
    else
    {
      box.div.div.style.left = (parentItem.getX()+parentItem.getWidth()+ddm.subOffsetX)+"px";
      box.div.div.style.top = (parentItem.getY()+ddm.subOffsetY)+"px";
    }
  }
  box.div.show();
  ddm_openBoxes[box.level] = name;
}

 // private function
function ddm_closeBox(level)
{
  for (var n=level; n<ddm_openBoxes.length; ++n)
  {
    if (ddm_openBoxes[n] != null)
    {
      var box = ddm_allBoxesHash[ddm_openBoxes[n]];
      box.div.hide();
      if (box.parentItem != null)
      {
        var ddm = ddm_itemToHandler[ddm_openBoxes[n]];
        ddm.onMouseOutItem(box.parentItem,box.level-1);
      }
      ddm_openBoxes[n] = null;
    }
  }
}

function DDMenuBox(menuHandler,level,boxName,itemPrefix,parentItem)
{
  this.name = boxName;
  this.div = getDiv(boxName);
  if (this.div == null) return;
  this.parentItem = parentItem;
  this.level = level;
  this.items = new Array(); // contains Div objects
  this.children = new Array(); // key=itemID, value=MenuBox

  {
    if (level > 0)
    {
      boxName += "_";
      itemPrefix += "_";
    }
    var n = 0;
    var it = null;
    var mb = null;
    ++level;
    while (1)
    {
      // yet another item?
      it = getDiv(itemPrefix+n);
      if (it == null) break;

      // yet another sub-box?
      mb = new DDMenuBox(menuHandler,level,boxName+n,itemPrefix+n,it);
      if (mb.div != null)
      {
        this.children[itemPrefix+n] = mb;
        ddm_allBoxesHash[boxName+n] = mb;
        ddm_itemToHandler[boxName+n] = menuHandler;
        // install event handlers
        mb.div.div.onmouseover = ddm_onMouseOverBox;
        mb.div.div.onmouseout = ddm_onMouseOutBox;
        //alert("box "+mb.name);
      }

      ddm_allItemsHash[itemPrefix+n] = it;
      ddm_itemInBox[itemPrefix+n] = this;
      ddm_itemToHandler[itemPrefix+n] = menuHandler;
      // install event handlers
      it.div.onmouseover = ddm_onMouseOverItem;
      it.div.onmouseout = ddm_onMouseOutItem;
      // add the item to this box
      this.items[this.items.length] = it.div;

      //if (level <= 1) alert("added "+itemPrefix+n+" level="+level);
      ++n;
    }
  }
}

