Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / XHTML

Sliding JavaScript Menu

3.67/5 (2 votes)
3 Sep 2009GPL31 min read 26.8K   199  
Easily build and customize your very own sliding JavaScript menu.

SlidingJavascriptMenuBuilder

Introduction

I wanted to make a menu that slides across the page into its final position. I needed something customizable and extendable, and I wanted something that would work across browsers. A few hours of coding later I got this mean menu, and I'd like to share it with you.

Using the code

To get the sliding JavaScript menu working for your site, save the source files to your web server. Open MenuTemplate.html with a text editor and change it to match your website. Next, save MenuTemplate.html and open it with a web browser. What loads will be the output JavaScript file for your menu. Copy the text area and save it to a file named OutputMenu.js. Now, open ViewFinalMenu.html and your menu will slide into view. Tweak the menu accordingly and add it to your site by adding the external JavaScript reference and calling LoadMenu() from the body's onload event.

JavaScript
<textarea runat="server" rows="678" 
      wrap="off" style="width: 525px; overflow-y: hidden">
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
     "http://www.w3.org/TR/html4/loose.dtd">
<head>
</head>
<body bgcolor="#FFFFFF" color=#000000 onload="BuildMenu()">
<textarea rows="40" wrap="off" style="width: 100%;" 
           ID="JavascriptTextArea" runat="server">
<script language="javascript">

/*
  Use this page as the Template for the Menu. In most 
  circumstances you will edit the values in the 
  javascript arrays to get the menu working for 
  your environment. If you are doin extensive 
  reformatting in some cases you will need to 
  increase array indexes and tweak functions
  so that related input buttons fade in and 
  out together.
*/

function BuildMenu()
{
  //  Initialization Settings
  var JavascriptTextAreaString = '';
  var ConvertNumberToWord = new Array(9);
  //  Uses loop indexes to create variables like SubOneCategoryTwo
  ConvertNumberToWord[0] = 'One';
  ConvertNumberToWord[1] = 'Two';
  ConvertNumberToWord[2] = 'Three';
  ConvertNumberToWord[3] = 'Four';
  ConvertNumberToWord[4] = 'Five';
  ConvertNumberToWord[5] = 'Six';
  ConvertNumberToWord[6] = 'Seven';
  ConvertNumberToWord[7] = 'Eight';
  ConvertNumberToWord[8] = 'Nine';

  //  this new Array declaration is use to determine how many 
  //  subcategories there will be per category. We will be using 3.
  var MenuElements = new Array(3);
  var MenuCategoryString = new Array(3);
  var MenuOnclickEvents = new Array(3);

  //  Build your menu here
  MenuElements[0] = new Array(4);
  //  This array will hold the events that each input will fire. Use 
  //  empty string if there is no event.
  MenuOnclickEvents[0] = new Array(4);

  //  Parent Category
  MenuElements[0][0] = 'Home';
  MenuOnclickEvents[0][0] = 'onclick="parent.location.href=\\\''+
    'http://www.resonantprogramming.com/solutions/'+
'ColossalShop/ColossalShopHome.html\\\'"';

  //  Sub Categories. Use space if there are no sub categories.
  MenuElements[0][1] = ' ';
  MenuOnclickEvents[0][1] = '';
  MenuElements[0][2] = ' ';
  MenuOnclickEvents[0][2] = '';
  MenuElements[0][3] = ' ';
  MenuOnclickEvents[0][3] = '';

  MenuElements[1] = new Array(4);
  MenuOnclickEvents[1] = new Array(4);

  //  Parent Category
  MenuElements[1][0] = 'Buildings';
  MenuOnclickEvents[1][0] = '';

  //  Sub Categories
  MenuElements[1][1] = 'Skyscrapers';
  MenuOnclickEvents[1][1] = 'parent.location.href=\\\''+
    'http://www.resonantprogramming.com/solutions/'+
'ColossalShop/Skyscrapers.html\\\'';
  MenuElements[1][2] = 'Castles';
  MenuOnclickEvents[1][2] = 'parent.location.href=\\\''+
    'http://www.resonantprogramming.com/solutions/'+
'ColossalShop/Castles.html\\\'';
  MenuElements[1][3] = 'Miscellaneous';
  MenuOnclickEvents[1][3] = 'parent.location.href=\\\''+
    'http://www.resonantprogramming.com/solutions/'+
'ColossalShop/Miscellaneous.html\\\'';

  MenuElements[2] = new Array(4);
  MenuOnclickEvents[2] = new Array(4);

  //  Parent Category
  MenuElements[2][0] = 'Check Out';
  MenuOnclickEvents[2][0] = 'onclick="parent.location.href=\\\''+
    'http://www.resonantprogramming.com/solutions/'+
'ColossalShop/CheckOut.html\\\'"';

  //  Sub Categories
  MenuElements[2][1] = ' ';
  MenuOnclickEvents[2][1] = '';
  MenuElements[2][2] = ' ';
  MenuOnclickEvents[2][2] = '';
  MenuElements[2][3] = ' ';
  MenuOnclickEvents[2][3] = '';

  document.getElementById('JavascriptTextArea').innerHTML =
'/*\n' +
'    Fading Js Menu was written by Andrew S. Kloos and \n'+
'    Jason Pappas on 08/13/2009.\n' +
'    Distributed by Resonant Programming.\n' +
'    http://www.resonantprogramming.com\n' +
'*/\n\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
  nSubIndex++)
    {
      if(nSubIndex == 0)
      {
        MenuCategoryString[nIndex] = 
        MenuElements[nIndex][nSubIndex];
      }
      else
      {

      //  Loops through Sub Cateories and builds variables accordingly

        if(MenuElements[nIndex][nSubIndex] != ' ')
          document.getElementById('JavascriptTextArea').innerHTML +=
        '  var Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
        ConvertNumberToWord[nIndex] + 'InputTimeout = 0;\n';
      }
    }
  }
  
  //  Builds function that adds the Menu to the page

  document.getElementById('JavascriptTextArea').innerHTML += 
