﻿//http://javascript.crockford.com/private.html
//http://www.javascriptkit.com/javatutors/oopjs2.shtml
//http://mckoss.com/jscript/object.htm


//Link about positioning elements
//http://www.barelyfitz.com/screencast/html-training/css/positioning/


//Going to rewrite this from scratch so that we can support sub menus
function MenuManager()
{
  var Name = "";
  var MenuItems = new Array();
  
  //These are globals used to control the delay for when the menu is shown or hidden
  var MainShowSetTimeOut;
  var TIMEOUT_DISPLAY = 500;
  var TIMEOUT_HIDE = 500;

  var LeftOffSet = 0;
  var UseLeftOffSet = false;

  this.AttachMenu = function(parentID, childID, location)
  {
    //We check to make sure that both the parent and child control exists
    if (document.getElementById(parentID) == null) { return; }
    if (document.getElementById(childID) == null) { return; }

    var tvIndex = MenuItems.length;
    var tvMenuElement = new MenuElement(parentID, childID, location);
    MenuItems[tvIndex] = tvMenuElement;

    var tvParent = tvMenuElement.ParentControl;
    var tvChild = tvMenuElement.ChildControl;
    var tvMainShowSetTimeOut;

    //http://codingforums.com/archive/index.php?t-17718.html          
    var obj = this;

    //This is getting quiet a bit harder to get the delay happening
    tvParent.onmouseover = function()
    {
      //We clear any previous timeout
      //document.getElementById("debug").value = "C:" + obj.MainShowSetTimeOut + "\n" + document.getElementById("debug").value;
      //document.getElementById("debug").value = "TD:" + TIMEOUT_DISPLAY + "\n" + document.getElementById("debug").value;
      
      clearTimeout(obj.MainShowSetTimeOut);

      obj.MainShowSetTimeOut = setTimeout(
        function()
        {
          obj.ShowMenu(tvMenuElement)
        }, TIMEOUT_DISPLAY);

      //document.getElementById("debug").value = "S:" + obj.MainShowSetTimeOut + "\n" + document.getElementById("debug").value;
    };

    tvParent.onmouseout = function()
    {
      //document.getElementById("debug").value = "H:" + obj.MainShowSetTimeOut + "\n" + document.getElementById("debug").value;
      clearTimeout(obj.MainShowSetTimeOut); 
      obj.HideMenu(); 
    };

    tvChild.onmouseover = function() { obj.ShowMenu(tvMenuElement) };
    tvChild.onmouseout = function() { obj.HideMenu() };


    //***    document.getElementById('debug').value += "tvIndex: " + tvIndex + "\n";
    if (tvIndex > 0)
    {
      //Sub menu 
      //This is super complicated this is what we are facing to link up the current menu to the parent
      /*
      this.ivMenuItems = [{p1, c1},{p2, c2}]
      the div structure would appear something like
      <div id=p1></div>
      <div id=c1>
      <div id=p2>
      </div>

      <div id=c2></div>

      the goal is want to link p2 to c2.
      note there could be additional elements around <div id=p2> which we have to bubble through
      */


      var tvParentFound = false;
      var tvParent = tvMenuElement.ParentControl;     //This gets us the p2
      //***      document.getElementById('debug').value += "tvParent.id: " + tvParent.id + "\n";
      //***      document.getElementById('debug').value += "tvParent.parentNode.id: " + tvParent.parentNode.id + "\n";
      while (tvParentFound == false)
      {
        //We walk through all the menus that we are tracking 
        for (i = 0; i < MenuItems.length; i++)
        {
          //check to see if p2.parent.id = c1.id
          if (MenuItems[i].ChildID == tvParent.parentNode.id)
          {
            tvMenuElement.ParentMenuElement = MenuItems[i];
            tvParentFound = true;

            //***            document.getElementById('debug').value += tvMenuElement.ParentID + "\n";
            //***            document.getElementById('debug').value += "  " + tvMenuElement.ParentMenuElement.ParentID + "\n";
          }
        }
        //We jump one nested element higher in our case to c1
        tvParent = tvParent.parentNode;
      }
    }

    return tvMenuElement;
  }

  //----
  //This method is very similar to the above one excep the item is aligned on the right hand side
  this.AttachMenuAligned = function(parentID, childID, location, alignment)
  {
    var tvMenuElement = this.AttachMenu(parentID, childID, location);
    if (tvMenuElement == null) { return; }
    tvMenuElement.Alignment = alignment;
  }
  //----

  this.SetLeftOffSet = function(leftOffSet)
  {
    LeftOffSet = leftOffSet;
    UseLeftOffSet = true;  
  }

  this.ShowMenu = function(menuElement)
  {
    //These two are identical
    //menuElement.ParentID + " " + this.ivMenuItems[0].ParentID);

    //At this point I do know which menus I want to show
    //So i know which TimeOuts to clear.
    var tvMenuElement = menuElement;
    while (tvMenuElement != null)
    {
      clearTimeout(tvMenuElement.TimeOutID);
      tvMenuElement = tvMenuElement.ParentMenuElement;
    }

    var tvParent = menuElement.ParentControl;
    var tvChild = menuElement.ChildControl;

    var tvTop = 0;
    var tvLeft = 0;

    if (menuElement.Location == "down")
    {
      tvTop = tvParent.offsetHeight;
    }
    else if (menuElement.Location == "left")
    {
      tvLeft = tvParent.offsetWidth + 1;
    }

    //We still have to bubble up through the parent layers but only up till we run into the parent relative item
    for (; tvParent; tvParent = tvParent.offsetParent)
    {
      if (this.DoesElementExist(tvParent.id))
      {
        tvTop += tvParent.offsetTop;
        tvLeft += tvParent.offsetLeft;
        //document.getElementById('debug').value += tvParent.id + " - " + tvParent.offsetTop + "\n";
      }
    }

    if (UseLeftOffSet)
    {
      tvLeft = LeftOffSet;
    }

    //Here I also want to set the alignment of the element;
    if (menuElement.Alignment == "right")
    {
      tvChild.style.position = "absolute";
      tvChild.style.top = tvTop + 'px';
      tvChild.style.right = (document.body.offsetWidth - tvLeft - menuElement.ParentControl.offsetWidth) + 'px';
      tvChild.style.left = "auto";
      tvChild.style.display = "block";
      tvChild.style.visibility = "visible";
    }
    else
    {
      tvChild.style.position = "absolute";
      tvChild.style.top = tvTop + 'px';
      tvChild.style.left = tvLeft + 'px';
      tvChild.style.display = "block";
      tvChild.style.visibility = "visible";
    }
  }


  //We hide all menus, since we do not know if the user moved from 
  //a main menu to a sub menu 
  //a sub menu to a main menu
  //a main menu to the page
  //a sub menu to the page    
  this.HideMenu = function()
  {
    for (i = 0; i < MenuItems.length; i++)
    {
      //clear out any previous hide commands. With submenus the container and the menu item can fire a hide
      //Which is 2 hide but the submenu is only generating one show, and hence the menu disappears
      clearTimeout(MenuItems[i].TimeOutID);

      //document.getElementById("debug").value = "TH:" + TIMEOUT_HIDE + "\n" + document.getElementById("debug").value;

      var tvCode = "  document.getElementById('" + MenuItems[i].ChildID + "').style.display = 'none';";
      MenuItems[i].TimeOutID = setTimeout(tvCode, TIMEOUT_HIDE);
    }
  }

  this.CloseMenu = function()
  {
    for (i = 0; i < MenuItems.length; i++)
    {
      //clear out any previous hide commands. With submenus the container and the menu item can fire a hide
      //Which is 2 hide but the submenu is only generating one show, and hence the menu disappears
      clearTimeout(MenuItems[i].TimeOutID);
      document.getElementById(MenuItems[i].ChildID).style.display = 'none';
    }
  }

  //This is used to return a menu element so that we can manually display a menu item
  this.FindMenuElementByChildID = function(childID)
  {
    for (i = 0; i < MenuItems.length; i++)
    {
      if (MenuItems[i].ChildID == childID)
      {
        return MenuItems[i];
      }
    }
    return null;
  }

  this.DoesElementExist = function(id)
  {
    for (i = 0; i < MenuItems.length; i++)
    {
      if ((MenuItems[i].ParentID == id) ||
          (MenuItems[i].ChildID == id))
      {
        return true;
      }
    }
    return false;
  } 
}


function MenuElement(parentID, childID, location)
{
  this.TimeOutID = null;
  this.ParentID = parentID;
  this.ChildID = childID;
  this.Location = location;
  this.ParentControl = document.getElementById(parentID);
  this.ChildControl = document.getElementById(childID);
  this.Alignment = "left";

  //We need a link back to the parent so that we can keep it visible 
  this.ParentMenuElement = null;
}
