/*---------------------------------------------------------------------------\
|                            Menu Control v3.0.1                             |
|----------------------------------------------------------------------------|
| Author: Dan Sutton                                                         |
| Date:   October 3rd, 2008                                                  |
|----------------------------------------------------------------------------|
| Dependencies: menu.css                                                     |
|----------------------------------------------------------------------------|
| This provides a menu control which displays vertically-arranged menus with |
| nested submenus. Elements on a menu can respond to onClick events, or can  |
| contain HREF-style links. "menus.lastSelected" returns the menu item last  |
| selected by the user.                                                      |
|----------------------------------------------------------------------------|
| Example:                                                                   |
|                                                                            |
|  // Create a Main Menu                                                     |
|  var m=menus.addMenu();                                                    |
|                                                                            |
|  // Add an HREF                                                            |
|  m.addMenuItem("London Telegraph", "http://www.telegraph.co.uk");          |
|                                                                            |
|  // Add an element with an "onClick" method                                |
|  m.addMenuItem("An Alert", null, function(){alert("This is an Alert!");}); |
|                                                                            |
|  // Add a submenu                                                          |
|  var s1=m.addSubMenu("Other Items");                                       |
|                                                                            |
|  // Add an element to the Submenu                                          |
|  s1.addMenuItem("CNN", "http://www.cnn.com");                              |
|                                                                            |
|  // Output the Menu                                                        |
|  document.write(m);                                                        |
|                                                                            |
|  // Write the menu into an existing DIV                                    |
|  var d=document.getElementById("myDiv");                                   |
|  d.innerHTML=m.toString();                                                 |
|----------------------------------------------------------------------------|
| Reserved Identifiers:                                                      |
|   menus, menuElement, menuItem, menu, subMenu, mainMenu                    |
|                                                                            |
| Reserved Class Identifiers:                                                |
|   .menuItemClass, .mainmenuItemClass, .menuDiv, .menuTable, .menuTD        |
|----------------------------------------------------------------------------|
| Javascript Object Inheritance Hierarchy                                    |
|                                                                            |
|  menus                                                                     |
|                +--> menuItem --> subMenu                                   |
|  menuElement --|                                                           |
|                +--> menu --> mainMenu                                      |
\---------------------------------------------------------------------------*/

// Control variable for Menus
var menus =
{
  nextElement: 1, 		                          // Unique number for element IDs
  items: [], 		                                // Menus Defined
  registry: [], 		                            // All elements, by ID
  lastSelected: null, 	                        // Last-selected item
  images: "/images/menus/", 										// Images directory
  focused: false,                               // States whether an input item is focused

  // Register an Element in the Registry
  register: function(e)
  {
    menus.registry[e.id] = e;
  },

  // event: Highlight the given Element
  highlight: function(id, noselect, nohighlight)
  {
    menus.registry[id].highlight(noselect, nohighlight);
  },

  // event: Unhighlight the given Element
  unHighlight: function(id)
  {
    menus.registry[id].unHighlight();
  },

  // event: Process onClick for an element
  doOnClick: function(id)
  {
    menus.registry[id].doOnClick();
  },

  // Add a Menu to the list
  addMenu: function()
  {
    var m = new mainMenu();
    this.items[this.items.length] = m;
    return m;
  },

  // Add a Menu Strip to the list
  addMenuStrip: function()
  {
    var m = new menuStrip();
    this.items[this.items.length] = m;
    return m;
  },

  // event: Process lostFocus event for a menu
  lostFocus: function(mm)
  {
    var m = menus.registry[mm];
    if (!m.inMenus)
      m.putAway();
  },

  // return the absolute TOP of something
  getElementTop: function(elem)
  {
    var yPos = elem.offsetTop;
    var tempEl = elem.offsetParent;
    while (tempEl)
    {
      yPos += tempEl.offsetTop - (tempEl.scrollTop ? tempEl.scrollTop : 0);
      tempEl = tempEl.offsetParent;
    }
    return yPos;
  },

  // Return the absolute LEFT of something.
  getElementLeft: function(elem)
  {
    var xPos = elem.offsetLeft;
    var tempEl = elem.offsetParent;
    while (tempEl)
    {
      xPos += tempEl.offsetLeft - (tempEl.scrollLeft ? tempEl.scrollLeft : 0);
      tempEl = tempEl.offsetParent;
    }
    return xPos;
  },

  // Bring the given element to the front
  bringToFront: function(obj, objs)
  {
    var d = document.getElementsByTagName("div");
    var t = 0;
    for (var i = 0; i < d.length; i++)
    {
      var x = d[i];
      if (!((x == obj) || (x.style.zIndex == '')))
      {
        var c = parseInt(x.style.zIndex);
        if (t < c)
          t = c;
      }
    }
    objs.style.zIndex = t + 1;
    obj.style.zIndex = t + 2;
  }
};