'\nfunction LoadMenu()\n' +
'{\n'+
'  if(navigator.appName == "Microsoft Internet Explorer")\n' +
'  {\n' +
'    var TableElement = document.createElement(\'table\');\n' + 
'    TableElement.align = \'center\';\n' +
'    var NewRow = TableElement.insertRow(null);\n' +
'    var NewCell = NewRow.insertCell(null);\n' +
'    NewCell.innerHTML = ReturnMenuTable();\n' +
'    document.body.appendChild(TableElement);\n' +
'  }else\n'+
'    document.getElementById(\'MenuTable\').innerHTML = ' +
'ReturnMenuTable();\n' +
'  setTimeout(\'DelayMenuLoad()\', 600);\n' +
'}';

  //  Starts sliding the Parent Categories from 
  //  the left to their resting place

  document.getElementById('JavascriptTextArea').innerHTML += 
'\n\n/*  fades in the main menu  */\n\n' +
'function DelayMenuLoad()\n' + 
'{\n';
    for(nIndex  = 0; nIndex < MenuCategoryString.length - 1; 
nIndex++)
    {
      if(nIndex == 0)
      {
        for(nSubIndex = 0; nSubIndex < MenuElements.length; 
                nSubIndex++)
            document.getElementById('JavascriptTextArea').innerHTML += 
            '  SlideMenuParent(\'Category' + 
ConvertNumberToWord[nSubIndex] + '\');\n';
      }
    }

  //  This section builds the HTML that contains the Menu

document.getElementById('JavascriptTextArea').innerHTML += '}\n\n' +
'/*  returns the fading menu table  */\n\n' +
'function ReturnMenuTable()\n' +
'{\n' +
'    var HTMLString = \'\';\n' + 
'  HTMLString = \'&lt;tr&gt;&lt;td&gt;&lt;table id="menutable" align="center"'+
     ' width="0px" style="background-color: transparent; position: relative; '+
     'top: 0px; left: -200px;" cellspacing="5" border="0" cellpadding="0"&gt;\';\n' +
