[ Team LiB ] Previous Section Next Section

10.3 Using a select Element for Navigation

NN 2, IE 3

10.3.1 Problem

You want users to choose a destination from a pop-up list originating from a <select> tag.

10.3.2 Solution

You have a few scripting possibilities for this solution, depending on your design and scripting style, but they all rely on the select element having been outfitted with option elements containing the URL for each destination. You can display any text you like that is visible in the list, but assign the URL for each item to the value attribute of each option:

<select name="chooser" id="chooser">
    <option value="">Choose a Destination:</option>
    <option value="http://www.megacorp.com/index.html">Home</option>
    <option value="http://www.megacorp.com/products/index.html">Products</option>
    <option value="http://www.megacorp.com/support/index.html">Support</option>
    <option value="http://www.megacorp.com/contact.html">Contact Us</option>
</select>

Some event must trigger the navigation action. The most backward-compatible approach is to locate a clickable button or "Go" icon next to the select element. The onclick event handler of that button or link-surrounded image invokes a function that reads the selected option's value property:

function navigate( ) {
    var choice = document.forms[0].chooser;
    var url = choice.options[choice.selectedIndex].value;
    if (url) {
        location.href = url;
    }
}

Perhaps more convenient for users is to trigger the navigation by making the choice from the list, in which case, you can create a generic (reusable) function that receives as an argument a reference to a select element:

function navigate(choice) {
    var url = choice.options[choice.selectedIndex].value;
    if (url) {
        location.href = url;
    }
}

The event handler in the select element should be as follows:

<select name="chooser" id="chooser" onchange="navigate(this)">...</select>

10.3.3 Discussion

The myriad of ways to translate a select element's choice into a navigation command depend primarily on the browser versions you need to support and your coding style, particularly with respect to event processing. For example, in IE 4 or later and NN 6 or later, you can access the value property of the chosen option by simply retrieving the value property of the select element directly. This cuts down on all the options array referencing shown in the Solution. On the other hand, if you wish to bind the onchange (or other) event to the select element through other means, the event handler function cannot receive a reference to the select element as an argument. Instead, the function has to derive that information from the event object in a way that applies to both the IE and NN event models:

function navigate(evt) {
   evt = (evt) ? evt : ((event) ? event : null);
   if (evt) {
      var elem = (evt.target) ? evt.target : ((evt.srcElement) ? 
          evt.srcElement : null);
      if (elem && elem.tagName.toLowerCase( ) =  = "select" && elem.value) {
         location.href = elem.value;
      }
   }
}

You can then bind the event handler within the tag:

<select name="chooser" id="chooser" onchange="navigate(event)">...</select>

Or in a script statement that executes after the page loads:

document.getElementById("chooser").onchange = navigate;

The scheme presented thus far has a significant flaw, however. If the user navigates from the current page to a choice in the select element and then returns to this page via the Back button, most browsers display the page just as it was the instant it unloaded—with the last choice preselected. The problem is that if the user wants to make the same selection again, the select element will not fire an onchange event (in most browsers). In other words, the user won't be able to duplicate the choice a second time without first making some other choice. You might think to bind any mouse-related events to trigger the navigation, but this is fraught with peril, because users can mouse down, mouse up, and click on a select element just to look through it, or (in some operating systems) keep a sticky list showing to view the list. Thus, mouse events are not suitable substitutes.

To force the user to make a selection that fires the onchange event, script the page to restore the select element (or perhaps all form controls) to its default state either via the onload or onunload event for the document or window objects. Either invoke the reset( ) method of the containing form element object, or set the selectedIndex property of the select element to zero. Notice that the select element shown in the Solution contains an initial choice that has no value—just a text label with instructions. All of the navigation event handler functions shown here assign a value to the location.href property only if there is, indeed, a value (other than an empty string) associated with the selected option.

You may wonder why, with the efficiency of the onchange event handler, a designer would include a "Go" button next to a select element. There are two primary reasons. First, some user interface designers don't like the idea of a select element triggering as drastic an action as navigating to another page. In other words, they intentionally separate the actions of choosing and going. Second, a historical precedent was set in Navigator 2, in which the onchange event handler for select elements was broken in the Windows versions of that browser (the element had to lose focus before the event would fire). To get a select element to do anything with a chosen item, the designer had to include a clickable element to initiate the going part (even if it was a dead element to get the focus out of the select element). How much each of these reasons influences today's designs is hard to say. If I want to make a page that provides select list navigation, yet can also work with nonscriptable browsers, I would include a "Go" button, but use scripted feature detection and style sheets to hide the button in scriptable, CSS-capable browsers.

10.3.4 See Also

Recipe 7.2 and Recipe 7.3 for controlling navigation of other frames; Recipe 14.1 for ideas about using scripts to add content to a page dynamically during page loading.

    [ Team LiB ] Previous Section Next Section