// A menu Item
function menuItem(owner, text, href, onclick)
{
	this.id="me_"+(menus.nextElement++);
	this.mpid="mp_"+this.id;
	this.owner=owner;
	var p=this;
	while (p.owner)
		p=p.owner;
	this.mainmenu=p;
	this.afterSpacer=false; // Does item appear after a spacer (menu strips)?
	this.text=text;
	this.href=href;
	this.onclick=onclick;
	menus.register(this);
}

menuItem.prototype.toString=function(isMain,isMenuStrip)
{
	var html="<tr class='"+(isMain && !isMenuStrip? "main" : "")+"menuItemClass'>"
	 +(this.href? "<a href=\""+this.href+"\">" : "")
	 +"<td class='menuTD' nowrap id='"+this.id+"' nowrap "
	 +"onmouseover='javascript:menus.highlight(\""+this.id+"\");'"
	 +" onmouseout='javascript:menus.unHighlight(\""+this.id+"\");'"
	 +" onmousedown='javascript:this.className=\"menuTDDn\";'"
	 +" onmouseup='javascript:this.className=\"menuTDH\";'"
	 +" onclick='javascript:menus.doOnClick(\""+this.id+"\");'>"
	 +(isMain? "<b>":"")
	 +(isMenuStrip? "&nbsp;":"")
	 +this.text//.replace("<","&lt;")
	 +(isMenuStrip? "&nbsp;":"")
	 +(isMain? "</b>":"")
	 +"</td>"+(this.href? "</a>" : "")
	 +(isMenuStrip? "" : "<td id='"+this.mpid+"' class='menuPos' nowrap></td>")
	 +"</tr>";
	return html;
};

menuItem.prototype.highlight = function(nofocus, nohighlight)
{
  this.mainmenu.inMenus = true;
  if (!nofocus)
  {
    var x = document.getElementById("f_" + this.mainmenu.id);
    x.focus();
  }
  var y = document.getElementById(this.id);
  y.className = "menuTD" + (nohighlight ? "" : "H");
};

menuItem.prototype.unHighlight=function()
{
	this.mainmenu.inMenus=false;
	var x=document.getElementById(this.id);
	x.className="menuTD";
};

menuItem.prototype.doOnClick=function()
{
	this.mainmenu.putAway();
	menus.lastSelected=this;
	if (this.onclick)
		this.onclick();
};

// Menu for submenus
function menu(owner)
{
	this.id="me_"+(menus.nextElement++);
	this.mpid="mp_"+this.id;
	this.owner=owner;
	var p=this;
	while (p.owner)
		p=p.owner;
	this.mainmenu=p;
	this.afterSpacer=false; // Does item appear after a spacer (menu strips)?
	this.shadow=this.id+"_sh";
	this.items=[];
	menus.register(this);
};
	
menu.prototype.addElement=function(e)
{
	this.items[this.items.length]=e;
	return e;
};

menu.prototype.toString=function()
{
	var html="<div class='menuShadowDiv"+(popupControl.ie6? "_msie":"")+"'"
 	 +" id='"+this.shadow+"'>&nbsp;</div>"
 	 +"<div id='"+this.id+"' class='menuDiv'>"
	 +"<table class='menuTable' cellpadding=0 cellspacing=0>";
	for (i in this.items)
		html+=this.items[i].toString();
	return html+"</table></div>";
};