'  HTMLString +=';

for(nIndex = 0; nIndex < MenuCategoryString.length; nIndex++)
{
var RandomLeftPosition = Math.round((Math.random()*300) + 400);
while(RandomLeftPosition%3 != 0)
    RandomLeftPosition++;
var CharLengthMath = (MenuElements[nIndex][0].length * 8);
document.getElementById('JavascriptTextArea').innerHTML +=
  '   \'&lt;tr&gt;';
  //  if the first Sub Category is space then 
  //  the Parent has no Children Categories
  //  else add fade in and out functions to the tag.

  if(MenuElements[nIndex][1] == ' ' )
  {
    document.getElementById('JavascriptTextArea').innerHTML +=
    '&lt;td align="right"&gt;&lt;div id="Category' + ConvertNumberToWord[nIndex] + 
    '" style="position: relative; left: -' + RandomLeftPosition.toString()  + 
    'px;  top: 0px;"&gt;' + 
    '&lt;input id="Category' + ConvertNumberToWord[nIndex] + 
    'Input" class="button_menu_class" size="3px" style='+
    '"cursor: pointer; width:' + 
    CharLengthMath + 'px;" onmouseout="MouseOutCategory(\\\'Category' + 
    ConvertNumberToWord[nIndex] + 'Input\\\');" onmouseover="'+
    'MouseOverCategory(\\\'Category' + 
    ConvertNumberToWord[nIndex] + 'Input\\\');" ' + 
    MenuOnclickEvents[nIndex][0]+ 
    ' value="' + MenuElements[nIndex][0]+ 
    '"&gt;&lt;/input&gt;&lt;/div&gt;&lt;/td&gt;\' +\n';
  }
  else
  {
    document.getElementById('JavascriptTextArea').innerHTML += 
    '      &lt;td align="right"&gt;&lt;div id="Category' + 
    ConvertNumberToWord[nIndex] + 
    '" style="position: relative; left: -' + RandomLeftPosition.toString()  + 
    'px;  top: 0px;"&gt;' +
    '&lt;input id="Category' + ConvertNumberToWord[nIndex] + 'Input" '+
    'class="button_menu_class" size="3px" style="cursor: default; width:' + 
    CharLengthMath + 
    'px;" onmouseout="MouseOutCategoryWithSubCategories(\\\'Category' + 
    ConvertNumberToWord[nIndex] + 
    'Input\\\');" onmouseover="MouseOverCategoryWithSubCategories(\\\'Category' + 
    ConvertNumberToWord[nIndex] + 'Input\\\');" value="' + 
    MenuElements[nIndex][0]+ 
    '"&gt;&lt;/input&gt;&lt;/div&gt;&lt;/td&gt;\' +\n';
  }
    //  if the Sub Category is not space build 
    //  the HTML for the Sub Category. else
    //  build blank cell.

  for(nSubIndex = 1; nSubIndex < MenuElements[nIndex].length; nSubIndex++)
    if(MenuElements[nIndex][nSubIndex] != ' ')
      {
      var CharLengthMath = (MenuElements[nIndex][nSubIndex].length * 6);
      document.getElementById('JavascriptTextArea').innerHTML +=
'            \'&lt;td&gt;&lt;div id="Sub' + ConvertNumberToWord[nSubIndex-1] + 
      'Category' + 
      ConvertNumberToWord[nIndex] + '" &gt;&lt;input id="Sub' + 
      ConvertNumberToWord[nSubIndex-1] + 
      'Category' + ConvertNumberToWord[nIndex]+ 
      'Input" size="3px" onclick="javascript:if(document.getElementById(\\\'Sub' + 
      ConvertNumberToWord[nSubIndex-1] + 'Category' + 
      ConvertNumberToWord[nIndex]+ 'Input\\\''+
      ').style.opacity > 0.01 || document.getElementById(\\\'Sub' + 
      ConvertNumberToWord[nSubIndex-1] + 
      'Category' + ConvertNumberToWord[nIndex]+ 
      'Input\\\').style.filter != undefined){' + 
      MenuOnclickEvents[nIndex][nSubIndex]+ 
      '}" class="button_menu_class" onmouseout="'+
      'MouseOutSubCategory(\\\'Sub' + 
      ConvertNumberToWord[nSubIndex-1] + 'Category' + 
      ConvertNumberToWord[nIndex]+ 
      'Input\\\')" onmouseover="MouseOverSubCategory(\\\'Sub' + 
      ConvertNumberToWord[nSubIndex-1] + 'Category' + 
      ConvertNumberToWord[nIndex]+ 'Input\\\');"'+
      ' style="cursor: pointer; filter:alpha(opacity=0); opacity: 0.0; width:' + 
      CharLengthMath + 
      'px;" runat="server" value="' + MenuElements[nIndex][nSubIndex] + 
      '"&gt;&lt;/input&gt;&lt;/div&gt' +
       '&lt;/td&gt;\' + \n';
      if(nSubIndex == MenuElements[nIndex].length -1)
        document.getElementById('JavascriptTextArea').innerHTML += 
      '    \'&lt;/tr&gt;\' + \n';
      }else
      {
         document.getElementById('JavascriptTextArea').innerHTML +=
  '            \'&lt;td&gt;&lt;div style="z-index: -1; cursor: pointer;'+
      ' background-color: #ffffff; color: ffffff;"&gt;&lt;/div&gt' +
         '&lt;/td&gt;\' + \n';
        if(nSubIndex == MenuElements[nIndex].length -1)
          document.getElementById('JavascriptTextArea').innerHTML += 
          '    \'&lt;/tr&gt;\' + \n';
      }
  }

      document.getElementById('JavascriptTextArea').innerHTML +=
