jQuery controlled Dependent (or Cascading) Select List 2

Thank you all. Thanx for using, commenting and visiting my script jQuery controlled Dependent (or Cascading) Select List from my old bolg http://php4bd.wordpress.com and here.

I am getting a lots of request and questions from visitors about adding some features and some other problems. Sometimes I faced some problem when using this script myself. So, I have made some changes here. I hope, this change will help you to overcome some problems of previous version of this script. The main features added in this version are:

  1. It will keep in child list box only sub items of selected parent value when initializing.
  2. Added a 4th parameter to input a selected value for child list box.
  3. When "isSubselectOptional" is true, add a default value ‘none’ for ‘– Select –‘ option of child list box.
  4. Automatically focus the child list box when a value is selected from parent list box.
  5. More effective for multilevel association.

Click here to see a demo of multilevel association using this function. here is same demo for jquery 1.3.x users.

Here is the modified function (for < jquery 1.3):

<span style="color: #606060"> 1:</span> <span style="color: #0000ff">function</span> makeSublist(parent,child,isSubselectOptional,childVal)
<span style="color: #606060"> 2:</span> {
<span style="color: #606060"> 3:</span> $(<span style="color: #006080">&quot;body&quot;</span>).append(<span style="color: #006080">&quot;&lt;select style='display:none' id='&quot;</span>+parent+child+<span style="color: #006080">&quot;'&gt;&lt;/select&gt;&quot;</span>);
<span style="color: #606060"> 4:</span> $(<span style="color: #006080">'#'</span>+parent+child).html($(<span style="color: #006080">&quot;#&quot;</span>+child+<span style="color: #006080">&quot; option&quot;</span>));
<span style="color: #606060"> 5:</span> 
<span style="color: #606060"> 6:</span> <span style="color: #0000ff">var</span> parentValue = $(<span style="color: #006080">'#'</span>+parent).attr(<span style="color: #006080">'value'</span>);
<span style="color: #606060"> 7:</span> $(<span style="color: #006080">'#'</span>+child).html($(<span style="color: #006080">&quot;#&quot;</span>+parent+child+<span style="color: #006080">&quot; .sub_&quot;</span>+parentValue).clone());
<span style="color: #606060"> 8:</span> 
<span style="color: #606060"> 9:</span> childVal = (<span style="color: #0000ff">typeof</span> childVal == <span style="color: #006080">&quot;undefined&quot;</span>)? <span style="color: #006080">&quot;&quot;</span> : childVal ;
<span style="color: #606060"> 10:</span> $(<span style="color: #006080">&quot;#&quot;</span>+child+<span style="color: #006080">' option[@value=&quot;'</span>+ childVal +<span style="color: #006080">'&quot;]'</span>).attr(<span style="color: #006080">'selected'</span>,<span style="color: #006080">'selected'</span>);
<span style="color: #606060"> 11:</span> 
<span style="color: #606060"> 12:</span> $(<span style="color: #006080">'#'</span>+parent).change( 
<span style="color: #606060"> 13:</span> <span style="color: #0000ff">function</span>()
<span style="color: #606060"> 14:</span> {
<span style="color: #606060"> 15:</span> <span style="color: #0000ff">var</span> parentValue = $(<span style="color: #006080">'#'</span>+parent).attr(<span style="color: #006080">'value'</span>);
<span style="color: #606060"> 16:</span> $(<span style="color: #006080">'#'</span>+child).html($(<span style="color: #006080">&quot;#&quot;</span>+parent+child+<span style="color: #006080">&quot; .sub_&quot;</span>+parentValue).clone());
<span style="color: #606060"> 17:</span> <span style="color: #0000ff">if</span>(isSubselectOptional) 
<span style="color: #606060"> 18:</span> $(<span style="color: #006080">'#'</span>+child).prepend(<span style="color: #006080">&quot;&lt;option value='none'&gt; -- Select -- &lt;/option&gt;&quot;</span>);
<span style="color: #606060"> 19:</span> $(<span style="color: #006080">'#'</span>+child).trigger(<span style="color: #006080">&quot;change&quot;</span>); 
<span style="color: #606060"> 20:</span> $(<span style="color: #006080">'#'</span>+child).focus();
<span style="color: #606060"> 21:</span> }
<span style="color: #606060"> 22:</span> );
<span style="color: #606060"> 23:</span> }

Again, here is the function for jquery 1.3.x. Thanks a lot to TuxX for tuning up it to work with jquery 1.3.x.

[javascript]
function makeSublist(parent,child,isSubselectOptional,childVal)
{
$("body").append("<select style=’display:none’ id=’"+parent+child+"’></select>");
$(‘#’+parent+child).html($("#"+child+" option"));

var parentValue = $(‘#’+parent).attr(‘value’);
$(‘#’+child).html($("#"+parent+child+" .sub_"+parentValue).clone());

childVal = (typeof childVal == "undefined")? "" : childVal ;
$("#"+child).val(childVal).attr(‘selected’,’selected’);

$(‘#’+parent).change(function(){
var parentValue = $(‘#’+parent).attr(‘value’);
$(‘#’+child).html($("#"+parent+child+" .sub_"+parentValue).clone());
if(isSubselectOptional) $(‘#’+child).prepend("<option value=’none’ selected=’selected’> — Select — </option>");

$(‘#’+child).trigger("change");
$(‘#’+child).focus();
});
}
[/javascript]

And initialize the association on ‘$(document).ready’, as following example:

<span style="color: #606060"> 1:</span> $(document).ready(<span style="color: #0000ff">function</span>()
<span style="color: #606060"> 2:</span> {
<span style="color: #606060"> 3:</span> makeSublist(&#x2019;parentID&#x2019;,<span style="color: #006080">'childID&#x2019;, true, '</span>selected_val_of_child');
<span style="color: #606060"> 4:</span> });

If you want to create multilevel association, start the initialization from child most order. such as:

<span style="color: #606060"> 1:</span> $(document).ready(<span style="color: #0000ff">function</span>()
<span style="color: #606060"> 2:</span> {
<span style="color: #606060"> 3:</span> makeSublist(<span style="color: #006080">'child'</span>,<span style="color: #006080">'grandson'</span>, <span style="color: #0000ff">true</span>, <span style="color: #006080">''</span>); 
<span style="color: #606060"> 4:</span> makeSublist(<span style="color: #006080">'parent'</span>,<span style="color: #006080">'child'</span>, <span style="color: #0000ff">false</span>, <span style="color: #006080">'3'</span>); 
<span style="color: #606060"> 5:</span> });

For details instruction and example of using this script, please visit the previous version. Feel free to ask me if any problem with using this script or any bug you found.

UPDATE [09/10/09] : Updated function added for jquery 1.3.x

248 Comments

  1. Excellent work on this! I’m new to jquery, but here is a modified version of your makeSublist() method that has the behavior that I was looking for.. namely disappearing/reappearing sublists, and working on Firefox 2, IE 6, IE 7, and Safari.

    function makeSublist(parent, child, isSubselectOptional, childVal) {
    $(“body”).append(“”);
    $(‘#’ + parent + child).html($(“#” + child + ” option”));
    var parentValue = $(‘#’ + parent).attr(‘value’);
    $(‘#’ + child).html($(“#” + parent + child + ” .sub_” + parentValue).clone());
    childVal = (typeof childVal == “undefined”) ? “” : childVal;
    $(“#” + child + ‘ option[@value=”‘ + childVal + ‘”]’).attr(‘selected’,’selected’);
    $(‘#’ + parent).change(
    function() {
    var parentValue = $(‘#’ + parent).attr(‘value’);
    $(‘#’ + child).html($(“#” + parent + child + ” .sub_” + parentValue).clone());
    if (isSubselectOptional) {
    $(‘#’ + child).prepend(” — More — “);
    }
    if (document.getElementById(child)) {
    if (document.getElementById(child).options.length == 1) {
    document.getElementById(child).style.visibility = ‘hidden’;
    } else {
    document.getElementById(child).style.visibility = ‘visible’;
    $(‘#’ + child).trigger(“click”);
    }
    } else {
    $(‘#’ + child).trigger(“click”);
    }
    $(‘#’ + child).trigger(“change”);
    }
    );
    }


    Jason
    Co-author, Tomcat: The Definitive Guide, 2nd Edition

  2. Great… I’m a newbie at JS… i need to redirect the visitor to a specific url once the user choosed the an option from the second dropdown:

    I mean;
    1) User selects one option from first dropdown.
    2) User selects one option from second dropdown.
    3) User is redirected to a specific #

    Thanks!

  3. @Martin
    Hi Martin, Thanx for ur question.
    I think, u may already get the solution. If not, please follow this steps:
    1. Set the urls, where u want to rediract as the values of child select box.
    2. On change event of child select box, call a function to rediract the page like this:

    $(“child_select_id”).change( function() {
    var theURL = $(“child_select_id”).val();
    window.location = theURL ;
    } );

    Define this binding in the ready enent of document.
    Please let me know if any more confution here.

  4. I am new to developing web sites with some very basic knowledge of PHP, some MySQL and a bit of HTML and almost none of Java. I have been trying to have 3 dependat option boxes. I tried to incorporate your script into the data extraction from MySQL to narrow down the department name down to financial years and further down to months for available reports to view. I am getting very ad-hoc results. I have listed my script here and I would greatly appreciate any help. Many thanks:

    function makeSublist(parent,child,isSubselectOptional,childVal)
    {
    $(“body”).append(“”);
    $(‘#’+parent+child).html($(“#”+child+” option”));

    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());

    childVal = (typeof childVal == “undefined”)? “” : childVal ;
    $(“#”+child+’ option[@value=”‘+ childVal +'”]’).attr(‘selected’,’selected’);

    $(‘#’+parent).change(
    function()
    {
    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());
    if(isSubselectOptional) $(‘#’+child).prepend(” — Select — “);
    $(‘#’+child).trigger(“change”);
    $(‘#’+child).focus();
    }
    );
    }

    $(document).ready(function()
    {
    makeSublist(‘child’,’grandson’, true, ”);
    makeSublist(‘parent’,’child’, false, ‘1’);
    });

    – Select Dept –

    “. $row[‘dept_name’] .””;
    }
    ?>

    “.$row[‘fy’].””;
    }
    ?>

    “. $row[‘month’] .””;
    }
    ?>

  5. This is really great..but just can’t seem to get 6 levels working in IE or Safari. Also, I’m very interested in an example of how to make certain items open links.

    Is there anyway you could slap together a quick 6 level example with a few links? this would be so perfect!

    thanks!

  6. Hi,

    Please note that in the latest version of Jquery 1.2.2, this does not work in IE browser (6.XX)

    The older version of Clone function is quite different from the new version of Jquery.

    TO workaround, you acn copy the clone fuction from old Jquery to the nwe jquery script and name it as clone_old and use clone_old in the line and it should look like this:
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone_old());

    Is there any other workaround ?

    Anand (acpadhi@twindia.com) &
    Shankar (shanki1969@yahoo.co.in)

  7. Great work.
    The script is very good, here it is an idea for a new feature. If you use tag inside , the script will just ignore it. It would be nice to display also the label.

  8. Great work.
    The script is very good, here it is an idea for a new feature. If you use optgroup tag inside select, the script will just ignore it. It would be nice to display also the optgroup label.

  9. I am wanting to incorporate your script into a dynamic php+mySQL app, and it works WONDERFULLY for creating new records. Problem is encountered when I attempt to show user an existing record for editing that has an existing value for child field. How do you get the initialization function to recognize and retain the value passed from the database.

  10. Forget it, I figured it out. I added a line to the initialization function
    childValue = $(‘#’+child).attr(‘value’);
    and then used that variable in makeSublist().

    This is script is just what I was looking for, very clean and efficient! Many thanks for sharing!

  11. Sorry to bother you again. But making that last change has introduced other problems. Now the child does not filter values based on parent change it shows all values available and does not change. *darn it*!

  12. Got it! (with a small *duh*) I was quite obviously calling for the value of the child element incorrectly for use in the makeSublist function. Thanks again for sharing solution and providing supporting explanation.

  13. hi;

    is there away to add a submit at the bottom , so when presed , it will show the selected valuse from the dropdown ?

    thanks jeff

  14. Very good script! But it only works with regular characters and no blank spaces… 🙁
    Is there a way to use it with options like “cork oak”, or “túlipa”?
    I’ve tried with different CHARSET, but never worked.
    Thank you in advance.

  15. I was trying to implement this and for some reason cannot get the “none” selected in IE6. Not sure if this is an IE6 bug, but I’m working with 1.2.6 version of jQuery. Is there something else I’m missing for this example?

  16. Thanks for this great script!
    I am trying to implement it in a Zend Framework environment, but the problem is that I can’t assign a css class to in any select box. I have therefore tried to match the relevant child-options by their value. I have then a bunch of options with the value journey_ID_SECID where the first ID is the exact value of the first select-box and SECID is the DB-ID I am using for further processing and validation. Is there a possibility to do this sort of matching?
    Cheers!

  17. @Dobo
    Hi Friend,
    I’ve already implemented it with ZF in my previous project which was 90% same with your idea. 🙂
    If you are using Zend_Form, you can assign a class to a select box as:
    $mySelectBox->setAttrib(‘class’, ‘large’);

    Hope to write a post about implementing this script with Zend Framework by next Weekend.

    Thank you Dobo.

  18. @Anis
    Hi Anis,

    Thank you for the quick reply.

    Here is my current problem(more detailed):

    My form is extending the main Zend_Form class and is being declared in a separate file in the appropriate directory.

    This is how my controller currently looks like (the relevant part of course):
    foreach($alltours as $select_input):
    $form->reisen->addMultiOption($select_input[‘id’], $select_input[‘name’]);
    if(!empty($id)) $form->reisen->setValue($id);
    endforeach;

    foreach($alltours as $select_input):
    $form->reisetermin->addMultiOption(‘termin_’.$select_input[‘id’].’_’.$select_input[‘date_id’] , date(‘d.m.Y’, strtotime($select_input[‘date_start’])) );
    //$form->reisetermin->setAttrib(‘class’, ‘large’);
    endforeach;
    As you can see, I am filling the values of the with a loop, whereas the form element “reisetermin” is being declared in the form/form.php file.

    Now your script, being as good as it is, is matching the sublist-values by their class-name. I however have no possibility to set multiple class-names to the options in this -box. That is why I tried doing it by a value-match, and that is where I got stuck.

    Any help will be greatly appreciated.

    Thanks in advance!

  19. Hi again,

    I figured it out. As I said, my tags had no class-names and values like “termin_1_12”.

    When I added this:
    $(“#”+child+” option”).each(
    function() {
    var buildChildData= $(this).attr(‘value’).split(“_”);
    $(this).addClass(“sub_”+buildChildData[1]);
    });

    to the top of your function it all worked out.

    Thank you once more for the great script!

  20. @Dobo
    Yes friend! that’s the technique.
    But needs a little change for re-setting values (otherwise you can it in backend).
    Just like this-

    $(”#”+child+” option”).each(
    function() {
    var buildChildData= $(this).attr(’value’).split(”_”);
    $(this).addClass(”sub_”+buildChildData[1]);
    $(this).attr(‘value’, ”sub_”+buildChildData[<value-index>]);
    });

    I couldn’t post the solution yet as promised because of time. Hope to do it soon. U r invited to visit(and suggest to make it better) that.

  21. I am new to jquery and would like to know where to change the script so that the function does the following:

    When user selects the last option of list 3, it launches a URL.

    Any assistance in providing the exact script for this action would be greatly appreciated.

    Thanks in advance!!!

  22. I am attempting to develop a site to which I would like to use 3 listboxes which are dependent to one another. At the very last selection of the 3rd listbox, I would like a script to launch a URL.

    Is there anyone that can assist in providing source code that modifies the code to allow it to perform the launch of a URL?

    Anyone that can assist, it would be appreciated.

    Thank you!

  23. @Tony Fox
    Hi friend,
    It’s very simple. 🙂

    just 2 steps
    1. Make the select boxes cascading as the demo shows.
    2. in your $(document).ready, bind a function with 3rd select box:
    $(“#3rd-select”).change(function () {
    if($(this).val() == ‘a-value’)
    {
    window.location=”http://someplace.com”;
    }
    elseif($(this).val() == ‘another-value’)
    {
    window.location=”http://some-other-place.com”;
    }
    })

  24. I am a true amature and appreciate your assistance. My ultimate goal would be to use the first listbox for a list of all the states, the second for all the cities and the third for the names of schools within those cities. Once they select the school, it would launch a URL to details about that school. I attempted to update the script that you had provided for the example, but I can’t get it to work. Below is the final code I have. Is there a way to refer the scripts to an XML file for the list?

    Again, thanks for your assistance!

    function makeSublist(parent,child,isSubselectOptional,childVal)
    {
    $(“body”).append(“”);
    $(‘#’+parent+child).html($(“#”+child+” option”));

    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());

    childVal = (typeof childVal == “undefined”)? “” : childVal ;
    $(“#”+child+’ option[@value=”‘+ childVal +'”]’).attr(‘selected’,’selected’);

    $(‘#’+parent).change(
    function()
    {
    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());
    if(isSubselectOptional) $(‘#’+child).prepend(” — Select — “);
    $(‘#’+child).trigger(“change”);
    $(‘#’+child).focus();
    }
    );
    }

    $(document).ready(function()
    {
    makeSublist(‘child’,’grandsun’, true, ”);
    makeSublist(‘parent’,’child’, false, ‘1’);
    });

    $(‘grandsun’).change(function ()
    {
    if($(this).val() == ’13’)
    {
    window.location=”http://www.yahoo.com”;
    }
    elseif($(this).val() == ’14’)
    {
    window.location=”http://www.google.com”;
    }
    })

  25. I’m using the latest jQuery v1.3.1 and it keeps throwing the following exception:

    Syntax error, unrecognized expression: [@value=”selected_val_of_child”]’ when calling method: [nsIDOMEventListener::handleEvent]

    Is there a fix or workaround for this?

  26. Hey Pablo,

    use this:

    function makeSublist(parent,child,isSubselectOptional,childVal)
    {
    $(“body”).append(“”);
    $(‘#’+parent+child).html($(“#”+child+” option”));

    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());

    childVal = (typeof childVal == “undefined”)? “” : childVal ;
    $(“#”+child).val([“‘+ childVal +'”]).attr(‘selected’,’selected’);

    $(‘#’+parent).change(
    function()
    {
    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .sub_”+parentValue).clone());
    if(isSubselectOptional) $(‘#’+child).prepend(” — Select — “);
    $(‘#’+child).trigger(“change”);
    $(‘#’+child).focus();
    }
    );
    }

    $(document).ready(function()
    {
    makeSublist(‘child’,’grandsun’, true, ”);
    makeSublist(‘parent’,’child’, false, ‘1’);
    });

  27. Thanks for the code snippet.

    With jquery 1.2.6 it works fine.

    Under jquery 1.3.2 it doesnt. The console has the error:
    [Exception… “‘Syntax error, unrecognized expression: [@value=”1″]’ when calling method: [nsIDOMEventListener::handleEvent]” nsresult: “0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)” location: “” data: no]

    Any ideas?
    Thanks,
    Andy

  28. A downloadable sample or source code for a simple form with 2 or three select boxes would go a long way in furthering my understanding of how to implement this.

  29. hi

    This is great and exactly what i’m looking for – however i cant get the script working with jquery 1.3.2. do you have any ideas please?

    Thanks

  30. I too am having similar issues as Carlo. It appears that jQuery 1.3.2 does not work with this code. I am not sure what it is about it though, the new version of jQuery doesn’t like about it.

  31. Thanks so much for this. Just one question – any idea why when I try to implement this the first time you navigate to the page the “grandson” element is blank, but when I refresh it shows up?

  32. Pingback: | ????? ?
  33. This version only works under Jquery 1.2.6 not 1.3.2. so please update for us. thanks.
    I have a problem which is that the –select– item is not preselected when parent item is changed. Instead, the first real item is selected. –select — was there, but it is not preselected.

  34. Pingback: jQuery????????
  35. Hi All
    I’ve added TuxX’s proposed function (with little change) in the main post for jquery 1.3.x users. Additionally, added a demo for jquery 1.3.2.

    I hope, it’s easy enough to understand and use. For better understanding, you can see the source code of demo pages and this post : http://www.ajaxray.com/blog/2007/07/15/javascript-controlled-dependent-or-cascading-select-list/

    Someone have reported a problem with default –Select– option. It’s also fixed.

    Thanks to all for using and asking for jquery-1.3.x compatible version (and complaining for being late) 🙂

  36. Pingback: 240??jQuery??????
  37. Pingback: ????jQuery?? « ??
  38. Hi,
    I am trying to get this to work for employees table – all three are required:
    select1: office name
    select2: office location
    select3: first name, last name
    Based of the name selected – I populate the remaining fields of the form.
    any suggestions..
    Thanks
    GS

  39. Hi Anis,

    Thank you for this beautiful script. I have a situation were i want to create dynamic dependent drop down list. For e.g. There is a Room drop down with values 1 to 4. If i select 1. Then there will two more drop downs one for Adult and second of Children. If you select 2 then there should be 2 row of drop down for adult and children. The children drop down goes from 0 to 4. If i select 4 from Children drop down then four drop down for age should populate.

    On LHS of this site find your hotel, http://bestofvegas.com/ I want to do something similar to this. Can you advice how can the same be achieved with jquery.

    Your valuable advice will be precious to me.

  40. I’m really new in Jquery… in fact this is my first attemp to do something, so it’s still hard to me to understand the most simple function.

    Anyway I’ll like to know, when you click a child option in the last select, at this moment you’ve got a cathegory selected (parent) and a child…

    How can I get their values?????????

    I mean, deppending on a value selected, I want that an image it’s displayed in the browser (and/or text!) How can this be accomplished???????

    Any help will be greatly appreciated 😉 Thanks =D

  41. Pingback: ?????240??jQuery??
  42. Pingback: palino
  43. Nice Work saved me some time however had to make a few changes.

    function makeSublist(parent,child,isSubselectOptional,childVal)
    {
    $(“body”).append(“”);
    $(‘#’+parent+child).html($(“#”+child+” option”));

    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .”+parent+”_”+parentValue).clone());

    childVal = (typeof childVal == “undefined”)? “” : childVal ;
    $(“#”+child).val(childVal).attr(‘selected’,’selected’);

    $(‘#’+parent).change(function(){
    var parentValue = $(‘#’+parent).attr(‘value’);
    $(‘#’+child).html($(“#”+parent+child+” .”+parent+”_”+parentValue).clone());
    if(isSubselectOptional) $(‘#’+child).prepend(” — Select — “);

    $(‘#’+child).trigger(“change”);
    $(‘#’+child).focus();
    });
    };

    This version allows multiple lists to be cascaded at the same time without classes being confused.

    It takes the parent name and uses it rather the sub_ name used perviously. Which means your sublists will need to have the parent list name _ rather then the sub_ in the class to work.

    Hope this makes sense.

    And thanks again, saved me a lot of work.

    kym.

  44. Hi,

    I tried your script (jquery 1.3.x version, while using jquery 1.4.3) and it works very nicely, except for this issue:

    I want to use the ” selected=’selected’ ” HTML tag to open the lists with the correct options selected when viewing a record from the database. This fails to work.

    I hope you can help me on this issue.

    Kind regards,
    Fritz

  45. Pingback: jQuery????? | ???
  46. Pingback: JQuery library

Leave a Comment

Your email address will not be published. Required fields are marked *