menu.prototype.show = function(parentIsInMenuStrip)
{
  var d = document.getElementById(this.id);
  if (parentIsInMenuStrip)
  {
    var p = document.getElementById(this.owner.id);
    var x = menus.getElementLeft(p);
    var y = menus.getElementTop(p);
    d.style.top = parseFloat(y) + parseFloat(p.offsetHeight);
    d.style.left = x;
  }
  else
  {
    var p = document.getElementById(this.owner.mpid);
    var x = menus.getElementLeft(p);
    var y = menus.getElementTop(p);
    d.style.top = y + 2;
    d.style.left = x - 2;
  }
  var s = document.getElementById(this.shadow);
  s.style.visibility = "visible";
  d.style.visibility = "visible";
  s.style.top = d.offsetTop + 2;
  s.style.left = d.offsetLeft + 2;
  try
  {
    s.style.width = d.offsetWidth - 1;
    s.style.height = d.offsetHeight;
  }
  catch (e) { }
  menus.bringToFront(d, s); // necessary for Safari

  // Look for input subitems which have "select" marked on, and focus on the textbox if found
  var f = false;
  for (var i = 0; (i < this.items.length) && (!f); i++)
  {
    try
    {
      if (this.items[i].select)
      {
        f = true;
        var t = document.getElementById(this.items[i].inputID);
        t.focus();
      }
    }
    catch (e) { } 
  }
};

menu.prototype.hide=function()
{
	var d=document.getElementById(this.id);
	d.style.visibility="hidden";
	var s=document.getElementById(this.shadow);
	s.style.visibility="hidden";
};

menu.prototype.putAway=function()
{
	for (i in this.items)
		try
		{
			this.items[i].putAway();
		}
		catch(e){}
	this.hide();
};

menu.prototype.addMenuItem=function(text, href, onclick)
{
	var i=new menuItem(this, text, href, onclick);
	this.addElement(i);
	return i;
};

menu.prototype.addInputItem = function(text, width, href, onclick, select)
{
  var x = new menuInput(this, text, width, href, onclick, select);
  this.addElement(x);
  return x;
};

menu.prototype.addSubMenu = function(text)
{
  var s = new subMenu(this, text);
  this.addElement(s);
  return s;
};
	
// SubMenu (subclassed from menuItem)
function subMenu(owner, text)
{
	this.id="me_"+(menus.nextElement++);
	this.mpid="mp_"+this.id;
	this.owner=owner;
	var p=this;
	while (p.owner)
		p=p.owner;
	this.mainmenu=p;
	this.afterSpacer=false; // Does item appear after a spacer (menu strips)?
	this.text=text;
	this.menuUp=false;
	this.menu=new menu(this);
	menus.register(this);
};
subMenu.prototype=new menuItem;

subMenu.prototype.onclick=function()
{
	this.subMenuClick();
};

subMenu.prototype.toString=function(isMain,isMenuStrip)
{
	var html="<tr class='"+(isMain && !(isMenuStrip)? "main" : "")
	 +"menuItemClass'>"
	 +(this.href? "<a href=\""+this.href+"\">" : "")
	 +"<td class='menuTD' nowrap id='"+this.id+"' "
	 +"onmouseover='javascript:menus.highlight(\""+this.id+"\",menus.focused);'"
	 +" onmouseout='javascript:menus.unHighlight(\""+this.id+"\");'"
	 +" onmousedown='javascript:this.className=\"menuTDDn\";'"
	 +" onmouseup='javascript:this.className=\"menuTDH\";'"
	 +" onclick='javascript:menus.doOnClick(\""+this.id+"\");'>"
	 +"<table cellspacing=0 cellpadding=0 border=0 width='100%' class='smtable'><tr><td nowrap>"
	 +(isMain? "<b>":"")
	 +(isMenuStrip? "&nbsp;":"")
	 +this.text.replace("<","&lt;")
	 +(isMenuStrip? "&nbsp;":"")
	 +(isMain? "</b>":"")
	 +(this.href? "</a>" : "")
	 +"</td>"+(isMenuStrip? "" : "<td align='right'><img src='images/sm_arrow.gif'></td>")
	 +"</tr></table>"
	 +"</td>"+(isMenuStrip? "" : "<td id='"+this.mpid+"' class='menuPos' nowrap></td>")
	 +"</tr>";
	return html;
};

subMenu.prototype.addElement=function(e)
{
	return this.menu.addElement(e);
};