'    \'&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;\';\n' +
'    return HTMLString;\n' +
'}\n\n';

//  this recursive function calls itself as long
//  as the Parent Category object.style.left is 
//  less than zero. Each time the function is 
//  called the Menu Element moves three pixels to
//  the right.

document.getElementById('JavascriptTextArea').innerHTML +=
'function SlideMenuParent(Category)\n' +
'{\n' +
  '  if(!document.getElementById(Category))\n' +
    '    return;\n' +
  '  var CurrentYPosition = parseInt(document.'+
  'getElementById(Category).style.left.replace(/px/,\'\')) + 3;\n' +
  '  document.getElementById(Category).style.left = CurrentYPosition.toString() +
   \'px\';\n' +
  '  if(CurrentYPosition < 0)\n' +
    '    setTimeout(\'SlideMenuParent("\' + Category + \'")\', 3);\n' +
'}\n\n';

/*  Here's how we fade in the sub categories. Internet Explorer uses the \
    style attribute called filter and it can range from 
    "alpha(opacity=0)" [100% opaque] to "alpha(opacity=100)" [0% opaque]. 
    For gecko based, chrome, opera and safari browser use the style attribute 
    opacity which ranges from "object.style.opacity = 0" [100% opaque] to 
    "object.style.opacity = 1" [0% opaque]. This function is recursive, 
    meaning if the opacity is greater then zero the function will call itself 
    slowly reducing the opacity giving us the fading in and fading out.\
*/

document.getElementById('JavascriptTextArea').innerHTML +=
'/*  displays the sub category when the parent is moused over  */\n' +
'function displaySubCategory(SubCategory, CurrentOpacity)\n' +
'{\n' +
'  if(!document.getElementById(SubCategory))\n' +
'    return;\n' +
'  if(navigator.appName == "Microsoft Internet Explorer")\n' +
'  {\n' +
'    if(CurrentOpacity == 0)\n' +
'      CurrentOpacity = 1;\n' +
'    CurrentOpacity = CurrentOpacity + 50;\n' +
'    document.getElementById(SubCategory).style.filter = \'alpha(opacity=\' + 
     CurrentOpacity + \')\';\n' +
