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.
|