Updated (i.e. completely changed) on June 26th 2011
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. And then maybe you need a third box, or even a fourth (and so on).
Here's what I'm talking about:
The HTML looks like this:
HTML
<form method="post" action="#">
<fieldset id="places">
<p><label>country: <select id="country" name="country">
</select></label>
<label>city: <select id="city" name="city">
</select></label></p>
<label>street: <select id="street" name="street"></select></label>
</fieldset>
</form>
The boxes are empty because the javascript fills them.
In the javascript, first, the options are declared as a big old array (of arrays). The first part of each array is the value that leads to the next ones.
javascript
places=[
['',['United Kingdom', 'United States', 'Japan']],
['United Kingdom', ['London','Manchester','Liverpool']],
['London', ['Chelsea','Tottenham','Peckham']],
['Chelsea',['Egerton Crescent', 'Carlyle Square', 'St Leonards Terrace']],
['Tottenham', ['Fore Street', 'Philip Lane', 'High Road']],
['Peckham', ['Old Kent Road', 'Patterdale Road', 'Sylvan Grove']],
['Manchester', ['Moss Side', 'Rusholme', 'Fallowfield']],
['Moss Side', ['Broadfield Road', 'Claremont Road', 'Great Western Street']],
['Rusholme', ['Wilmslow Road', 'Heald Place', 'Victory Street']],
['Fallowfield', ['Wilbraham Road', 'Wellington Road', 'Granville Road']],
['Liverpool', ['Croxteth', 'Everton', 'Kirkdale']],
['Croxteth', ['Sovereign Road', 'Regal Road', 'Throne Road']],
['Everton', ['Windermere Street', 'Coniston Street', 'Ullswater Street']],
['Kirkdale', ['Stanley Road', 'King\'s Road', 'Bankhall Street']],
['United States', ['New York', 'Los Angeles']],
['New York', ['The Bronx', 'Queens', 'Manhattan']],
['The Bronx', ['Bronxdale Avenue', 'Bronx River Parkway', 'Bronx Park East']],
['Queens', ['71st Avenue', '72nd Avenue', '73rd Avenue']],
['Manhattan', ['Broadway', 'First Avenue', 'Park Avenue']],
['Los Angeles', ['Beverly Hills', 'Hollywood', 'South Central']],
['Beverly Hills', ['Sunset Boulevard', 'Santa Monica Boulevard', 'Beverly Boulevard']],
['Hollywood', ['Sunset Boulevard', 'Santa Monica Boulevard', 'Hollywood Boulevard']],
['South Central', ['West Gage Avenue', 'East Gage Avenue', 'East Manchester Avenue']],
['Japan', ['Tokyo','Sendai']],
['Tokyo', ['Shinjuku', 'Shibuya', 'Akihabara']],
['Shinjuku', ['Omoide Yokocho', 'Kabukicho Street']],
['Shibuya', ['Koen Street', 'Omotesando', 'Aoyama-dori']],
['Akihabara', ['Chuo-dori', 'Kandamyojin-dori']],
['Sendai', ['Aoba-ku', 'Miyagino-ku', 'Izumi-ku']],
['Aoba-ku', ['Nishi-koen-dori', 'Jozenji-dori', 'Kimachi-dori']],
['Miyagino-ku', ['Route 4', 'Route 45']],
['Izumi-ku', ['Route 4', 'Route 457']]
];
Onload, we count the select boxes and make an array of them, then we define the array to be used. The first select box gets filled, followed by all the others, depending on the values of the ones before them.
javascript
window.onload = function() {
boxes = document.getElementById('places').getElementsByTagName('select');
boxes_len = boxes.length;
our_array = places;
arr_len = our_array.length;
fillEm(0);
for (i=0; <boxes_len-1; i++) {
boxes[i].onchange=function() {
for (m=0; m<boxes_len-1; m++) {
if (this==boxes[m]) {
fillEm(m+1);
}
}
}
}
}
You can see fillEm() is called. Here's that function.
javascript
function fillEm(no) {
for (j=no; j<boxes_len; j++) {
if (j==0) {
the_options = our_array[0][1];
addOptions(the_options, boxes[j]);
}
else {
pVal = boxes[j-1].value;
for (k = 0; k<arr_len; k++) {
if (our_array[k][0] == pVal) {
the_options = our_array[k][1];
addOptions(the_options, boxes[j]);
}
}
}
}
}
You can see addOptions() is called twice. It removes all options from a box and fills it with new ones. Here's that function.
javascript
function addOptions(the_options, the_sel) {
len = the_options.length;
while (the_sel.hasChildNodes()) {
the_sel.removeChild(the_sel.firstChild);
}
for (i=0; i<len; i++) {
op = document.createElement("option");
the_val = the_options[i];
val = document.createAttribute('value');
val.value = the_val;
op.setAttributeNode(val);
the_text = document.createTextNode(the_val);
op.appendChild(the_text);
if (i==0) {
op.selected=true;
}
the_sel.appendChild(op);
}
}
If you don't need as many select boxes, simply remove what you don't need from the HTML and sort out the array. If you need more, just add them to the HTML and the array - I'm sure you can follow the pattern.
There may be a better way to do this, but I don't know what it is. I hope this helps.
<<--
yeah, i was mentioning the Ajax version actually !
Sam,
Yes, it is possible...
(I'm afraid I haven't had time to show how though ).
This presents error in box2 at ie 6.0
at fillbox2:
for (i=1; i<cities.length; i++) { --- eliminates the first array occurency.
the first index must be 0
correct command: for (i=0; i<cities.length; i++)
Hey guyz,
this is a cool example.. thanks!
but this script has issues with IE... it shows empty box in IE... if I set to view the errors on the page.. even this page pops up JS errors...
The Error says: 'length' is null or not an object..
all fixed.. cool & thanks!
Have you noticed that the first city is never available? For example, London does not display under United Kingdom...
Andrew,
Thanks for pointing that out. I hadn't noticed that. It was just a small mistake - a '1' where there should have been a '0'.
Fixed it now.
Easy enough. What about if you wanted to submit values that were not the same as the displayed option? For example, how could you submit numerical values for the cities - London as "1", Manchester as "2" ?
Andrew,
To do that, you just need to add this line: x.value=i+1;
...and this bit for IE: if (window.attachEvent) { // for IE
x.setAttribute('value',i+1);
}
...here:function fillBox2(box2,country) {
for (i=0; i<countries.length; i++) {
if (countries[ i ]['country']==country) {
var cities=countries[ i ]['cities'];
}
}
for (i=0; i<cities.length; i++) {
var x=document.createElement('option');
var y=document.createTextNode(cities[ i ]);
x.value=i;
if (window.attachEvent) { // for IE
x.setAttribute('value',i+1);
}
x.appendChild(y);
box2.appendChild(x);
}
}
You could just use php + Ajax. of even if you dont know Ajax you could use PHP but it would cost you a click or two (ie you would have to press submit to get all cities related to your country
There is a way that i can send var to the page
list a defualt country and city to show first ?
or if i want to update a page so the country and city already selected ??
Hi,
i have used this code and find very useful.
only one this i need is that when i want to give custom values
like in Cities currently only numbers are shown...
but i want to show the specified values
like, LON for London, and so on....
How can i implement that
regards,
Naseer Ahmad
HEY I COPY PASTED THE WHOLE CODE BUT THIS IS NOT WORKING ONLY THE COUNTRIES ARE LISTED IN THE OPTION AND THE CITIES ARE NOT LISTED PLEASE HELP.........
I am having the same problem as GM above. Script works great except for in IE. Select boxes are blank, won't populate. Any fix?
Your site is very interesting and useful
this example is very nice. hats off
I used the script. But the e field 'city' is empty when i have it check after a submit
Cool. And if you insert new array value:
countries[0]['citiescode']=['333','352','361','370','374','378','382'];
And want to submit these values for cities?
Thanks!
thanks for your great work but can you please point out how to do this to submit information from the select menu into a div beneath it
when checked on IE, it gives this error;
length is 'null' or not an object on line 30, character 11. Only countries are displayed as mentioned above and cities wouldn't show up.
This is a great and I need it to be working also in IE as well as Firefox?
I tried the code you gave above but wouldn't work here unfortunately.
Any help is appreciated
thanks and keep up the great work
Hello, I need to remember selected values after form is sent. Can you let me know, how to do it ? Something on the way html selected="selected"...
Thanks in advance.
Hi,
i dont understand how to put the code together.
shall i copy/paste it to an html file? 2 seperate files?
which code goes first, javascript or html.Please help me.
Thanks,
atn
This script is exactly what I was looking for. Thanks.
I've used php to fill the arrays from a db. It's working well in FF and IE.
Question: How do I pre select elements? In http this is SELECTED but how can I do this in the java script?
David.
vry bad coding dude...itz just useless...u hvn't cared abt the IE 6.0
Re: Pre selection (see above)
I've worked this out now for anyone who is interested.
after:
country.appendChild(x);
}
Add:
country.options[n].selected=true;
and after:
box2.appendChild(x);
}
add:
box2.options[n].selected=true;
where n = the element you want pre selected.
Great Site - really useful information!
hi,
is this work with php _POST ?
thanks
cipu,
Yes.
To fix IE, AFTER THIS:
for (i=0; i<regions.length; i++) {
var x=document.createElement('option');
ADD THIS:
x.value = regions[ i ];
Hi, BonRouge.
Is there a way to edit this and make 3 chain linked select box? each one dependent on the previous?
Please,I need your help
Thanks.
Great!!
It is very simple and helpful javascript coding.
Thanks BonRouge!
how can i loop this and carry the first select options to another?
example:
country: United Kingdom city: London
country: United Kingdom city: London
country: United Kingdom city: London
Monde,
I'm sorry. Could you explain that again?
i want to loop the form, but at the same time the value of the select box are still there..
example: ______________ ______
country: |United Kingdom| city: |London|
______________ ______
country: |United Kingdom| city: |London|
______________ ______
country: |United Kingdom| city: |London|
Monde,
I've played around with the code and I think I've got what you're looking for here: chain select js boxes
Let me know if you have any questions.
Monde,
Sorry. It looks like I spoke too soon.
Although the new page (in the link above) works fine in Firefox and Chrome, it's not working in Internet Explorer.
I'll come back to it soon.
Where is all this javascript supposed to go? in the head? as a separate file? I am so confused.
Has anyone managed to get the demo link working on IE8?
http://bonrouge.com/br2.php?create=See+demo+only&page=chain_select_js
FF and Chrome etc are fine but IE8 is stuffed and sadly a lot of users use it, have tried adding
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
But no joy is IE
Shame really, first cascading menu I've found that actually works inside Plone CMS..
McKee,
Thanks for pointing this out. I've been trying to work out what's going wrong in IE8 since I saw your message, and I'm afraid I can't. Hopefully someone smarter than me can see how Microsoft has managed to screw up my script (or how my coding was shoddy in the first place).
Thanks, am still scratching my head but coming up with zilch.. Will keep checking back here and see if I can figure it out. As a webmaster IE makes my life sooo much more complicated ;(
McKee,
I went back to the drawing board and tried again. I've (almost) completely changed the code.
There's a new simple chain select js demo <<-here.
Hello.
I've changed the code again. People have asked for more than two select boxes, so I wrote something that will work for any number. It now works in Firefox, IE8 and Chrome.
Let me know if there are any problems.
Thank you for that, will give it a whizz this evening
hi there! i was just wondering what if it's not in 'select'? would it be possible if it's in textbox form? i want the user to input in the textbox and then it will be chained to the next input box.
ysh,
I don't really understand what you mean. Can you give me an example?
Hey, I think you missed the 'j' on the first function:
window.onload = function() {
boxes = document.getElementById('places').getElementsByTagName('select');
boxes_len = boxes.length;
our_array = places;
arr_len = our_array.length;
fillEm(0);
for (j=0; j<boxes_len-1; j++) {
boxes[j].onchange=function() {
for (m=0; m<boxes_len-1; m++) {
if (this==boxes[m]) {
fillEm(m+1);
}
}
}
}
}
Maykel,
I believe you're right. Sorry about that. I'll fix it soon.
Thank you. This javascripts did it. Yes, the "i" is missing, I added that "i" and all worked all right
I'm trying to use this to display 2 option fields, followed by a 3rd field that is just to display html/text.
1OPTION--2OPTION--3HTML/TEXT
Is that possible?
Your latest code at the top of the page seems to work good on all browsers. Is there a way to test the box value selected after the selection is made? I want to make sure the user has made a selection.
I wasn't sure that the normal form validation would work. The way you loaded the box data was new to me. As it turns out my normal test works. fieldname.selectedindex==0 indicates no selection. Thanks for your chained select code. I had been coding the chained selects myself but your code is much more compact. Since I plan to use your code, I will contribute if you tell me how.
Please excuse my lack of knowledge, but can i copy and paste the above code exactly as it is in that order?? I can change values later
Mike,
It's easier if you go to this demo page and copy the source from that.
Thanks for that, great site.
Cheers
How can I modify this to do multiple selects on the same page?
Excellent code. Thanks for the editing too.
Cheers,
hi, the code is really nice. but how can i go tu a URL with the last box?.. im making a 3 level combo (countries, cities, hotel) and i want to go to a xxx.htm when the client select the last field.
How to get back the value of the 'select' with php?
Any way to get rid of the border that shows up for comment #46 code?
Bergs,
You do that with CSS.
form {
border:0;
}
Thanks for the help. Can you show me some demo code for the same code (#46) but with a third menu? I'm getting kind of confused. Thanks! Sorry if you've answered this already, I'm not seeing it if you did.
Bergs,
If you look at the top of this page, on the left, below the menu, there's a button that says 'See demo only'. That might be what you want. Let me know if that doesn't help.
ya that's what i need but its not possible to have that with the new code? its easier to follow and neater...also how would i code a hiding an empty menu? ex. choosing something from the dropdown and another dropdown appears. Thanks.
Bergs,
If you tell me exactly what you're trying to do (send it to me through my contact form if you like), I might be able to quickly put something together for you.
Why this code doesn't work? :
<!DOCTYPE html>
<html>
<form method="post" action="#">
<fieldset id="places">
<p><label>country: <select id="country" name="country">
</select></label>
<label>city: <select id="city" name="city">
</select></label></p>
<label>street: <select id="street" name="street"></select></label>
</fieldset>
</form>
<script>
places=[ ['',['United Kingdom', 'United States', 'Japan']],
['United Kingdom', ['London','Manchester','Liverpool']],
['London', ['Chelsea','Tottenham','Peckham']],
['Chelsea',['Egerton Crescent', 'Carlyle Square', 'St Leonards Terrace']],
['Tottenham', ['Fore Street', 'Philip Lane', 'High Road']],
['Peckham', ['Old Kent Road', 'Patterdale Road', 'Sylvan Grove']],
['Manchester', ['Moss Side', 'Rusholme', 'Fallowfield']],
['Moss Side', ['Broadfield Road', 'Claremont Road', 'Great Western Street']],
['Rusholme', ['Wilmslow Road', 'Heald Place', 'Victory Street']],
['Fallowfield', ['Wilbraham Road', 'Wellington Road', 'Granville Road']],
['Liverpool', ['Croxteth', 'Everton', 'Kirkdale']],
['Croxteth', ['Sovereign Road', 'Regal Road', 'Throne Road']],
['Everton', ['Windermere Street', 'Coniston Street', 'Ullswater Street']],
['Kirkdale', ['Stanley Road', 'King\'s Road', 'Bankhall Street']],
['United States', ['New York', 'Los Angeles']],
['New York', ['The Bronx', 'Queens', 'Manhattan']],
['The Bronx', ['Bronxdale Avenue', 'Bronx River Parkway', 'Bronx Park East']],
['Queens', ['71st Avenue', '72nd Avenue', '73rd Avenue']],
['Manhattan', ['Broadway', 'First Avenue', 'Park Avenue']],
['Los Angeles', ['Beverly Hills', 'Hollywood', 'South Central']],
['Beverly Hills', ['Sunset Boulevard', 'Santa Monica Boulevard', 'Beverly Boulevard']],
['Hollywood', ['Sunset Boulevard', 'Santa Monica Boulevard', 'Hollywood Boulevard']],
['South Central', ['West Gage Avenue', 'East Gage Avenue', 'East Manchester Avenue']],
['Japan', ['Tokyo','Sendai']],
['Tokyo', ['Shinjuku', 'Shibuya', 'Akihabara']],
['Shinjuku', ['Omoide Yokocho', 'Kabukicho Street']],
['Shibuya', ['Koen Street', 'Omotesando', 'Aoyama-dori']],
['Akihabara', ['Chuo-dori', 'Kandamyojin-dori']],
['Sendai', ['Aoba-ku', 'Miyagino-ku', 'Izumi-ku']],
['Aoba-ku', ['Nishi-koen-dori', 'Jozenji-dori', 'Kimachi-dori']],
['Miyagino-ku', ['Route 4', 'Route 45']],
['Izumi-ku', ['Route 4', 'Route 457']]
];
window.onload = function() {
boxes = document.getElementById('places').getElementsByTagName('select');
boxes_len = boxes.length;
our_array = places;
arr_len = our_array.length;
fillEm(0);
for (i=0; <boxes_len-1; i++) {
boxes[ i ].onchange=function() {
for (m=0; m<boxes_len-1; m++) {
if (this==boxes[m]) {
fillEm(m+1);
}
}
}
}
}
function addOptions(the_options, the_sel) {
len = the_options.length;
while (the_sel.hasChildNodes()) {
the_sel.removeChild(the_sel.firstChild);
}
for (i=0; i<len; i++) {
op = document.createElement("option");
the_val = the_options[ i ];
val = document.createAttribute('value');
val.value = the_val;
op.setAttributeNode(val);
the_text = document.createTextNode(the_val);
op.appendChild(the_text);
if (i==0) {
op.selected=true;
}
the_sel.appendChild(op);
}
}
</script>
</html>
Paolo,
You've missed one of the functions. There's a function called 'fillEm()' that you need.
Thanks for the answer so fast
And i have added the functions but he doesn't work , i have the select but all choice are empty
Thanks for help
Its good with the : http://bonrouge.com/br2.php?create=See+demo+only&page=chain_select_js
Code . Thanks
And now i want add a text with the select choice , its possible?
Love your site, have played around with a number of the different variations and actually got them working, not bad for a newbie.
Would appreciate being able to connect code to mysql with this version http://bonrouge.com/demos/chain_select_js_with_extra_div.html
Thanks
Ian,
Have you seen this page? http://bonrouge.com/~chain_select_ajax
It's a little different from this, but it might give you an idea of how to do this with PHP. The code doesn't use a database, but you should be able to easily exchange the arrays for database calls - I mean build the arrays from your mysql queries.
I hope that helps.
I can not get it to work with database, obviously a newbie with lack of knowledge.
Can anyone post code to use http://bonrouge.com/~chain_select_ajax with a database.
Ian,
Hi. You said you can't get it to work with a database. Let me see where you're up to and I might be able to help. You could post your code here or post a link to your test file or send me a link through my contact form. It's up to you. I'll see if I can help.
Great script but I need to be able to add a url to the data in the last box to direct to another page in my site is this possible?
Thanks
andy,
To do that automatically, you can do something like this select-and-go thing here. If you don't want it automatically going anywhere, you need something like a switch statement that will do something when you click a button.
Does that help?
HELLO! I have a question
I modified your code for my needs but it seems that I no longer work.
My code is:
<script type="text/javascript">
places=[['',['Integral', 'Taxa Rezervare', 'Plata La Imbarcare']],
['Integral', ['10']],
['10', ['0']],
['0',['60']],
['Taxa Rezervare', ['10']],
['10', ['60']],
['60', ['0']],
['Plata La Imbarcare', ['10']],
['10', ['70']],
['70', ['-10']]];
function addOptions(the_options, the_sel) {
len = the_options.length;
while (the_sel.hasChildNodes()) {
the_sel.removeChild(the_sel.firstChild);
}
for (i=0; i<len; i++) {
op = document.createElement("option");
the_val = the_options;
val = document.createAttribute('value');
val.value = the_val;
op.setAttributeNode(val);
the_text = document.createTextNode(the_val);
op.appendChild(the_text);
if (i==0) {
op.selected=true;
}
the_sel.appendChild(op);
}
}
function fillEm(no) {
for (j=no; j<boxes_len; j++) {
if (j==0) {
the_options = our_array[0][1];
addOptions(the_options, boxes[j]);
}
else {
pVal = boxes[j-1].value;
for (k = 0; k<arr_len; k++) {
if (our_array[k][0] == pVal) {
the_options = our_array[k][1];
addOptions(the_options, boxes[j]);
}
}
}
}
}
window.onload = function() {
boxes = document.getElementById('places').getElementsByTagName('select');
boxes_len = boxes.length;
our_array = places;
arr_len = our_array.length;
fillEm(0);
for (i=0; i<boxes_len-1; i++) {
boxes.onchange=function() {
for (m=0; m<boxes_len-1; m++) {
if (this==boxes[m]) {
fillEm(m+1);
}
}
}
}
}</script>
Can you help me!
10x
best online writing services <a href="https://papermetering.com/ ">ghostwriter services</a> literature review writing service
I needs to spend some time learning much more or understanding more.
this script is great, you should link it on the menu !
do you think it would be difficult to add more levels, for example, you would select the country, then the state, county etc.. ?