views:

192

answers:

1
+3  Q: 

jQuery Filtering

Is there a way to filter a multi-line select box using jQuery?

I'm a new to jQuery and can't seem to figure out the best way to do this.

For example if I have:

<select size="10">
   <option>abc</option>
   <option>acb</option>
   <option>a</option>
   <option>bca</option>
   <option>bac</option>
   <option>cab</option>
   <option>cba</option>
   ...
</select>

I want to filter this list based on a selection drop down with:

<select>
   <option value="a">Filter by a</option>
   <option value="b">Filter by b</option>
   <option value="c">Filter by c</option>
</select>
+5  A: 

Something like this might do the trick (assuming you give your 'Filter by...' select an id of filter and the filtered / other select an id of otherOptions):

$(document).ready(function() {
    $('#filter').change(function() {
        var selectedFilter = $(this).val();
        $('#otherOptions option').show().each(function(i) {
            var $currentOption = $(this);
            if ($currentOption.val().indexOf(selectedFilter) !== 0) {
                $currentOption.hide();
            }
        });
    });
});

UPDATE: As @Brian Liang pointed out in the comments, you might have problems setting the <option> tags to display:none. Therefore the following should give you a better cross-browser solution:

$(document).ready(function() {
 var allOptions = {};

 $('#otherOptions option').each(function(i) {
  var $currentOption = $(this);
  allOptions[$currentOption.val()] = $currentOption.text();
 });

 $('#filter').change(function() {
  // Reset the filtered select before applying the filter again
  setOptions('#otherOptions', allOptions);
        var selectedFilter = $(this).val();
        var filteredOptions = {};

        $('#otherOptions option').each(function(i) {
            var $currentOption = $(this);

            if ($currentOption.val().indexOf(selectedFilter) === 0) {
                filteredOptions[$currentOption.val()] = $currentOption.text();
            }
        });

        setOptions('#otherOptions', filteredOptions);
    });

    function setOptions(selectId, filteredOptions) {
     var $select = $(selectId);
     $select.html('');

     var options = new Array();
     for (var i in filteredOptions) {
      options.push('<option value="');
      options.push(i);
      options.push('">');
      options.push(filteredOptions[i]);
      options.push('</option>');
     }

     $select.html(options.join(''));
    }

});
Ian Oxley
I don't think this works since you cannot hide that option element.
Floetic
@Brian Liang I did do a quick test in Firefox before I posted and it worked. However I have just checked in Opera, Safari, Chrome and IE 8 and you're right: it does not work in those browsers.
Ian Oxley
+1 though, I like the idea.
Floetic
wow thanks guys.
Tim, I tried it in Chrome/IE and it works like a charm. Great work Ian!
Floetic