Javascript Drop down menus

A number of e-commerce sites employ a drop-down menu containing a list of "hot" pages. The advantage of this technique is that critical pages are only one click or so away - from anywhere within the site. Although there are drawbacks:

  • The drop-down menu is not an intuitively obvious method of navigation, it has nowhere near the clarity and simplicity of a list of hyperlinks.
  • Search engines will have difficulty indexing other pages on your site since it will not be able to find proper links to these pages.

In both cases, this could mean that users of your website will not be able to find what they are looking for on your site.

Certain websites, however, have managed to exasperate the user by not implementing a reliable solution, and by making the navigation component unusable in anything other than Internet Explorer powered browsers. With a little thought and some common sense these "problems" rapidly disappear, leaving us with a reliable component we can use everywhere on our website.

The main problems that crop up in other sites using the drop-down list as a navigation aid are:

  • When Javascript is unavailable, the menu doesn't work.
  • When Javascript is available, its usage relies on certain browser notation shortcuts.

Both of these problems can be tackled sensibly. When Javascript is unavailable, we can gracefully degrade to the natural processor of forms - the serverside process. When Javascript is there for us to use, we'll write some cross-browser compatible code to run our menu.

In this tutorial we'll start off by making an ultra reliable CGI based menu, then add the necessary Javascript later. This will give us some useful advantages and maintain cross-platform compatibility. The advantages of this technique are:

  • the usability advantage of using client side Javascript to navigate
  • the dependability of server side processing to kick in when Javascript is not available

First off we need the HTML to display our drop down menu. The drop down menu will use the <select> element. Within our <select>s we'll have one <option> for each menu item we want to display. A quick check of the World Wide Web Consortium recommendations for HTML shows us that <select> is a component of the form element, so we'll need to nest our dropdown menu within the <form> element.

 <form name="menuForm" 
 	method="get" 
	action="/cgi-bin/redir.cgi"> 
  <select name="menuList">
   <option value="http://www.google.com">
   Google
   </option>
   <option value="http://www.yahoo.com">
   Yahoo
   </option>
   <option value="http://www.askjeeves.com"> 
   Ask Jeeves
   </option>
   <option value="http://www.altavista.com"> 
   Altavista
   </option>
  </select>
  <input type="submit" value="Go">
 </form>

This is what is rendered:

From this HTML snippet, notice the action attribute on the form is /cgi-bin/redir.cgi. This is going to be our server side process - our fallback if Javascript fails us. The code behind this CGI script is relatively simple:

   redir.cgi:
 #!/usr/bin/perl
 use CGI;
 
 if(param('menuList')) { 
  print redirect(param('menuList')); 
 } else { 
  print redirect("/"); 
 }

A minimalist Perl script (the CGI.pm module does most of the hard word). If the menuList parameter (Our <select> element has the name menuList) was received, then the script prints out the relevant HTTP redirect request to the page specified, otherwise it redirects back to the home page of the server the script sits on.

With the solid foundation laid, we can turn our attention to the Javascript part. Although the solution provided so far will work in all form-conforming browsers, there's nothing that needs to be changed.

So why add any Javascript? For no reason at all than to take an unnecessary load off the server when Javascript is available, and to make the website a little more usable, since doing it via Javascript cuts the number of HTTP requests to the webserver in half so making it faster and more responsive to the user.

The first thing we need to do is to insert a Javascript event handler which takes over at the most appropriate time. The obvious event handler is onSubmit which fires when the user clicks the submit button (which is our "Go" button on our form).

  <form name="menuForm" 
 	method="get" 
	action="/cgi-bin/redir.cgi" 
	onSubmit=
	"return doRedir(this.menuList);">  

The onSubmit is an event-handler designed for the <form> element. This event-handler is normally used for form validation - so it accepts a return value. If we had onSubmit="return false" the form will halt in its track and not be submitted. With onSubmit="return true" allows the form details to be sent along with the HTTP request to the URL specified in the action attribute (our redir.cgi script). We can use this to our advantage by getting Javascript to request the selected page, and also stopping the form from doing a default submit.

 <script language="Javascript"
	type="text/javascript">
 <!--
 function doRedir(menu) {
  var itemNo = menu.selectedIndex; 
  document.location = 
	menu.option[itemNo].value;
  return false;
 }
 // -->
 </script>

Its too easy to stumble into Internet Explorer's "short-cut" and fall down on reliability in this short function. You'll see a few Javascript attempts with: menu.value. With a little common sense, its obvious that the menuList <select> doesn't have a value attribute!

The <option> elements within <select> are referenced as an array, and the selectedIndex attribute stores the currently selected array element. Hence the need to get the selectedIndex value first, and then reference the value of the selected array element.

And of course, we need to tell the form not to submit itself. We do this by finally doing a return false. If we leave this line out we get a very strange effect - the page briefly tries to access the url written to document.location and then the form submits, calling our CGI routine which redirects to the same page. This gives the impression the Javascript routine doesn't work (which is almost correct). Leaving out a proper return value is a sloppy piece of Javascript programming that seems to crop up on a lot of "Javascript tutorial" sites - so beware!

One variant of this Javascript drop-down is one without the "go" button. Javascript-wise this is possible, but there are a few pitfalls that make this solution questionable.

Without a "go" button, the form doesn't have a proper submit button. Without a submit button - how does a form get submitted? Using Internet Explorer pressing Enter on the keyboard can be used as a replacement for a submit button. This is a non-standard feature, so this technique is not to be recommended on an open network such as the Internet. It may be useful in a controlled Intranet with all users running some form of Internet Explorer.

This technique is implemented by using the onChange event handler on the <select> element. So taking our code snippet above (and removing the submit button), we change it to:

 <form name="menuForm" 
 	method="get" 
	action="/cgi-bin/redir.cgi"> 
  <select name="menuList"
  	onChange="return doRedir(this);"> 

Test this in your favourite browser and it works nicely. Now disable Javascript and test it again. In Internet Explorer, you'll have to press enter to submit the form. In other browsers you are stuck - there is no way to submit the form.

So we have added a useful component to our armoury, but it has one serious flaw: If this drop-down menu is the only way of navigating from page to page, then search engines will have great difficulty in finding your other pages - so they will remain unindexed. This may lose you some potential visitors. Take this into consideration during your design phase.