subMenu.prototype.subMenuClick=function()
{
	if (this.menuUp)
		this.menu.hide();
	else
		this.menu.show(this.owner.isMenuStrip);
	this.menuUp=!this.menuUp;
};

subMenu.prototype.menuHighlight=function()
{
	this.mainmenu.inMenus=true;
	var x=document.getElementById("f_"+this.mainmenu.id);
	x.focus();
	var x=document.getElementById(this.id);
	x.className="menuTDH";
};

subMenu.prototype.unHighlight=function(id)
{
	this.mainmenu.inMenus=false;
	var x=document.getElementById(this.id);
	x.className="menuTD";
};

subMenu.prototype.doOnClick=function()
{
	var x=document.getElementById("f_"+this.mainmenu.id);
	x.focus();
	var mu=this.menuUp;
	try // put away other items on Main Menu, if applicable
	{
		for (i in this.owner.items)
			try
			{
				this.owner.items[i].putAway();
			}
			catch(e){}
	}
	catch(e){}
	try // Put away other items on submenus, if applicable
	{
		for (i in this.owner.menu.items)
			try
			{
				this.owner.menu.items[i].putAway();
			}
			catch(e){}
	}
	catch(e){}
	this.menuUp=mu;
	if (this.onclick)
		this.onclick();
};

subMenu.prototype.putAway=function()
{
	if (this.menuUp)
	{
		this.menu.putAway();
		this.menuUp=false;
	}
};

subMenu.prototype.addMenuItem=function(text, href, onclick)
{
	return this.menu.addMenuItem(text, href, onclick);
};

subMenu.prototype.addInputItem = function(text, width, href, onclick, select)
{
  return this.menu.addInputItem(text, width, href, onclick, select);
};

subMenu.prototype.addSubMenu = function(text)
{
	return this.menu.addSubMenu(text);
};

// Main Menu (subclassed from menu)
function mainMenu()
{
	this.id="me_"+(menus.nextElement++);
	this.mpid="mp_"+this.id;
	this.owner=null;
	var p=this;
	while (p.owner)
		p=p.owner;
	this.mainmenu=p;
	this.afterSpacer=false; // Does item appear after a spacer (menu strips)?
	this.shadow=this.id+"_sh";
	this.items=[];
	this.inMenus=false;
	menus.register(this);
};
mainMenu.prototype=new menu;

mainMenu.prototype.toString=function()
{
	var html="<table class='menuTable' cellpadding=2 cellspacing=0 id='"+this.id+"'>";
	for (i in this.items)
		html+=this.items[i].toString(true);
	html+="</table>";
	for (var i=0; i<this.items.length; i++)
		html+=this.menusToString(this.items[i]);
	html+="<div style='position:absolute;top:0;left:0;'>"
	 +"<input type='text' class='menuInput' readonly=true"
	 +" name='f_"+this.id+"' id='f_"+this.id+"'"
	 +" onblur='javascript:menus.lostFocus(\""+this.id+"\");'>"
	 +"</div>";
	return html;
};

mainMenu.prototype.menusToString=function(e)
{
	var s="";
	if (e.menu)
	{
		s+=e.menu.toString();
		for (i in e.menu.items)
			s+=this.menusToString(e.menu.items[i]);
	}
	return s;
};

mainMenu.prototype.show=function(){};
mainMenu.prototype.hide=function(){};

// Main Menu Strip (subclassed from mainMenu)
function menuStrip()
{
	this.id="me_"+(menus.nextElement++);
	this.mpid="mp_"+this.id;
	this.owner=null;
	var p=this;
	while (p.owner)
		p=p.owner;
	this.mainmenu=p;
	this.afterSpacer=false; // Does item appear after a spacer (menu strips)?
	this.shadow=this.id+"_sh";
	this.items=[];
	this.inMenus=false;
	this.isMenuStrip=true;
	menus.register(this);
};
menuStrip.prototype=new mainMenu;

menuStrip.prototype.height = function()
{
  var x = document.getElementById(this.id);
  if (x)
    return x.offsetHeight;
  else
    return 0;
};

