This question would probably make more sense in the clientside technologies section.
One easy way to do it
<script type="text/javascript">
function nextSelect(o) {
// Clear out the next select element
if (o.value == '0') {
var next = o.nextSibling;
while (next && next.nodeName != 'SELECT') {
next = next.nextSibling;
}
next.length = 0;
return;
}
var d = document;
// get the invisible select holding data
var useSelect = d.getElementById(o.name + '_' + o.value);
// No select found with matching id. You made an error somewhere
if (!useSelect) {
alert('Unknown id: ' + o.name + '_' + o.value);
return;
}
// get a copy of it so the original is left where it was
var copy = useSelect.cloneNode(true);
copy.style.display = 'inline';
/* find out where to place it. br means nextSibling is a br node,
* and line breaks means nextSibling is text node. The next select from the
* current one with the html code used here would be
* o.nextSibling.nextSibling.nextSibling. But if you
* start adding dom nodes with javascript you'd have to also append empty
* text nodes to match this format. The code below keeps going until it finds
* a select node. */
var next = o.nextSibling;
while (next && next.nodeName != 'SELECT') {
next = next.nextSibling;
}
next.parentNode.insertBefore(copy, next);
next.parentNode.removeChild(next);
}
</script>
</head>
<body style="width: 100%">
<!-- all dependent selects go here -->
<div style="display: none;">
<!-- note that they should only have onchange event if there is another
select following this one. There isn't in my example... so the onchange
shouldn't actually be here for the second level selects in this case -->
<select name="second" id="first_numeral" onchange="nextSelect(this);">
<option value="0">Select</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<select name="second" id="first_alpha" onchange="nextSelect(this);">
<option value="0">Select</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</div>
<form method="post" action="">
<fieldset>
<select name="first" onclick="nextSelect(this);">
<option value="0">Select</option>
<option value="numeral">Numerals</option>
<option value="alpha">Letters</option>
</select><br/>
<select></select>
</fieldset>
</form>
The drawback is that the number of unnecessary invisible selects grows rapidly with the amount of selects and options per select. It's advisable to implement this using XHR and pulling the needed data from a db, return them as a json string, document.createElement('option') for each of them, and append to the appropriate select. But the basic principles are the same as here.