/********************************************************************

   TwoLvlMenu 3.11                                         2003-04-15



	Two level menu for IE4, NS4 or later. Uses version 2.13 of Slider.



   // Markus Gemstad

   gemstad@hotmail.com

   http://www.gemstad.com (references, samples etc)

********************************************************************/



// Global variables

var g_arrTwoLvlMenus = new Array();





// TwoLvlMenu(iTop, iLeft, iWidth, iZIndex, [iLvl2Offset])

function TwoLvlMenu(iTop, iLeft, iWidth, iZIndex, iLvl2Offset)

{

   // Public variables (settings)

   this.m_bSlide   = true; // Use slider (required that the slider.js file is included as well as this js file).

   this.m_bFormGet = true; // The menu posts a form when going to an url, the method 

                           // is "get" by default. Set to false to use "post" instead.



   this.m_iLvl1Space       = -4; // Space between level 1 items

   this.m_iLvl1ToLvl2Space = -4; // Space between level 1 and underlying level 2 item

   this.m_iLvl2Space       = -6; // Space between level 2 items

   this.m_iLvl2ToLvl1Space = 18; // Space between level 2 and underlying level 1 item



   // Slider settings

   this.m_iSliderSpeed           = 12; // How often the slider should update.

   this.m_iSliderCounterIncrease = 10;  // How long (pixels) the slider should move per update.



   // HTML code for menuitems. [menulink] will be replaced by the menu link.

   this.m_sLvl1Html    = "[menulink]";

   this.m_sLvl1HtmlSel = "[menulink]";

   this.m_sLvl2Html    = "[menulink]";

   this.m_sLvl2HtmlSel = "[menulink]";



   // Stylesheet classes for menuitems.

   this.m_sLvl1Class    = "txtLvl1";

   this.m_sLvl1ClassSel = "txtLvl1Selected";

   this.m_sLvl2Class    = "txtLvl2";

   this.m_sLvl2ClassSel = "txtLvl2Selected";

   

   // Private variables

   this.m_iObjIndex = g_arrTwoLvlMenus.length;

   g_arrTwoLvlMenus[g_arrTwoLvlMenus.length] = this;



   this.m_arrItems  = new Array();

   this.m_arrStore  = null;

   this.m_oMenuDiv  = null;

   this.m_bDisabled = false;



   this.m_iTop    = iTop;

   this.m_iLeft   = iLeft;

   this.m_iWidth  = iWidth;

   this.m_iZIndex = iZIndex;



   this.m_iLvl2Offset = (iLvl2Offset != null) ? iLvl2Offset : 0;



   this.m_iLvl1IdSel = null;

   this.m_iLvl2IdSel = null;



   // Public functions

   this.draw        = TwoLvlMenuDraw;        // Draw the menu. Call on this inside the body tag of your webpage.

   this.addLvl1Item = TwoLvlMenuAddLvl1Item; // Add level 1 item.

   this.addLvl2Item = TwoLvlMenuAddLvl2Item; // Add level 2 item.

   this.collapseAll = TwoLvlMenuCollapseAll; // Close all open level 1 items and deselect.

   this.sync        = TwoLvlMenuSync;        // Sync menu with an id



   // Private functions

   this.drawItem   = TwoLvlMenuDrawItem;

   this.getDivRef  = TwoLvlMenuGetDivRef;

   this.open       = TwoLvlMenuOpen;

   this.close      = TwoLvlMenuClose;

   this.click      = TwoLvlMenuClick;

   this.select     = TwoLvlMenuSelect;

   this.deSelect   = TwoLvlMenuDeSelect;

   this.getItem    = TwoLvlMenuGetItem;

   this.afterSlide = TwoLvlMenuAfterSlide;

}



// Do stuff after a slide, like showing children and opening level 1 item

function TwoLvlMenuAfterSlide(bOpen, iOpenId)

{

   if(this.m_arrStore != null)

   {

      for(var i=0; i<this.m_arrStore.length; i++)

      {

         this.m_arrStore[i][0].setTop(this.m_arrStore[i][1]);

         this.m_arrStore[i][0].setVisible(true);

      }

      this.m_arrStore  = null;

   }

   this.m_bDisabled = false;

   if(bOpen)

      this.open(iOpenId);

}



// Get reference to menuitem

function TwoLvlMenuGetItem(iId)

