Como esconder uma <option> em um menu <select> com CSS?


103

Percebi que o Chrome, ao que parece, não permite que eu me esconda <option>em um <select>. O Firefox vai.

Preciso ocultar os <option>s que correspondem aos critérios de pesquisa. Nas ferramentas da web do Chrome, posso ver que elas estão sendo definidas corretamente display: none;pelo meu JavaScript, mas uma vez que o <select>menu é clicado, elas são exibidas.

Como posso fazer com que esses <option>s que correspondem aos meus critérios de pesquisa NÃO sejam exibidos quando o menu for clicado? Obrigado!


4
Em vez de se esconder e mostrar em uma pesquisa. Tente preencher o select de acordo com a pesquisa
— Henesnarfel

1
Eu concordo com Henesnarfel. Se você já está fazendo uma pesquisa ou algum tipo de consulta, deve poder preencher apenas os que deseja.
— Michael Stramel

1
isso funciona bem para mim no Chrome 16.0.912.77 m. Estou entendendo mal o problema?
— mgibsonbr de

3
@mgibsonbr Não funciona em vários navegadores.
— Jasper

3
@Henesnarfel Pode haver boas razões para ocultar opções. Por exemplo, eu tinha uma página com uma caixa de listagem selecionada e links para ocultar ou mostrar itens marcados como inativos. Não há razão para manter várias listas ou consultar o servidor por uma nova lista sempre que o usuário alterar essa opção.
— Ryan P de

Respostas:


69

Você deve implementar dois métodos de ocultação. display: nonefunciona para FF, mas não para Chrome ou IE. Portanto, o segundo método é envolver o <option>em a <span>com display: none. O FF não fará isso (HTML tecnicamente inválido, de acordo com as especificações), mas o Chrome e o IE farão e ocultarão a opção.

EDIT: Ah sim, já implementei isso no jQuery:

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        if( jQuery( this ).parent( 'span.toggleOption' ).length == 0 )
            jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

EDIT 2: Veja como você usaria esta função:

jQuery(selector).toggleOption(true); // show option
jQuery(selector).toggleOption(false); // hide option

EDIT 3: Adicionada verificação extra sugerida por @ user1521986


1
Este método maluco é o único que realmente funcionou completamente em vários navegadores e não envolveu a criação de uma caixa de seleção falsa oculta.
— Jesse Atkinson

15
Cuidado com isso. Parece funcionar muito bem no início, mas em algum ponto ao longo da linha ele pára. Aqui está uma pequena demonstração: jsfiddle.net/Yb6sk/9
— Bill Criswell

17
Embora esta solução oculte o elemento, qualquer tentativa de ler o valor de <select>(usando jQuery .val()) retornará null. Acabei de testar isso no Chrome 29, portanto, os Googlers, cuidado!
— Marcos

10
Hack interessante, mas eu recomendaria evitar "HTML tecnicamente inválido" se possível.
— Luke

3
É verdade que todos os navegadores têm implementações diferentes. Mas um motivo pelo qual os navegadores não podem implementar estritamente as especificações padrão é porque há muito código ativo por aí que não segue as especificações. IMO: Se não houver outras soluções, use um hack. Mas se você pode seguir as especificações e resolver seu problema, por que não o faria? Isso ajuda seu código a funcionar bem com os outros e ajuda a fortalecer as especificações.
— Lucas

82

Para HTML5, você pode usar o atributo 'oculto'.

<option hidden>Hidden option</option>

É não suportado pelo IE <11. Mas se você só precisa de esconder alguns elementos, talvez seria melhor apenas para definir o atributo oculto em combinação com deficientes em comparação a adição / remoção de elementos ou não fazer semanticamente construções corretas.

<select>  
  <option>Option1</option>
  <option>Option2</option>
  <option hidden>Hidden Option</option>
</select>

Referência .


4
O IE 11 oferece suporte para isso.
— Iván Pérez

7
Esta é a resposta moderna. Idealmente, também estamos definindo isso para disabledque os navegadores que não suportam o atributo global HTML5hidden tenham alguma indicação visual para o usuário.
— cloudworks de