'    if(CurrentOpacity < 100)\n' +
'      setTimeout(\'displaySubCategory("\' + SubCategory + \'",\' + 
      CurrentOpacity + \')\', 140);\n' +
'  }else\n' +
'  {\n' +
'    CurrentOpacity = CurrentOpacity + 0.5;\n' +
'    document.getElementById(SubCategory).style.opacity = CurrentOpacity;\n' +
'    if(CurrentOpacity < 1)\n' +
'      setTimeout(\'displaySubCategory("\' + SubCategory + \'",\' + 
      CurrentOpacity + \')\', 140);\n' +
'  }\n' +
'}\n\n';

// Here's how we hide the sub categories. This function although
// similar to the function above it works oppositely to fade out menu items.


document.getElementById('JavascriptTextArea').innerHTML +=
'/*  hides the sub category when the parent is moused out  */\n' +
'function HideSubCategory(SubCategory, CurrentOpacity)\n' +
'{\n' +
'  if(document.getElementById(SubCategory) && navigator.appName'+
     ' == "Microsoft Internet Explorer")\n' +
'  {\n' +
'    if(CurrentOpacity > 0)\n' +
'    {\n' +
'      CurrentOpacity = CurrentOpacity - 50;\n' +
'      setTimeout(\'HideSubCategory("\' + SubCategory + \'",\' + 
       CurrentOpacity + \')\', 140);\n' +
'      document.getElementById(SubCategory).style.filter = \'alpha(opacity=\' + 
      CurrentOpacity + \')\';\n' +
'    }\n' +
'    else\n' +
'    {\n' +
'      document.getElementById(SubCategory).style.filter = \'alpha(opacity=0)\';\n';
  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
  nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
          document.getElementById('JavascriptTextArea').innerHTML +=
        '      Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
          ConvertNumberToWord[nIndex] + 
        'InputTimeout = 0;\n';
      }
    }
  }
document.getElementById('JavascriptTextArea').innerHTML +=
'    }\n\n';

document.getElementById('JavascriptTextArea').innerHTML +=
'  }else if(document.getElementById(SubCategory))\n' +
'  {\n' +
'    if(CurrentOpacity > 0)\n' +
'    {\n' +
'      CurrentOpacity = (CurrentOpacity / 99.0) - 0.5;\n' +
'      setTimeout(\'HideSubCategory("\' + SubCategory + \'",\' + 
      CurrentOpacity + \')\', 140);\n' +
'      document.getElementById(SubCategory).style.opacity = CurrentOpacity;\n' +
'    }\n' +
'    else\n' +
'    {\n' +
'      document.getElementById(SubCategory).style.opacity = 0;\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
  nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
          document.getElementById('JavascriptTextArea').innerHTML +=
        '      Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
        ConvertNumberToWord[nIndex] + 
        'InputTimeout = 0;\n';
      }
    }
  }
document.getElementById('JavascriptTextArea').innerHTML +=
'    }\n' +
'  }\n' +
'}\n\n';

//  These simple functions are for hightlighting and unhightlighting 
//  the top categories without any sub categories when moused over or out.
document.getElementById('JavascriptTextArea').innerHTML +=
'/*  highlights the category when moused over  */\n' +
'function MouseOverCategory(Category)\n' +
'{\n' +
'  document.getElementById(Category).style.backgroundColor=\'#66ccff\';\n' +
'}\n\n' +

//  unhighlight the category when moused out\

'/*  unhighlight the category when moused out  */\n' +
'function MouseOutCategory(Category)\n' +
'{\n' +
'  document.getElementById(Category).style.backgroundColor=\'#0099ff\';\n' +
'}\n\n' +

//  Next we handle the mouseover event for a category with sub categories. 
//  SubOneCategoryOneInput and SubTwoCategoryOneInput are related 
//  because they both belong to the same parent category. Therefore 
//  they will fade in and out together.