{

   if(iId == null) return;

   var oRetItem = null;

   var oItem    = null;

   for(var i=0; i<this.m_arrItems.length; i++)

   {

      oItem = this.m_arrItems[i];

      if(oItem.m_iId == iId)

      {

         oRetItem = oItem;

         break;

      }

      else

      {

         for(var i2=0; i2<oItem.m_arrChildren.length; i2++)

         {

            if(oItem.m_arrChildren[i2].m_iId == iId)

            {

               oRetItem = oItem.m_arrChildren[i2];

               break;

            }

         }

      }

   }

   return oRetItem;

}



// Add level 1 menu item

function TwoLvlMenuAddLvl1Item(iId, sName, sUrl, sTarget, sRunOnClick)

{

   var i = this.m_arrItems.length;

   this.m_arrItems[i] = new TwoLvlMenuItem(null, iId, sName, sUrl, sTarget, sRunOnClick);

}



// Add level 2 item

function TwoLvlMenuAddLvl2Item(iParentId, iId, sName, sUrl, sTarget, sRunOnClick)

{

   var oParent = this.getItem(iParentId);

   oParent.m_arrChildren[oParent.m_arrChildren.length] = new TwoLvlMenuItem(iParentId, iId, sName, sUrl, sTarget, sRunOnClick);

}



// Get reference to div tag

function TwoLvlMenuGetDivRef(sID)

{

   var oDiv;

   if(document.layers)

      oDiv = document.layers[sID];

   else if(document.getElementById)

      oDiv = document.getElementById(sID);

   else if(document.all)

      oDiv = document.all(sID);

   return oDiv;

}



// Close all open items

function TwoLvlMenuCollapseAll()

{

   var oItem = null;

   for(var i=0; i<this.m_arrItems.length; i++)

   {

      if(this.m_arrItems[i].m_bIsOpen)

         this.close(this.m_arrItems[i].m_iId);

   }

   this.deSelect(this.m_iLvl1IdSel, null, true);

   this.deSelect(this.m_iLvl2IdSel, null, true);

}



function TwoLvlMenuSync(iId)

{

   var oItem = this.getItem(iId);

   var bSlide = this.m_bSlide;

   if(oItem.m_iParentId != null) // Lvl2

   {

      this.m_bSlide = false;

      var oParent = this.getItem(oItem.m_iParentId);

      this.close(this.m_iLvl1IdSel, true, oParent.m_iId);

      this.deSelect(this.m_iLvl2IdSel, null, true);

      this.deSelect(this.m_iLvl1IdSel, null, true);

      this.select(null, oParent, false, true);

      this.select(null, oItem, false, true);

      this.m_bSlide = bSlide;

   }

   else // Lvl1

   {

      this.m_bSlide = false;

      this.close(this.m_iLvl1IdSel, true, iId);

      this.deSelect(this.m_iLvl2IdSel, null, true);

      this.deSelect(this.m_iLvl1IdSel, null, true);

      this.select(null, oItem, false, true);

      this.m_bSlide = bSlide;

   }

}



// Open item (show subitems)

function TwoLvlMenuOpen(iId)

{

   if(iId == null) return;



   var iStorePos, oItem, oChild, oSlider;



   var bItemAfter    = false;

   var iTop          = 0;

   var sRunOnDone    = "";

   var arrItemsAfter = new Array();



   // Find item

   for(var i=0; i<this.m_arrItems.length; i++)

   {

      oItem = this.m_arrItems[i];



      // If item has been found bItemAfter is true, add following items to arrItemsAfter array

      if(bItemAfter)

         arrItemsAfter[arrItemsAfter.length] = oItem;



      // If itemid=id and item has children

      if(oItem.m_iId == iId && oItem.m_arrChildren.length > 0)

      {

         bItemAfter      = true;

         oItem.m_bIsOpen = true;

         this.m_arrStore = new Array();



         iTop = oItem.m_iTop + oItem.m_iHeight + this.m_iLvl1ToLvl2Space;



         // We go through this to find out top for items after to slide/move to

         for(var i2=0; i2<oItem.m_arrChildren.length; i2++)

         {

            oChild    = oItem.m_arrChildren[i2];

            iStorePos = this.m_arrStore.length;



            // Store items and their top position for user after slide is complete

            this.m_arrStore[iStorePos]    = new Array();

            this.m_arrStore[iStorePos][0] = oChild;

            this.m_arrStore[iStorePos][1] = iTop;



            if(i2 < oItem.m_arrChildren.length-1)

               iTop += oChild.m_iHeight + this.m_iLvl2Space;

            else // If last child

               iTop += oChild.m_iHeight + this.m_iLvl2ToLvl1Space;

         }

      }

   }



   // Move/start slide of items after the one being opened

   if(arrItemsAfter.length > 0)

   {

      for(var i=0; i<arrItemsAfter.length; i++)

      {

         oItem = arrItemsAfter[i];

         if(this.m_bSlide)

         {

            if(i >= arrItemsAfter.length-1) // If last item in arrItemsAfter

            {

               sRunOnDone = "g_arrTwoLvlMenus["+this.m_iObjIndex+"].afterSlide(false,null);";

               this.m_bDisabled = true; // disable menu during slide

            }

            oSlider = new Slider(oItem.m_oDiv.id, sRunOnDone);

            oSlider.m_iSpeed           = this.m_iSliderSpeed;

            oSlider.m_iCounterIncrease = this.m_iSliderCounterIncrease;

            oSlider.m_iDegrees         = 90;

            oSlider.startSlide(null, iTop);

         }

         else

            oItem.setTop(iTop);

         iTop += oItem.m_iHeight + this.m_iLvl1Space;

      }

   }

   if(arrItemsAfter.length == 0 || !this.m_bSlide)

      this.afterSlide(false,null);

}



