How can I hide select options with JavaScript? (Cross browser)

Unfortunately, you can't hide option elements in all browsers.

In the past when I have needed to do this, I have set their disabled attribute, like so...

$('option').prop('disabled', true);

I've then used the hiding where it is supported in browsers using this piece of CSS...

select option[disabled] {
    display: none;
}

As has been said, you can't display:none individual <option>s, because they're not the right kind of DOM elements.

You can set .prop('disabled', true), but this only grays out the elements and makes them unselectable -- they still take up space.

One solution I use is to .detach() the <select> into a global variable on page load, then add back only the <option>s you want on demand. Something like this (http://jsfiddle.net/mblase75/Afe2E/):

var $sel = $('#sel option').detach(); // global variable

$('a').on('click', function (e) {
    e.preventDefault();
    var c = 'name-of-class-to-show';
    $('#sel').empty().append( $sel.filter('.'+c) );
});

At first I thought you'd have to .clone() the <option>s before appending them, but apparently not. The original global $sel is unaltered after the click code is run.


If you have an aversion to global variables, you could store the jQuery object containing the options as a .data() variable on the <select> element itself (http://jsfiddle.net/mblase75/nh5eW/):

$('#sel').data('options', $('#sel option').detach()); // data variable

$('a').on('click', function (e) {
    e.preventDefault();
    var $sel = $('#sel').data('options'), // jQuery object
        c = 'name-of-class-to-show';
    $('#sel').empty().append( $sel.filter('.'+c) );
});

Had a crack at it myself and this is what I came up with:

(function($){

    $.fn.extend({detachOptions: function(o) {
        var s = this;
        return s.each(function(){
            var d = s.data('selectOptions') || [];
            s.find(o).each(function() {
                d.push($(this).detach());
            });
            s.data('selectOptions', d);
        });
    }, attachOptions: function(o) {
        var s = this;
        return s.each(function(){
            var d = s.data('selectOptions') || [];
            for (var i in d) {
                if (d[i].is(o)) {
                    s.append(d[i]);
                    console.log(d[i]);
                    // TODO: remove option from data array
                }
            }
        });
    }});   

})(jQuery);

// example
$('select').detachOptions('.removeme');
$('.b').attachOptions('[value=1]');');

You can see the example at http://www.jsfiddle.net/g5YKh/

The option elements are fully removed from the selects and can be re-added again by jQuery selector.

Probably needs a bit of work and testing before it works well enough for all cases, but it's good enough for what I need.


I know this is a little late but better late than never! Here's a really simple way to achieve this. Simply have a show and hide function. The hide function will just append every option element to a predetermined (hidden) span tag (which should work for all browsers) and then the show function will just move that option element back into your select tag. ;)

function showOption(value){
    $('#optionHolder option[value="'+value+'"]').appendTo('#selectID');             
}

function hideOption(value){
    $('select option[value="'+value+'"]').appendTo('#optionHolder');
}