menuStrip.prototype.toString=function()
{
	var html="<table cellpadding=0 cellspacing=0 border=0 id='"+this.id+"' width='100%' class='menuStrip'>"
	 +"<tr><td class='menuFiller'>&nbsp;</td>"
	for (i in this.items)
		if (!this.items[i].afterSpacer)
			html+="<td><table cellspacing=0 cellpadding=0 border=0>"+this.items[i].toString(true,true)+"</table></td>";
	html+="<td width='100%' class='menuFiller'>&nbsp;</td>";
	var afs=false;
	for (i in this.items)
		if (this.items[i].afterSpacer)
		{
			html+="<td><table cellspacing=0 cellpadding=0 border=0>"+this.items[i].toString(true,true)+"</table></td>";
			afs=true;
		}
	if (afs)
		html+="<td class='menuFiller'>&nbsp;</td>";
	html+="</tr></table>";
	for (i in this.items)
		html+=this.menusToString(this.items[i]);
	html+="<div style='position:absolute;top:0;left:0;'>"
	 +"<input type='text' class='menuInput' readonly=true"
	 +" name='f_"+this.id+"' id='f_"+this.id+"'"
	 +" onblur='javascript:menus.lostFocus(\""+this.id+"\");'>"
	 +"</div>";
	return html;

};

// Class for a menu item with an Input box
function menuInput(owner, text, width, href, onclick, select)
{
  this.id = "me_" + (menus.nextElement++);
  this.mpid = "mp_" + this.id;
  this.inputID = "mtxt_" + this.id;
  this.owner = owner;
  this.select = select;
  var p = this;
  while (p.owner)
    p = p.owner;
  this.mainmenu = p;
  this.afterSpacer = false; // Does item appear after a spacer (menu strips)?
  this.prompt = text;
  this.text = "<form method='post' action='javascript:void(0);' class='menuForm'"
   + " onsubmit='javascript:menus.doOnClick(\"" + this.id + "\");return false;'>"
   + "<table cellspacing=0 cellpadding=2 border=0><tr>"
   + (this.prompt ? "<td nowrap class='menuInputTD'>" + this.prompt + "</td>" : "")
   + "<td><input type='text' id='" + this.inputID + "' name='" + this.inputID + "'"
   + " size='" + width + "' class='.menuTextBox'"
   + " onfocus='javascript:menus.highlight(\"" + this.id + "\",true,true);menus.focused=true;'"
   + " onblur='javascript:menus.lostFocus(\"" + this.mainmenu.id + "\");menus.focused=false;'>"
   + "</td><td class='menuInputTD'><input type='image' class='menuIcon' src='" + menus.images + "go.png'>"
   + " </td></tr></table></form>";
  this.href = href;
  this.onclick = onclick;
  menus.register(this);
}

// toString for the menu input
menuInput.prototype.toString = function(isMain, isMenuStrip)
{
  var html = "<tr class='" + (isMain && !isMenuStrip ? "main" : "")
	 + "menuItemClass'>"
	 + (this.href ? "<a href=\"" + this.href + "\">" : "")
	 + "<td class='menuTD' nowrap id='" + this.id + "' nowrap "
	 + "onmouseover='javascript:menus.highlight(\"" + this.id + "\",true);'"
	 + " onmouseout='javascript:menus.unHighlight(\"" + this.id + "\");'>"
	 + (isMain ? "<b>" : "")
	 + (isMenuStrip ? "&nbsp;" : "")
	 + this.text//.replace("<","&lt;")
	 + (isMenuStrip ? "&nbsp;" : "")
	 + (isMain ? "</b>" : "")
	 + "</td>" + (this.href ? "</a>" : "")
	 + (isMenuStrip ? "" : "<td id='" + this.mpid + "' class='menuPos' nowrap></td>")
	 + "</tr>";
  return html;
};

// Returns the value from the Text Box
menuInput.prototype.getValue = function()
{
  var r = null;
  try
  {
    var x = document.getElementById(this.inputID);
    r = x.value;
  }
  catch (e) { }
  return r;
};

// Sets the Value of the Text Box
menuInput.prototype.setValue = function(value)
{
  try
  {
    var x = document.getElementById(this.inputID);
    x.value = value;
  }
  catch (e) { }
};

// Methods which work the same as menuItem
menuInput.prototype.highlight = menuItem.prototype.highlight;
menuInput.prototype.unHighlight = menuItem.prototype.unHighlight;
menuInput.prototype.doOnClick = menuItem.prototype.doOnClick;