'/*  highlights the category when moused over  */\n' +
'function MouseOverCategoryWithSubCategories(SubCategory)\n' +
'{;\n' +
'  document.getElementById(SubCategory).style.backgroundColor = \'#66ccff\';\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
               nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
            document.getElementById('JavascriptTextArea').innerHTML +=
             '  if(SubCategory == \'Category' + ConvertNumberToWord[nIndex] + 
             'Input\' && document.getElementById(\'' +
             'Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
             ConvertNumberToWord[nIndex] + 
             'Input\').style.opacity < 0.01)\n';
            nIndex = MenuElements[0].length;
            break;
        }
      }
    }
  }
  document.getElementById('JavascriptTextArea').innerHTML += '  {\n';
  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
          document.getElementById('JavascriptTextArea').innerHTML +=
          '    displaySubCategory(\'Sub' + ConvertNumberToWord[nSubIndex-1] + 
          'Category' + 
          ConvertNumberToWord[nIndex] + 'Input\', 0);\n';
      }
    }
  }

  document.getElementById('JavascriptTextArea').innerHTML += 
          '  }\n' + '}\n\n';

  //  Here we handle the mouseoout event for a category with sub categories.

  document.getElementById('JavascriptTextArea').innerHTML +=
    '/*  displays the sub category when the parent is moused over  */\n\n' +
    'function MouseOutCategoryWithSubCategories(SubCategory)\n' +
    '{\n' + 
    '  document.getElementById(SubCategory).style.backgroundColor = \'#0099ff\';\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
                     nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
            document.getElementById('JavascriptTextArea').innerHTML +=
               '  if(SubCategory == \'Category' + ConvertNumberToWord[nSubIndex] + 
               'Input\' && document.getElementById(\'Sub' + 
          ConvertNumberToWord[nSubIndex-1] + 'Category' + 
          ConvertNumberToWord[nIndex] + 'Input\').style.opacity > 0.01)\n';
          nIndex = MenuElements[0].length;
          break;
        }
      }
    }
  }

  document.getElementById('JavascriptTextArea').innerHTML += '  {\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
              nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
            document.getElementById('JavascriptTextArea').innerHTML += 
              '    Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
              ConvertNumberToWord[nIndex] + 
              'InputTimeout = setTimeout(\'HideSubCategory(\\\'' +
              'Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' +
              ConvertNumberToWord[nIndex] + 'Input\\\', 99)\', 120);\n';
        }
      }
    }
  }
  document.getElementById('JavascriptTextArea').innerHTML += '  }\n' + '}\n\n';

  //  This function highlights the sub category and clears any 
  //  of the recursive setTimeout function calls so that the item
  //  does not fade out. The trick here is to not highlight or 
  //  change the cursor to default when the button is not displayed.

  document.getElementById('JavascriptTextArea').innerHTML +=
   '/*  highlights the sub category when moused over  */\n' +
   'function MouseOverSubCategory(SubCategory)\n' +
   '{\n' +
   '  if(navigator.appName != "Microsoft Internet Explorer" && '+
   'document.getElementById(SubCategory).style.opacity == 0)\n' +
   '    return;\n' +
   '  else if(navigator.appName == "Microsoft Internet Explorer" && \n' +
   '    (document.getElementById(SubCategory).style.filter == undefined || \n' +
   '    document.getElementById(SubCategory).style.filter == \'alpha(opacity=0)\'))\n' +
   '    return;\n' +
   '  document.getElementById(SubCategory).style.cursor = \'pointer\';\n' +
   '  document.getElementById(SubCategory).style.backgroundColor = \'#66ccff\';\n';


  document.getElementById('JavascriptTextArea').innerHTML += '  if(';
  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
                             nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
           document.getElementById('JavascriptTextArea').innerHTML +=
            'SubCategory == \'Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
            ConvertNumberToWord[nIndex] + 'Input\' ||\n';
        }
      }
    }
  }
  document.getElementById('JavascriptTextArea').innerHTML = 
  document.getElementById('JavascriptTextArea').innerHTML.substring(0,
  document.getElementById('JavascriptTextArea').innerHTML.length - 4)
  document.getElementById('JavascriptTextArea').innerHTML += ')\n' + '  {\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
                                nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
           document.getElementById('JavascriptTextArea').innerHTML +=
             '    if(Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
                  ConvertNumberToWord[nIndex] + 'InputTimeout > 0)\n' +
                  '    {\n' +
                  '      try\n' +
                  '      {\n' +
                  '        clearTimeout(Sub' + 
                  ConvertNumberToWord[nSubIndex-1] + 'Category' + 
                  ConvertNumberToWord[nIndex] + 'InputTimeout);\n' +
                  '      }catch(asdf){}\n' + '    }\n';
        }
      }
    }
  }

  document.getElementById('JavascriptTextArea').innerHTML += '  }\n' + '}\n\n';

  //  Finally, we need to handle the mouseout event for the 
  //  sub categories. We store the setTimeout ids so that if 
  //  the users hovers back over the button before it faded 
  //  out of site we can cancel the fade.

  document.getElementById('JavascriptTextArea').innerHTML +=
    '/*  unhighlight the sub category when moused out  */\n' + 
    'function MouseOutSubCategory(SubCategory)\n' + '{\n' +
    '  document.getElementById(SubCategory).style.cursor = \'Default\';\n' +
    '  if(navigator.appName != "Microsoft Internet Explorer" && '+
    'document.getElementById(SubCategory).style.opacity == 0)\n' + '    return;\n' +
    '  else if(navigator.appName == "Microsoft Internet Explorer" && \n' +
    '    (document.getElementById(SubCategory).style.filter == undefined || \n' +
    '    document.getElementById(SubCategory).style.filter == \'alpha(opacity=0)\'))\n' +
    '    return;\n' +
    '  document.getElementById(SubCategory).style.backgroundColor=\'#0099ff\';\n';

  document.getElementById('JavascriptTextArea').innerHTML += '  if(';
  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
                  nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
           document.getElementById('JavascriptTextArea').innerHTML +=
             'SubCategory == \'Sub' + 
             ConvertNumberToWord[nSubIndex-1] + 'Category' + 
             ConvertNumberToWord[nIndex] + 'Input\' ||\n';
        }
      }
    }
  }
  document.getElementById('JavascriptTextArea').innerHTML = 
  document.getElementById('JavascriptTextArea').innerHTML.substring(0,
  document.getElementById('JavascriptTextArea').innerHTML.length - 4)
  document.getElementById('JavascriptTextArea').innerHTML += ')\n';
  document.getElementById('JavascriptTextArea').innerHTML += '  {\n';

  for(var nIndex = 0; nIndex < MenuElements.length; nIndex++)
  {
    for(var nSubIndex = 0; nSubIndex < MenuElements[nIndex].length; 
                   nSubIndex++)
    {
      if(nSubIndex > 0)
      {
        if(MenuElements[nIndex][nSubIndex] != ' ')
        {
            document.getElementById('JavascriptTextArea').innerHTML +=
               '    Sub' + ConvertNumberToWord[nSubIndex-1] + 'Category' + 
               ConvertNumberToWord[nIndex] + 
               'InputTimeout = setTimeout(\'HideSubCategory(\\\'' +
               'Sub' + ConvertNumberToWord[nSubIndex-1] + 
               'Category' + ConvertNumberToWord[nIndex] + 
               'Input\\\', 99)\', 120);\n';
        }
      }
    }
  }
  document.getElementById('JavascriptTextArea').innerHTML += '  }\n' + '}\n';
}
</script>
</body>
</html>
</textarea>

History

The first version of the JavaScript menu required a handful of changes if you wanted to add or remove elements. Now, I have created a JavaScript framework that writes the output JavaScript, making changes take seconds not minutes.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)