1
Como você usa essa técnica com CSS?
— GetFree

7
Não funciona no Safari, Edge ou IE. Bug para Safari tem 10 anos, por favor ajude atualizando os patches existentes. Não é possível encontrar bug no rastreador de problemas do Edge.
— Indolente de

7
Uma solução alternativa para isso é usar <option hidden disabled>, portanto, oculta em todos os bons navegadores e desativa nos outros.
— Ramon Balthazar

37

Eu sugeriria que você não use as soluções que usam um <span>invólucro porque não é um HTML válido, o que pode causar problemas no futuro. Acho que a solução preferida é realmente remover todas as opções que você deseja ocultar e restaurá-las conforme necessário. Usando jQuery, você só precisará dessas 3 funções:

A primeira função salvará o conteúdo original da seleção . Por segurança, convém chamar essa função ao carregar a página.

function setOriginalSelect ($select) {
    if ($select.data("originalHTML") == undefined) {
        $select.data("originalHTML", $select.html());
    } // If it's already there, don't re-set it
}

A próxima função chama a função acima para garantir que o conteúdo original foi salvo e, em seguida, simplesmente remove as opções do DOM.

function removeOptions ($select, $options) {
    setOriginalSelect($select);
    $options.remove();
 }

A última função pode ser usada sempre que você quiser "redefinir" para todas as opções originais.

function restoreOptions ($select) {
    var ogHTML = $select.data("originalHTML");
    if (ogHTML != undefined) {
        $select.html(ogHTML);
    }
}

Observe que todas essas funções esperam que você esteja passando elementos jQuery. Por exemplo:

// in your search function...
var $s = $('select.someClass');
var $optionsThatDontMatchYourSearch= $s.find('options.someOtherClass');
restoreOptions($s); // Make sure you're working with a full deck
removeOptions($s, $optionsThatDontMatchYourSearch); // remove options not needed

Aqui está um exemplo prático : http://jsfiddle.net/9CYjy/23/


3
Confiável e não um hack. Ótima resposta!
— Jeremy Cook de

1
@DanBeaulieu Havia uma função nomeada incorretamente no jsfiddle anterior. Consertei e atualizei o link acima. Obrigado por pegar isso.
— Lucas

Sim, esta também foi minha escolha. Na verdade, consegui reduzir o código um pouco, primeiro colocando o valor dos dados em uma variável, se indefinido, ele salvará as opções, caso contrário, restaurará as opções. Minha necessidade era específica para tal.
— diynevala

1
Tive que adicionar var value=$select.val(); $select.html(ogHTML); $select.val(value);para manter o valor selecionado selecionado mesmo após a restauração.
— diynevala

O ciclo de seleção das opções para remover e removê-las funcionou apenas uma vez. Depois disso, options.remove () não teve nenhum efeito para mim. Depois que movi restoreOptions ($ s), chamei algumas linhas para que eu estivesse sempre trabalhando com um objeto Select completo e novo, funcionou.
— Newclique

18

A resposta de Ryan P deve ser alterada para:

    jQuery.fn.toggleOption = function (show) {
        $(this).toggle(show);
        if (show) {
            if ($(this).parent('span.toggleOption').length)
                $(this).unwrap();
        } else {
            **if ($(this).parent('span.toggleOption').length==0)**
                $(this).wrap('<span class="toggleOption" style="display: none;" />');
        }
    };

Caso contrário, ele fica embrulhado em muitas tags