// Close item (hide subitems) - can call open on another item directly after slide

function TwoLvlMenuClose(iId, bOpenAfter, iOpenId)

{

   if(iId == null)

   {

      if(bOpenAfter && iOpenId != null)

         this.open(iOpenId);

      return;

   }

   if(bOpenAfter == null) // Fix for ie5

   {

      bOpenAfter = false;

      iOpenId = 0;

   }



   var iStorePos, oItem, oChild, oSlider;



   var bItemAfter    = false;

   var iTop          = 0;

   var sRunOnDone    = "";

   var arrItemsAfter = new Array();



   // Find item

   for(var i=0; i<this.m_arrItems.length; i++)

   {

      oItem = this.m_arrItems[i];



      // If item has been found bItemAfter is true, add following items to arrItemsAfter array

      if(bItemAfter)

         arrItemsAfter[arrItemsAfter.length] = oItem;



      if(oItem.m_iId == iId) // If itemid = id

      {

         iTop += oItem.m_iTop + oItem.m_iHeight + this.m_iLvl1Space;

         if(oItem.m_arrChildren.length > 0) // If item has children

         {

            bItemAfter      = true;

            oItem.m_bIsOpen = false;



            // Move children outside screen and hide

            for(var i2=0; i2<oItem.m_arrChildren.length; i2++)

            {

               oChild = oItem.m_arrChildren[i2];

               oChild.setTop(this.m_iTop);

               oChild.setVisible(false);

            }

         }

      }

   }



   // Move/start slide of items after the one being closed

   if(arrItemsAfter.length > 0)

   {

      for(var i=0; i<arrItemsAfter.length; i++)

      {

         oItem = arrItemsAfter[i];

         if(this.m_bSlide)

         {

            if(i >= arrItemsAfter.length-1) // If last item in arrItemsAfter

            {

               sRunOnDone = "g_arrTwoLvlMenus["+this.m_iObjIndex+"].afterSlide("+bOpenAfter+","+iOpenId+");";

               this.m_bDisabled = true; // disable menu during slide

            }

            oSlider = new Slider(oItem.m_oDiv.id, sRunOnDone);

            oSlider.m_iSpeed           = this.m_iSliderSpeed;

            oSlider.m_iCounterIncrease = this.m_iSliderCounterIncrease;

            oSlider.m_iDegrees         = 90;

            oSlider.startSlide(null, iTop);

            oItem.m_iTop = iTop;

         }

         else

            oItem.setTop(iTop);

         iTop += oItem.m_iHeight + this.m_iLvl1Space;

      }

   }

   if(arrItemsAfter.length == 0 || !this.m_bSlide)

      this.afterSlide(bOpenAfter,iOpenId);

}



// Select item (redraw and go to url)

function TwoLvlMenuSelect(iId, oTheItem, bGoToUrl, bDraw)

{

   if(iId == null && oTheItem == null) return;

   var oItem = (oTheItem == null) ? this.getItem(iId) : oTheItem;

   oItem.m_bIsSelected = true;

   if(bDraw && !document.layers) this.drawItem(null, oItem);

   if(bGoToUrl) oItem.click();

   (oItem.m_iParentId == null) ? this.m_iLvl1IdSel = oItem.m_iId : this.m_iLvl2IdSel = oItem.m_iId;

}



