advertisement -- please support sponsors

forms:
context-sensitive select boxes

I want to have the choices in a dropdown list driven by the choice made in a previous drop down list.

is there a way to do this in javascript?

Do you mean something like this?

Category menu

Choose a food category:

(Selecting a category will update the food menu on the right.)

item menu

Choose a specific food item:

Select an option in the Category menu. When you do, you will see that the Item menu is updated according to the category you have selected.

To achieve this effect, I programmed the form so that it would respond to Change events in the Category select box. Here's the source for both select boxes:

<select size=2 name=category onChange="update_item_list ();">
 <option value=f>fruits
 <option value=v>vegetables
</select>

<select size=5 name=item>
 <option>--------------------
 <option>--------------------
 <option>--------------------
 <option>--------------------
 <option>--------------------
</select>

Note the use of onChange within the <select> tag. This tells the browser to call update_item_list () whenever the selection is changed. Obviously, the purpose of calling update_item_list () is to update the Item select box menu.

Note also that the source for the Item select box does not contain references to any fruits or vegetables. Instead, it contains only blank lines. These are "place holders" to indicate that, initially, there are no choices available. The place holders serve an additional purpose by guaranteeing that the select box will be wide enough to display either of the menus.

Here's the code for update_item_list ():

function update_item_list ()
{
	// Step 1: Define aliases in order to minimize typing:
	var cat_selobj = document . f . category;
	var item_selobj = document . f . item;

	// Step 2: Determine which category was selected:
	var choice = cat_selobj . options [cat_selobj . selectedIndex] . value;

	// Step 3: Determine which category was selected and update the item menu:
	if (choice == "f")
	{
		// "fruits" was selected
		item_selobj . options [0] = new Option ("apple");
		item_selobj . options [1] = new Option ("banana");
		item_selobj . options [2] = new Option ("grape");
		item_selobj . options [3] = new Option ("kiwi");
		item_selobj . options [4] = new Option ("orange");
		item_selobj . options [5] = new Option ("peach");
		item_selobj . options [6] = new Option ("pear");
		delete_extra_options (item_selobj, 7);
	}
	else if (choice == "v")
	{
		// "vegetables" was selected
		item_selobj . options [0] = new Option ("carrot");
		item_selobj . options [1] = new Option ("cucumber");
		item_selobj . options [2] = new Option ("lettuce");
		item_selobj . options [3] = new Option ("spinach");
		item_selobj . options [4] = new Option ("tomato");
		delete_extra_options (item_selobj, 5);
	}
}

As you can see, update_item_list () is a three-step plan. Step 1 sets up aliases for the Select objects in order to minimize typing effort. Step 2 determines which item in the Category menu is selected, and Step 3 updates the Item menu accordingly.

These last two steps require additional explanation.

The Category select object, cat_selobj, has a property called options, which is an array of Option objects. cat_selobj also has a property called selectedIndex, which is the index of the currently selected option. Thus, the expression

cat_selobj . options [cat_selobj . selectedIndex] . value
returns the value of the currently selected object, which, in this example, is either "f" or "v".

In Step 3, the options array of item_selobj (the object representing the Item select box) is overwritten with new Option objects. After the new options have been written into the array, the tail of the array may still contain options from the previous list, especially if the updated list is smaller than the previous list. We can remove these extra options by calling delete_extra_options ().

The source for delete_extra_options () is shown below:

function delete_extra_options (selobj, size)
{
	while (selobj . options . length > size)
		selobj . options [selobj . options . length - 1] = null;
}

This function requires two parameters:

selobj
the select object from which extra options are to be deleted
size
the size of the new option list, i.e., after deleting the extra options (or, equivalently, the index of the first extra object)

When delete_extra_options () is called, every Option in the options array that has an index equal to or greater than size is removed from the array. The result is a trimmed array that contains only the updated Options.

Now that you've seen the source code for this example piece by piece, here is the whole thing. I put it in an edit box so that you can cut and paste to your heart's content.

Charlton Rose
23 August 1997