5
Observe que, de acordo com as especificações HTML ( w3.org/TR/html5/forms.html#the-select-element ), a <select>deve conter apenas <option>ou <optgroup>ou elementos de suporte a script. Portanto, você deve evitar o uso de <span>wrappers inválidos .
— Lucas

9

A função toggleOption não é perfeita e introduziu bugs desagradáveis ​​em meu aplicativo. jQuery vai se confundir com .val () e .arraySerialize () Tente selecionar as opções 4 e 5 para ver o que quero dizer:

<select id="t">
<option value="v1">options 1</option>
<option value="v2">options 2</option>
<option value="v3" id="o3">options 3</option>
<option value="v4">options 4</option>
<option value="v5">options 5</option>
</select>
<script>
jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

$("#o3").toggleOption(false); 
$("#t").change(function(e) {
    if($(this).val() != this.value) {
    console.log("Error values not equal", this.value, $(this).val());
    }
});
</script>

8

Selecionar entradas são complicadas dessa forma. Que tal desativá-lo, isso funcionará em todos os navegadores:

$('select').children(':nth-child(even)').prop('disabled', true);

Isso desativará todos os outros <option>elementos, mas você pode selecionar qualquer um que desejar.

Aqui está uma demonstração: http://jsfiddle.net/jYWrH/

Nota: Se você deseja remover a propriedade disabled de um elemento, você pode usar .removeProp('disabled').

Atualizar

Você pode salvar os <option>elementos que deseja ocultar no elemento de seleção oculto:

$('#visible').on('change', function () {
    $(this).children().eq(this.selectedIndex).appendTo('#hidden');
});

Você pode então adicionar os <option>elementos de volta ao elemento de seleção original:

$('#hidden').children().appendTo('#visible');

Nestes dois exemplos, espera-se que o elemento select visível tenha o id de visiblee o elemento select oculto tenha o id hidden.

Aqui está uma demonstração: http://jsfiddle.net/jYWrH/1/

Observe que .on()é novo no jQuery 1.7 e o uso para esta resposta é o mesmo que .bind(): http://api.jquery.com/on


7

Resposta simples: você não pode. Os elementos do formulário têm recursos de estilo muito limitados.

A melhor alternativa seria definir disabled=truea opção (e talvez uma cor cinza, já que apenas o IE faz isso automaticamente), e isso tornará a opção impossível de clicar.

Como alternativa, se você puder, remova completamente o optionelemento.


6
// Simplest way

var originalContent = $('select').html();

$('select').change(function() {
    $('select').html(originalContent); //Restore Original Content
    $('select option[myfilter=1]').remove(); // Filter my options
});

4

Como já está usando JS, você pode criar um elemento SELECT oculto na página e, para cada item que está tentando ocultar nessa lista, mova-o para a lista oculta. Dessa forma, eles podem ser facilmente restaurados.

Não sei como fazer isso em CSS puro ... Eu teria pensado que o truque display: none teria funcionado.


2

!!! AVISO !!!

Substitua o segundo "IF" por "WHILE" ou não funciona!

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        while( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

2

Você deve removê-los do <select>usando JavaScript. Essa é a única maneira garantida de fazê-los ir embora.


1
Usando jQuery, isso pode ser feito com remove:$('options').remove();
— Luke

2

este parece funcionar para mim no cromo

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');

1
Adicione o formato do código ao seu código, recuando com 4 espaços ou envolvendo o código com `.
— Banana

1
este código é ótimo! ele funciona no Chrome, Firefox e IE 11 mais recentes, isso é bom o suficiente para mim :)
— Sijav

1
antes do meu último comentário, essa coisa funciona no IE 7 também! então ff 3.5, isso é o que eu criei no último, de alguma forma no IE e no cromo preserva o valor que foi selecionado antes que as opções sejam ocultadas e se outro valor não for definido após trazer de volta o navegador de opções irá definir a opção selecionado como antes!
— Sijav

0

Atrasado para o jogo, mas a maioria parece bastante complicada.

Veja como eu fiz:

var originalSelect = $('#select-2').html();

// filter select-2 on select-1 change
$('#select-1').change(function (e) {

    var selected = $(this).val();

    // reset select ready for filtering
    $('#select-2').html(originalCourseSelect);

    if (selected) {
        // filter
        $('#select-2 option').not('.t' + selected).remove();
    }

});

marcação de select-1:

<select id='select-1'>
<option value=''>Please select</option>
<option value='1'>One</option>
<option value='2'>Two</option>
</select>

marcação de select-2:

<select id='select-2'>
<option class='t1'>One</option>
<option class='t2'>Two</option>
<option>Always visible</option>
</select>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.