// Deselect item (redraw and go to url)

function TwoLvlMenuDeSelect(iId, oTheItem, bDraw)


{

   if(iId == null && oTheItem == null) return;

   var oItem = (oTheItem == null) ? this.getItem(iId) : oTheItem;

   oItem.m_bIsSelected = false;

   if(bDraw && !document.layers) this.drawItem(null, oItem);

   (oItem.m_iParentId == null) ? this.m_iLvl1IdSel = null : this.m_iLvl2IdSel = null;

}



// OnClick for menu items

function TwoLvlMenuClick(iId, bGoToUrl)

{

   if(this.m_bDisabled) return;



   var oItem = this.getItem(iId);

   if(oItem.m_iParentId == null) // Lvl1

   {

      if(iId == this.m_iLvl1IdSel && 

         oItem.m_arrChildren.length > 0) // Same as selected and has children

      {

         this.close(iId);

         this.deSelect(null, oItem, true);

      }

      else if(iId != this.m_iLvl1IdSel) // Not same as selected

      {

         this.close(this.m_iLvl1IdSel, true, iId); // Does open as well (after slide)

         this.deSelect(this.m_iLvl1IdSel, null, true);

         this.select(null, oItem, bGoToUrl, true);

      }

      else if(iId == this.m_iLvl1IdSel && bGoToUrl) // Same as selected without children

         oItem.click();

      this.deSelect(this.m_iLvl2IdSel, null, true);

   }

   else // Lvl2

   {

      if(!oItem.m_bIsSelected)

      {

         this.deSelect(this.m_iLvl2IdSel, null, true);

         this.select(null, oItem, bGoToUrl, true);

      }

      else if(bGoToUrl)

         oItem.click();

   }

}



// Draw a menu item

function TwoLvlMenuDrawItem(iId, oTheItem)

{

   var oItem     = (oTheItem == null) ? this.getItem(iId) : oTheItem;

   var oDiv      = oItem.m_oDiv;

   var sSel      = (oItem.m_bIsSelected) ? "Sel" : "";

   var sItemHtml = (oItem.m_iParentId == null) ? eval("this.m_sLvl1Html"+sSel)  : eval("this.m_sLvl2Html"+sSel);

   var sClass    = (oItem.m_iParentId == null) ? eval("this.m_sLvl1Class"+sSel) : eval("this.m_sLvl2Class"+sSel);

   var sHtml     = oItem.createInnerHtml(this.m_iObjIndex, sItemHtml, sClass);



   if(document.layers)

   {

      oDiv.document.open();

      oDiv.document.writeln(sHtml);

      oDiv.document.close();

   }

   else

      oDiv.innerHTML = sHtml;

}



// Draw the entire menu

function TwoLvlMenuDraw()

{

   var sMethod = (!this.m_bFormGet) ? "post" : "get";

   var sHtml   = "<FORM NAME=frmTwoLvlMenu METHOD="+sMethod+"><INPUT TYPE=hidden></FORM>";

   var sNsFix  = (document.layers) ? "<DIV ID=divTwoLvlMenuNs4Fix style=\"position:absolute; left:-1px; top:-1px; height:1px; width:1px\"></div>" : "";

   var oItem   = null;

   var oChild  = null;



   for(var i=0; i<this.m_arrItems.length; i++)

   {

      oItem = this.m_arrItems[i];

      sHtml += oItem.createDivHtml(this.m_iObjIndex, this.m_iTop, this.m_iLeft, this.m_iWidth, this.m_iZIndex, this.m_sLvl1Html, this.m_sLvl1Class);

      for(var i2=0; i2<oItem.m_arrChildren.length; i2++)

      {

         oChild = oItem.m_arrChildren[i2];

         sHtml += oChild.createDivHtml(this.m_iObjIndex, this.m_iTop, this.m_iLeft+this.m_iLvl2Offset, this.m_iWidth-this.m_iLvl2Offset, this.m_iZIndex, this.m_sLvl2Html, this.m_sLvl2Class);

      }

   }



   // Draw menu (all is hidden)

   document.writeln(sNsFix + sHtml);



   // Fix position, get/set height and show items

   var iItemTop = this.m_iTop;

   var iHeight  = 0;

   for(var i=0; i<this.m_arrItems.length; i++)

   {

      oItem        = this.m_arrItems[i];

      oItem.m_oDiv = this.getDivRef("divTwoLvlMenu"+oItem.m_iId);



      oItem.setTop(iItemTop);

      oItem.m_iHeight = (document.layers) ? oItem.m_oDiv.clip.height : oItem.m_oDiv.offsetHeight;



      for(var i2=0; i2<oItem.m_arrChildren.length; i2++)

      {

         oChild = oItem.m_arrChildren[i2];

         oChild.m_oDiv = this.getDivRef("divTwoLvlMenu"+oChild.m_iId);

         oChild.m_iHeight = (document.layers) ? oChild.m_oDiv.clip.height : oChild.m_oDiv.offsetHeight;

      }



      iItemTop = iItemTop + oItem.m_iHeight + this.m_iLvl1Space;

      oItem.setVisible(true);

   }

}



