Quick and dirty expandable navigation

The topics two and four have subtopics, clicking them will expand/collapse the nested UL below them.

The whole functionality gets added to the links via DOM, and the function init() which needs to get called onload.

In the Javascript, you can set the highlight and standard background colour of the link, as :focus or :active support is flimsy in different browsers.

How it is done

var originalcolour='#fff';
var highlightcolour='#fcc';
function init()
{
     if(document.getElementById && document.createTextNode)
 

Check if the browser is capable of DOM manipulations

     {
      var mn=document.getElementById('mainnav');
      var lis=mn.getElementsByTagName('li');
 

Grab the element with the ID mainnav (our UL) and read all the LI elements in it

      for (var i=0;i<lis.length;i++)
      {
         if(lis[i].getElementsByTagName('ul').length>0)
         {
            lis[i].getElementsByTagName('a')[0].onclick=function(){expand(this);return false}
            lis[i].getElementsByTagName('a')[0].onkeypress=function(){expand(this);return false}
         }
      }      
 

loop through all the LIs and check if one of them contains a nested UL. If that is the case, make the first link in this li execute the function expand onclick and onkeypress. Send the link itself as a parameter.

   }
   expand(null);
 

Call the function expand with no parameter.

}
function expand(origin){
     if(document.getElementById && document.createTextNode)
   {
      var mn=document.getElementById('mainnav');
      var lis=mn.getElementsByTagName('li');
      for (var i=0;i<lis.length;i++)
      {
         if(lis[i].getElementsByTagName('ul').length>0)
         {
 

same as above.

            if (origin!=lis[i].getElementsByTagName('a')[0])
            {
               lis[i].getElementsByTagName('a')[0].style.background=originalcolour;
               lis[i].getElementsByTagName('ul')[0].style.display='none';                  
            }
 

If the first link inside the LI is not the link that was clicked, set the background to the standard and hide the nested UL. This is the part where all other nested ULs get hidden to prevent two of them being open at the same time.

         }
      }      
      if(origin){
         var daughternode=origin.parentNode.getElementsByTagName('ul')[0];
         if(daughternode.style.display=='none')
         {
            daughternode.style.display='block';
            origin.style.background=highlightcolour;
         }else{
            daughternode.style.display='none';
            origin.style.background=originalcolour;
         }                  
      }   
 

If origin has a value (a link was clicked) reverse the settings of the first link and the nested UL regarding background and display. Highlight a standard link and show the nested list or set the highlighted link to standard and hide the nested list.

   }
}      

That's all there is to it. Only works when you nest once though.