Sometimes you have two select boxes and you want to fill the second one with options depending on the user's selection in the first box. There are a few ways to do this. This one uses AJAX.
Here's what I'm talking about:
The HTML looks like this:
HTML
<form method="post" action="#">
<p><label>country: <select id="country" name="country">
<option value="United Kingdom">United Kingdom</option>
<option value="United States">United States</option>
<option value="Australia">Australia</option>
<option value="Japan">Japan</option>
</select></label>
<label>city: <select id="city" name="city">
</select></label></p>
</form>
The second box is empty because the javascript fills it. The javascript looks like this:
javascript
var request = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
request = false;
}
}
@end @*/
if (!request && typeof XMLHttpRequest != 'undefined') {
request = new XMLHttpRequest();
}
function fillSelect(country) {
var url = "csa_ajax.php?country=" + escape(country);
request.open("GET", url, true);
request.onreadystatechange = go;
request.send(null);
}
function go() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText;
var list=document.getElementById("city");
var cities=response.split('|');
for (i=1; i<cities.length; i++) {
var x=document.createElement('option');
var y=document.createTextNode(cities[i]);
x.appendChild(y);
list.appendChild(x);
}
}
}
}
function initCs() {
var country=document.getElementById('country');
country.onchange=function() {
if(this.value!="") {
var list=document.getElementById("city");
while (list.childNodes[0]) {
list.removeChild(list.childNodes[0])
}
fillSelect(this.value);
}
}
fillSelect(country.value);
}
This is called onload like this:
javascript
window.onload=initCs;
The first part (before the first function) sets up the XMLHttpRequest() object. The initCs() function loads the second select box onload and sets an onchange event for the first box. Onchange, the fillSelect() function is called. The selected option is sent as a variable to a PHP page, 'csa_ajax.php', which looks like this:
PHP
<?php
function doIt($country) {
switch ($country) {
case "United Kingdom":
return array('London','Manchester','Birmingham','Liverpool','Edinburgh','Cardiff','Belfast');
break;
case "United States":
return array('Washington DC','New York','Los Angeles', 'Chicago');
break;
case "Australia":
return array('Canberra','Melbourne','Sydney', 'Brisbane');
break;
case "Japan":
return array('Tokyo','Osaka','Fukuoka','Sendai','Sapporo');
break;
}
}
$country=@$_GET['country'];
$cities=doIt($country);
foreach ($cities as $city) {
echo '|'.$city;
}
?>
That takes the value of the selected option and chooses the appropriate array for it. This would often be done by calling data from a database, but for convenience, I've used a switch(). The last bit echoes each of the items in the array preceded by '|' for the javascript to split up into individual items. The go() function takes the output from the PHP page, breaks it down, makes new text nodes out of each item, appends them to new option nodes and adds the option nodes to the select box.
It doesn´t work on IE. Pity!!!
AURILEIDE,
I've just checked this page on IE6 and IE7, and as far as I can see, it works fine. What seems to be the problem?
Maybe he's referring to my Comment. It's not working in IE, trying to debug it. Not sure why, it's not very different from your original.
It works for the most part, but there's something fishy with IE's cache of the results from the database.
Sorry, not trying to turn this into a forum, but the problem was with IE using the cache. You need to force it to grab new data from the DB on every onchange event.
Here's some methods, using the header PHP commands worked for to get this script working.
http://www.greenash.net.au/posts/thoughts/an-ie-ajax-gotcha-page-caching
Hello,
Just wondering if there is a way to store the arrays into a database...and then say make a form to where you could add to the arrays.
Like say you wanted to add a city to the United States...
i too, would also like to know if its possible to have the cases and arrays outputted by a database?
/\/\ongoose / Nick,
Yeah, it's easy enough to use a database to do this. I would have done that here, but I just couldn't be bothered.
The query to the database would look something like this:<?php
$country=@$_GET['country'];
$q = mysql_query("SELECT city FROM cities WHERE country='$country' ORDER BY city ASC");
while ($r = mysql_fetch_assoc($q)){
echo "|".$r['city'];
}
?>
This is assuming you have a database of cities with maybe three fields - id, city, country.
I hope that helps.
I want a script with two chained selects, the first one is for a main category, all the categories are extracted from a database.
The second select contains subcategories which are also selected from a database. Is this remotely possible?
Simon,
Yeah. Here's an example of something like that. You'll need this text file too. That's the php file referred to in the source of the demo. The example I've just given you a link to is not drawing things from a database, but hopefully one of my replies above will help with that.
Good luck.
I have this script up and running, but I need 2 or more dependent selects, (not just 1). I'm running into a lot of trouble tyring to reuse the XHR object in IE for the 2nd and 3rd, etc. dependent select fields. I've checked the solutions on http://keelypavan.blogspot.com/2006/03/reusing-xmlhttprequest-object-in-ie.html and other pages with no luck. Any thoughts on what the problem might be ?
Hi,
I am not sure why not, but it works very well with Firefox, not with IE. Any idea, what I may be missing?
Sam
I opened the link with IE from item # 11 above, posted by BonRouge that also did not work. Thanks.
Sam,
Sorry about the very late response (maybe you'll never see this...
).
I see what you mean about the link in #11 - that doesn't work in IE.
(I'll try to get back to it soon and sort it out). This page works fine for me in IE though, so I'm not sure what your problem would be there.
Hi Bon,
Does the script from Item # 11 works on your PC, when you click that one. On mine, it not only did not work, but also showed duplication of the contents of the second selection everytime I made a selection from that option list. Please advice!
-Sam
Thanks, Bon. Script works fine, including the code that retrieves cites and countries from a db.
i need the second chained box to have a value like this:
<option value="1">Town Branch</option>. how do i print this? the data is gotten from a database, a user selects a bank and then the bank's branches are called from the database
I made a little modification to get values in the selecboxes.
here is the new function go:
function go() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText;
var list=document.getElementById("city");
var cities=response.split('|');
for (i=1; i<cities.length; i++) {
var values=cities[ i ].split(';');
var x=document.createElement('option');
x.setAttribute('value', values[0]);
var y=document.createTextNode(values[1]);
x.appendChild(y);
list.appendChild(x);
}
}
}
}
I have added two new lines:
var values=cities[ i ].split(';');
x.setAttribute('value', values[0]);
Both inside the for-loop. Now the only thing you hafte to do is change the .php file to echo in this format:
|id;text|id;text
Ex:
|1;London|2;Manchester
It works fine :-)
Sorry, I also alter the line:
var y=document.createTextNode(values[1]);
This works slick. Here's a little variation that would make an <option> become <option selected> based on the first value.
So you could look up the first value entered in your database and then make that selected in your second select menu. You'd have to return the value of the <option id> from your database.
function go() {
if (request.readyState == 4) {
if (request.status == 200) {
var response = request.responseText;
var list=document.getElementById("city");
var curCity = document.getElementById(response);
curCity.selected = true;
}
}
}
function initCs() {
var memberLogin=document.getElementById('country');
memberLogin.onchange=function() {
if(this.value!="") {
fillSelect(this.value);
}
}
fillSelect(country.value);
}