/*********************************************************/



// TwoLvlMenuItem class constructor

function TwoLvlMenuItem(iParentId, iId, sName, sUrl, sTarget, sRunOnClick)

{

   this.m_iParentId   = iParentId;

   this.m_iId         = iId;

   this.m_sName       = sName;

   this.m_sUrl        = sUrl;

   this.m_sTarget     = sTarget;

   this.m_sRunOnClick = sRunOnClick;



   this.m_oDiv        = null;

   this.m_iHeight     = null;

   this.m_iTop        = null;



   this.m_bIsOpen     = false;

   this.m_bIsSelected = false;

   this.m_arrChildren = new Array();



   this.createDivHtml   = TwoLvlMenuItemCreateDivHtml;

   this.createInnerHtml = TwoLvlMenuItemCreateInnerHtml;

   this.click           = TwoLvlMenuItemClick;

   this.setTop          = TwoLvlMenuItemSetTop;

   this.setVisible      = TwoLvlMenuItemSetVisible;

}



function TwoLvlMenuItemSetVisible(bShow)

{

   var oDiv = (document.layers) ? this.m_oDiv : this.m_oDiv.style;

   if(bShow)

      oDiv.visibility = (document.layers) ? "show" : "visible";

   else

      oDiv.visibility = (document.layers) ? "hide" : "hidden";

}



function TwoLvlMenuItemSetTop(iTop)

{

   if(document.layers)

      this.m_oDiv.top = iTop;

   else

      this.m_oDiv.style.top = iTop;

   this.m_iTop = iTop;

}



// Go to url and run sRunOnClick

function TwoLvlMenuItemClick()

{

   // Use form to goto url (in target)

   if(this.m_sUrl)

   {

      var oForm = document.forms["frmTwoLvlMenu"];

      oForm.action = this.m_sUrl;

      if(this.m_sTarget)

         oForm.target = this.m_sTarget;

      oForm.submit();

   }



   // Run extra function

   if(this.m_sRunOnClick)

      eval(this.m_sRunOnClick);

}



// Make the divs inner html for this item

function TwoLvlMenuItemCreateInnerHtml(iObjIndex, sItemHtml, sClass)

{

   var sHtml     = "";

   var sLinkHtml = "";

   var sOnClick  = "return false;";

   var oRe       = /\[menulink\]/g;



   sOnClick  = "g_arrTwoLvlMenus["+iObjIndex+"].click('" + this.m_iId + "', true);" + sOnClick;

   sLinkHtml = "<A HREF=\"#\" onClick=\"" + sOnClick + "\" onFocus=\"this.blur();\" CLASS=\"" + sClass + "\">" + this.m_sName + "</A>";



   sHtml = sItemHtml.replace(oRe, sLinkHtml);



   return sHtml;

}



// Make the html for the div

function TwoLvlMenuItemCreateDivHtml(iObjIndex, iTop, iLeft, iWidth, iZIndex, sItemHtml, sClass)

{

   var sStyle     = ""

   var sDiv       = "";

   var sInnerHtml = this.createInnerHtml(iObjIndex, sItemHtml, sClass);



   // DIV style properties

   sStyle  = "position:absolute;";

   sStyle += "top:" + iTop + "px;";

   sStyle += "left:" + iLeft + "px;";

   sStyle += "width:" + iWidth + "px;";

   sStyle += "z-index:" + iZIndex + ";";

   sStyle += "visibility:hidden;";



   // Put them all together

   sDiv = "<DIV ID=\"divTwoLvlMenu" + this.m_iId + "\" STYLE=\"" + sStyle + "\">" + sInnerHtml + "</DIV>\n"



   return sDiv;

}
