6

I'm trying to count the number of options in a list. However, some of the options have been hidden due to the search text entered into an input box.

I started off looking into .size() and .length but was only getting the full list rather than those that were not hidden. In order to simplify, I've changed it to try and find the hidden options (I can use :not later).

$('#txtListSearch').keyup(function(evt) {
    if($(this).val().length < 1) {
        $('#selContactLists option').show();
    } else {
        $('#selContactLists option:not(:contains("' + $(this).val() + '"))').hide();

        if($('#selContactLists').size()) {
            $('#selContactLists option:contains("' + $(this).val() + '")').first().attr('selected', 'selected');                
        } else {
        }
    }
    console.log($('#selContactLists option').filter(':hidden'));
});

I've also tried: console.log($('#selContactLists option:hidden')); I never quite get the number I'm expecting. Can anyone see where I'm going wrong?

Even more odd, is that if I change the "size" of the select so that more than one item is shown by default, on chrome it never hides any of the options.

Artemis
  • 2,553
  • 7
  • 21
  • 36
David
  • 320
  • 1
  • 6
  • 22
  • can you also post an HTML example ? – Stefan Aug 14 '12 at 14:43
  • Side-Note on `size()` cause youm entioned it. It has been marked depracated. From the docs: `The .size() method is functionally equivalent to the .length property; however, the .length property is preferred because it does not have the overhead of a function call.` (http://api.jquery.com/size/) – Nope Aug 14 '12 at 14:45
  • On what basis do the options hide, or show? – David Thomas Aug 14 '12 at 15:33
  • it is determined by the text in the search box: http://jsfiddle.net/kcRUB/3/ – David Aug 14 '12 at 15:36
  • Yes, I've seen the fiddle. I'm assuming that typing `t` should show both `two` and `three`? And `o` should show only `one`? – David Thomas Aug 14 '12 at 15:41

3 Answers3

4

This works for me, but you might want to manually add and remove the css display:none from the elements, instead of using show/hide, for compatibility reasons...

alert($('#selContactLists option:not([style*=none])').length);
LJ2
  • 593
  • 5
  • 11
3

Use jQuery's :visible selector.

$('#selContactLists option:visible').length;
James Hill
  • 60,353
  • 20
  • 145
  • 161
  • 1
    Hi James, this always come back with zero. I used .hide() to hide them from view in the first place, but on an example where the list has been filtered from 3 options down to 2, I still get 0 – David Aug 14 '12 at 15:04
  • @David, post your markup. Even better, throw an example [fiddle](http://jsfiddle.net) together for us. – James Hill Aug 14 '12 at 15:17
  • @David, do you even intend to put the hidden options back? – James Hill Aug 14 '12 at 15:32
  • Yes, if you remove all the text from the search then they reappear – David Aug 14 '12 at 15:34
  • It appears to be a chrome issue, it works in Firefox if I do:alert(($('#selContactLists option').filter(':visible').length)); – David Aug 14 '12 at 15:49
  • This doesn't work in all browsers and should not be used as a solution. – Yuck Apr 06 '14 at 17:53
1

One approach that seems to work is the following, though it cheats, somewhat, by assigning the options that are hidden, and shown, to variables and then using the .length property of those variables:

$('#txtListSearch').keyup(
    function(e) {
        var val = $(this).val().toLowerCase(),
            sel = $('#selContactLists');
        if (val.length < 1) {
            sel.find('option').show();
        }
        else {
            var shown = sel.find('option').filter(

                function() {
                    return $(this).text().toLowerCase().indexOf(val) !== -1;
                }).show().first().prop('selected',true),
                hidden = sel.find('option').filter(

                function() {
                    return $(this).text().toLowerCase().indexOf(val) == -1;
                }).hide();
            console.log(shown.length, hidden.length);
        }
    });​

JS Fiddle demo.

Please note that the above is a relatively large re-write of your original code. I've used some caching of selectors to reduce the number of times the DOM is accessed from within the keyup method, and, currently, because of the .toLowerCase() methods this is a case-insensitive search, and also shifts the selectedIndex to the first of the non-hidden options (in Chromium this seemed to be required in order to allow one to be hidden while it was shown in the select while typing t).

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • This still doesn't work for me. I get incorrect counts for both shown and hidden. All of the attempts above are producing different results in each browser. I think the storage of the options in a separate array and then populating or removing the elements is the way to go. I tried increasing the size of the select box also so more than one element is displayed at a time and in this case none of the elements are hidden. I think hiding is not a good idea, removal is the answer. I've +1'd your answer as it's not quite right (for me at least) but it's set me on the right path. – David Aug 15 '12 at 10:05