4

I have two lists one displays cars company and the second one displays all the cars

Here is the first comboxbox ( The first option is ALL)

<select id="company">
     <option selected="true" >ALL</option>
    <option>GM</option>
    <option>Honda</option>
    <option>Ford</option>
</select>

here is my second lisbox

<select id="names" multiple="multiple" size="8">
    <option>Chevy [GM]</option>
    <option>Buick [GM]</option>
    <option>Civic [Honda]</option>
    <option>Accord [Honda]</option>
    <option>Focus [Ford]</option>
</select>

Based on the first combox selection , I should display only that car company cars in the second list . Even the second list has the car company name in brackets .. This is fixed format . Again from the the first list if user selects "ALL" I should show all the vehicles .

Could any body give me an idea to implement this or code snippet for this ?

Thanks for your help

Regards

Kiran

Bujji
  • 1,717
  • 10
  • 41
  • 66

7 Answers7

6

Not all browsers allow you to hide the individual items in a drop-down list, so you need to keep a master list, and then repopulate based on that.

var names = $('#names option').clone();

$('#company').change(function() {
    var val = $(this).val();  
    $('#names').empty();
    names.filter(function(idx, el) {
        return val === 'ALL' || $(el).text().indexOf('[' + val + ']') >= 0;
    }).appendTo('#names');
});

Working demo at http://jsfiddle.net/alnitak/WsHvS/

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Thanks @Alnitak for this wonderful solution . I am testing this for around 12oo records and let you know the result – Bujji Apr 21 '11 at 19:34
  • FWIW this could be made faster if necessary by storing the make in a separate field so that .text().indexOf() isn't called for every row each time the list is refreshed. I've also just changed .html() to .text() – Alnitak Apr 21 '11 at 19:45
  • Once again thanks . Just tested with 1500 cars and every thing went well . – Bujji Apr 21 '11 at 20:17
2

As far as I know, hiding of select options only works on Firefox, so for cross browser compatibility you need to use a bit more trickery (see this SO question and this question among others). This is what I suggest:

For HTML, have a hidden copy of your select as well as the version you currently provide:

<select id="company">
    <option selected="true" >ALL</option>
    <option>GM</option>
    <option>Honda</option>
    <option>Ford</option>
</select>
<br />
<div id="namesDiv">
    <select id="names" multiple="multiple" size="8">
        <option>Chevy [GM]</option>
        <option>Buick [GM]</option>
        <option>Civic [Honda]</option>
        <option>Accord [Honda]</option>
        <option>Focus [Ford]</option>
    </select>
</div>
<select id="baseNames" multiple="multiple" size="8">
    <option>Chevy [GM]</option>
    <option>Buick [GM]</option>
    <option>Civic [Honda]</option>
    <option>Accord [Honda]</option>
    <option>Focus [Ford]</option>
</select>

Hide basenames with CSS display:none.

Then for your jQuery, you'll be replacing names regularly with a cloned version of baseNames and filtering it.

$(document).ready(function() {
    $("#company").change(function() {
        $("#namesDiv").empty();
        $("#baseNames").clone().appendTo("#namesDiv").attr("id", "names");
        var val = $(this).find("option:selected").val();
        if(val !== "ALL") {
            $("#names option").each(function() {
                if($(this).val().indexOf(val) < 0) {
                    $(this).remove();
                }
            });
        }
    });
});

You can see this in action.

Community
  • 1
  • 1
justkt
  • 14,610
  • 8
  • 42
  • 62
1

EDIT: Works in FF only

Try this:

$(function(){
 $("#company").change(function(){
    var val = $(this).val();
    $("#names option").hide().filter(function(){
        var regExp = new RegExp("\\[" + val + "\\]$");
        return (val == "ALL") || regExp.test($(this).text());
    }).show();
 });
});

Example: http://jsfiddle.net/Chandu/2Zppp/

Chandu
  • 81,493
  • 19
  • 133
  • 134
0

You can each() on the second select's options in change() of the first select, search for substring and set the disabled attribute. (But this solution has a flaw: not every browser supports disabled attribute for option, AFAIK.)

UPDATE

And if you want to hide options completely, you should consider storing items from your second select in some temp storage and re-populate that select from the storage only with items that match your criteria.

UPDATE2

    var temp = new Array();

    $(document).ready(function(){

    //save in temp
    $('select#names').children().each(function(){temp.push($(this).val());});

    //change handler
    $('select#company').change(function(){
        var pref = $(this).val();
        $('select#names').children().remove();

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

            if(pref=='ALL' || temp[i].match('.[\\[]'+pref+'[\\]]$') )
                $('select#names').append('<option>'+temp[i]+'</option>');
        }

        });
    });
Dmitry
  • 3,069
  • 1
  • 17
  • 26
0

http://css-tricks.com/dynamic-dropdowns/

This is you wanted try to do with first option using text files or alternative option is JSON.

Vishwanath Dalvi
  • 35,388
  • 41
  • 123
  • 155
  • the code on that website is horrendous - storing arrays within JSON as comma separated text instead of as a JSON array?! – Alnitak Apr 21 '11 at 19:31
0

Edit: Tested and working with IE7 and Firefox 3.6.x

Live Demo

HTML: note the value="" on the ALL option

<select id="company">
    <option selected="true" value="">ALL</option>
    <option>GM</option>
    <option>Honda</option>
    <option>Ford</option>
</select>

<select id="names" multiple="multiple" size="8">
    <option>Chevy [GM]</option>
    <option>Buick [GM]</option>
    <option>Civic [Honda]</option>
    <option>Accord [Honda]</option>
    <option>Focus [Ford]</option>
</select>

jQuery:

$('#company').change(function() {
    var make = $(this).val();
    $('#names').contents().each(function() {
        if (this.nodeType == 8 && this.nodeValue.length > 0 && this.nodeValue.indexOf(make) != -1) {
            $(this).before('<option>' + this.nodeValue + '</option>');
            $(this).remove();
        }
        else if ($(this).val().indexOf(make) == -1 && $(this).val().length > 0) {
            $(this).replaceWith('<!--' + $(this).val() + '-->');
        }
    });
});
drudge
  • 35,471
  • 7
  • 34
  • 45
0

Another option is to assign a classname to the options like this:

  <select id="names" multiple="multiple" size="8">
    <option class="gm">Chevy [GM]</option>
    <option class="gm">Buick [GM]</option>
    <option class="honda">Civic [Honda]</option>
    <option class="honda">Accord [Honda]</option>
    <option class="ford">Focus [Ford]</option>
  </select>

Then based on the class you can show() and hide() like this:

 $(document).ready(function(){
   $("#names>option").hide();
   $("#company").change(function(){
     $("#names>option").hide();
     $("#names>." + $(this).val()).show();
     if($(this).val() == "ALL"){
          $("#names>option").show();
     }
   });
});
Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192