In the constant struggle to make web sites accessible to everyone, we sometimes

have to reconsider some of the techniques we use in web development.

One of the main obstacles is to "de-script" forms. For years we

have been spicing up forms with Javascript, and, if we didn't consider the

consequences, didn't know better, or weren't allowed to elaborate due to tight

deadlines, we made forms dependent on Javascript.

The classic interdependent select box

The classic example is interdependent select boxes. These are two or more select

boxes, that allow the user to choose an option of one, and the content of the

second gets automatically updated depending on the choice. A very neat way to filter

search options or available options. Airlines use them a lot, as most flights

from one airport go to a defined number of other airports.

The technique behind is to manipulate the options array of the

select boxes, something that can only be done "on the fly" with

Javascript.

Script, begone!

To offer a similar functionality, but make it independent of scripting, we

have several options. One would be to shift all the logic to the backend, and

reload the page every time you select an option of the first box. This'll be

the safest way to do it, but it means another step for the user.

A nice way to work around is to rethink the concept of the interdependent

select box, and make it work with normal form functionality:

Instead of using two select boxes and changing their options via Javascript

we replace the first one with a row of radio buttons. Each radio button has a

select box connected to it.

This is not really a 100% replacement, as the benefit of a select box — the

same screen space for loads of options — is not given anymore, but it's a feasable

option.

Via Javascript, we hide all the select boxes and only show the one

connected to the radio button, once the radio button is selected.

Users without Javascript, or with an older browser that is not able to understand the

DOM, will see all the select

boxes.

HTML

<form id="mainform">

<p><input type="radio" onfocus="hide(0)" name="choice" value="one" id="choice1" />

<label for="choice1">Choice1</label>

<span>

<label for="select1">Options 1</label> 

<select name="select1" id="select1">

<option value="s1_1">s1_1</option>

[...]

</select>

</span></p>

<p><input type="radio" onfocus="hide(1)" name="choice" value="two" id="choice2" />

<label for="choice2">Choice2</label>

<span>

 <label for="select2">Options 2</label> 

<select name="select2" id="select2">

<option value="s2_1">s2_1</option>

[...]

</select>

</span></p>

<input type="submit" value="Send" />

</form>

As the Javascript uses DOM to find the SPAN to hide and the P to highlight,

all we need to do to add another select is to add it after the last one:

<p><input type="radio" onfocus="hide(2)" name="choice" value="three" id="choice3" />

<label for="choice3">Choice3</label>

<span>

 <label for="select3">Options 3</label> 

<select name="select3" id="select3">

<option value="s3_1">s3_1</option>

[...]

</select>

</span></p>

Notice we need to increment the counter for hide().

To hide all select boxes, we call the hide() function with an id

of "none".

<body onload="hide('none')">

Javascript

function hide(id){

if (document.getElementById && document.createTextNode){

spans=document.getElementById('mainform').getElementsByTagName('span');

m=document.getElementById('mainform');

for (i=0;i<spans.length;i++){

m.getElementsByTagName('span')[i].style.display='none';

m.getElementsByTagName('p')[i].style.background='#eee';

m.getElementsByTagName('p')[i].style.borderColor='#ccc';

}

if(id!='none'){

m.getElementsByTagName('span')[id].style.display='inline';

m.getElementsByTagName('p')[id].style.background='#ffc';

m.getElementsByTagName('p')[id].style.borderColor='#000';

}

}

}

The background and border colour change is just there to add some eye candy.

If there is more than one instance on the page, we need to turn 'mainform'

into a second variable added to hide().

Any other way?

Another solution would be to turn all the option of the first select into

headlines with radio buttons for the dependent select boxes and hide and

show the radio groups with DOM. How to show and hide them was explained in the

Collapsible page elements with DOM article.

To see the code here in action, go to the Demo page.