Ocultar opções em uma lista de seleção usando jQuery

98

Eu tenho um objeto com pares de chave / valor de opções que quero ocultar / remover de uma lista de seleção. Nenhum dos seguintes seletores de opção funcionam. o que estou perdendo?

$.each(results['hide'], function(name, title) {                     
  $("#edit-field-service-sub-cat-value option[value=title]").hide();
  $("#edit-field-service-sub-cat-value option[@value=title]").hide();
}); 
hitfactory
fonte
12
tem certeza de que a resposta aceita funciona com o navegador x;) Eu odiaria que qualquer outra pessoa encontrasse essas perguntas e respostas no google e ficasse com a impressão errada!
redsquare
@redsquare - é exatamente por isso que postei um link para outra pergunta sobre como ocultar elementos de opção em um navegador selecionado que não seja cruzado :)
Russ Cam
Descobri que você também precisa desmarcar o elemento selecionado se ele estiver oculto depois que hide () for chamado no Chrome 57.0
omarjebari

Respostas:

127

Pelo que vale a pena, a segunda forma (com o @) não existe no jQuery 1.3. O primeiro não está funcionando porque aparentemente você está esperando uma interpolação de variável. Experimente isto:

$("#edit-field-service-sub-cat-value option[value=" + title + "]").hide();

Observe que isso provavelmente será interrompido de várias maneiras horríveis se titlecontiver metacaracteres do seletor jQuery.

caos
fonte
50
As opções de ocultação não são compatíveis com navegadores diferentes.
mpen
1
Colocar aspas simples resolveria a maioria dos problemas de metacaracteres do jquery
peterjwest
Esse conceito me ajudou para outra solução. Obrigado
Ajay Kumar
Cansado ao ocultar <options /> com freqüência, isso não atualizará o valor selecionado. Você precisará selecionar uma nova opção após ela ser ocultada. Se você estiver trabalhando em optgroup, será complicado atravessar o DOM.
Solvitieg
80

Você não pode fazer este navegador x. Se bem me lembro, ou seja, tem problemas. A coisa mais fácil a fazer é manter uma cópia clonada do select antes de remover itens; isso permite que você remova facilmente e depois acrescente os itens que faltam de volta.

quadrado vermelho
fonte
2
obter opções de volta não será um problema, pois é parte de uma lista suspensa dependente com chamadas ajax para o servidor para atualizar as opções cada vez que a alteração. Mas é um caso de hide () não funcionar no IE?
hitfactory de
Na verdade, isto é, não os esconderá. Não tenho certeza sobre o ie8, mas certamente um dos sabores do ie não funciona
redsquare
O exemplo do link pastebin também não esconde a opção no Chrome
slolife
5
Aqui está uma resposta que funciona em vários navegadores - com um exemplo aqui - eu testei no IE6-9, Chrome e FF
Tr1stan
Veja minha resposta abaixo, trabalhando no IE, FF, Chrome e Safari. É a opção mais flexível (permitindo valores diferentes do texto exibido).
Sablefoste de
53

Encontrei uma maneira melhor e é muito simples:

$("option_you_want_to_hide").wrap('<span/>')

Para mostrar novamente, apenas encontre essa opção (não span) e $("option_you_want_to_show").unwrap().

Ele foi testado no Chrome e Firefox.

William Herry
fonte
3
Você é um gênio absoluto! Apenas uma mágica de navegador cruzado de linha.
manudea de
Legal. Lida muito bem com o problema do navegador cruzado.
Subrat Pattnaik
Eu votei positivamente neste, mas ele bagunça se não for implementado corretamente: por exemplo, você não pode usar $("select").val("0").trigger("change"). A solução mais fácil é esta
clod986
2
Você perde muito controle usando embrulhar / desembrulhar. é fácil desembrulhar acidentalmente elementos que ainda não foram agrupados, removendo-os de seu elemento pai. Também pode bagunçar os seletores de css. Usar mostrar / ocultar é melhor, embora você ainda precise se lembrar de desmarcar qualquer elemento selecionado também com: $ ('selector-for-dropdown'). Val ('');
omarjebari
1
Gostei da solução wrap / uwnrap. Só precisamos ter certeza de não embrulhar duplamente os que já estão embrulhados. Idéia semelhante com os desembrulhados.
anon
47

Aqui está meu giro, provavelmente um pouco mais rápido devido aos métodos DOM nativos

$.each(results['hide'], function(name, title) {                     
    $(document.getElementById('edit-field-service-sub-cat-value').options).each(function(index, option) {
      if( option.value == title ) {
        option.hidden = true; // not fully compatible. option.style.display = 'none'; would be an alternative or $(option).hide();
      }
    });
});
Caprica Six
fonte
14

Isso funciona no Firefox 3.0, mas não no MSIE 8, nem no Opera 9.62:

jQuery('#destinations').children('option[value="1"]').hide();
jQuery('#destinations').children('option[value="1"]').css('display','none');

Mas, em vez de ocultar uma opção, pode-se simplesmente desativá-la:

jQuery('#destinations').val('2'); 
jQuery('#destinations').children('option[value="1"]').attr('disabled','disabled');

A primeira das duas linhas acima é para o Firefox e passe o foco para a segunda opção (assumindo que tenha o valor = "2"). Se a omitirmos, a opção será desabilitada, mas ainda exibirá a opção "habilitada" antes de ser descartada. Portanto, passamos o foco para outra opção para evitar isso.

entusiasmado123
fonte
12

PODE ser feito em qualquer navegador; só precisa de alguma programação personalizada. Por favor, veja meu violino em http://jsfiddle.net/sablefoste/YVMzt/6/ . Ele foi testado para funcionar no Chrome, Firefox, Internet Explorer e Safari.

Resumindo, eu tenho um campo oculto,, #optionstoreque armazena o array sequencialmente (já que você não pode ter Arrays Associativos em JavaScript). Então, quando você altera a categoria, ele analisa as opções existentes (apenas na primeira vez), grava-as #optionstore, apaga tudo e coloca de volta apenas aquelas associadas à categoria.

NOTA: Eu criei isso para permitir diferentes valores de opção do texto exibido para o usuário, por isso é altamente flexível.

O HTML:

<p id="choosetype">
    <div>
        Food Category:
    </div>
    <select name="category" id="category" title="OPTIONAL - Choose a Category to Limit Food Types" size="1">
        <option value="">All Food</option>
        <option value="Food1">Fruit</option>
        <option value="Food2">Veggies</option>
        <option value="Food3">Meat</option>
        <option value="Food4">Dairy</option>
        <option value="Food5">Bread</option>
    </select>
    <div>
        Food Selection
    </div>
    <select name="foodType" id="foodType" size="1">
        <option value="Fruit1" class="sub-Food1">Apples</option>
        <option value="Fruit2" class="sub-Food1">Pears</option>
        <option value="Fruit3" class="sub-Food1">Bananas</option>
        <option value="Fruit4" class="sub-Food1">Oranges</option>
        <option value="Veg1" class="sub-Food2">Peas</option>
        <option value="Veg2" class="sub-Food2">Carrots</option>
        <option value="Veg3" class="sub-Food2">Broccoli</option>
        <option value="Veg4" class="sub-Food2">Lettuce</option>
        <option value="Meat1" class="sub-Food3">Steak</option>
        <option value="Meat2" class="sub-Food3">Chicken</option>
        <option value="Meat3" class="sub-Food3">Salmon</option>
        <option value="Meat4" class="sub-Food3">Shrimp</option>
        <option value="Meat5" class="sub-Food3">Tuna</option>
        <option value="Meat6" class="sub-Food3">Pork</option>
        <option value="Dairy1" class="sub-Food4">Milk</option>
        <option value="Dairy2" class="sub-Food4">Cheese</option>
        <option value="Dairy3" class="sub-Food4">Ice Cream</option>
        <option value="Dairy4" class="sub-Food4">Yogurt</option>
        <option value="Bread1" class="sub-Food5">White Bread</option>
        <option value="Bread2" class="sub-Food5">Panini</option>
    </select>
    <span id="optionstore" style="display:none;"></span>
</p>

O JavaScript / jQuery:

$(document).ready(function() {
    $('#category').on("change", function() {
        var cattype = $(this).val();
        optionswitch(cattype);
    });
});

function optionswitch(myfilter) {
    //Populate the optionstore if the first time through
    if ($('#optionstore').text() == "") {
        $('option[class^="sub-"]').each(function() {
            var optvalue = $(this).val();
            var optclass = $(this).prop('class');
            var opttext = $(this).text();
            optionlist = $('#optionstore').text() + "@%" + optvalue + "@%" + optclass + "@%" + opttext;
            $('#optionstore').text(optionlist);
        });
    }

    //Delete everything
    $('option[class^="sub-"]').remove();

    // Put the filtered stuff back
    populateoption = rewriteoption(myfilter);
    $('#foodType').html(populateoption);
}

function rewriteoption(myfilter) {
    //Rewrite only the filtered stuff back into the option
    var options = $('#optionstore').text().split('@%');
    var resultgood = false;
    var myfilterclass = "sub-" + myfilter;
    var optionlisting = "";

    myfilterclass = (myfilter != "")?myfilterclass:"all";

    //First variable is always the value, second is always the class, third is always the text
    for (var i = 3; i < options.length; i = i + 3) {
        if (options[i - 1] == myfilterclass || myfilterclass == "all") {
            optionlisting = optionlisting + '<option value="' + options[i - 2] + '" class="' + options[i - 1] + '">' + options[i] + '</option>';
            resultgood = true;
        }
    }
    if (resultgood) {
        return optionlisting;
    }
}
Sablefoste
fonte
Você poderia explicar o uso da variável resultgood? Removemos seu uso porque quando o usuário tem uma lista filtrada e insere um caractere que significa que não há itens a serem exibidos, uma lista vazia não é realmente exibida - o código continua a listar os itens que correspondem ao termo de pesquisa sem o personagem extra. Nosso caso de uso difere um pouco do exemplo - usamos um campo de entrada para aceitar a entrada de um termo de pesquisa.
B5A7
O resultgoodé simplesmente uma verificação para ver se algum optionlistingfoi adicionado. se fosse, a lista de <option>s é retornada. Caso contrário, nada será retornado, que é o que você desejaria se incluísse acidentalmente uma classe que não estava realmente lá (neste exemplo, digamos, sub-Food6). Para retornar um espaço em branco em um menu suspenso, altere a linha de declaração no início da função para var optionlisting="<option value=''></option>";.
Sablefoste
A propósito, se eu fosse escrever isso hoje, provavelmente não usaria classe como o portador da informação, mas sim o dataatributo; é semanticamente mais correto.
Sablefoste
Sim. Nós fizemos o mesmo.
B5A7
5

Sua melhor aposta é definir disabled = true nos itens de opção que deseja desativar e, em seguida, no conjunto CSS

option:disabled {
    display: none;
}

Dessa forma, mesmo se o navegador não suporta escondendo o item desativado, ele ainda não pode ser selecionado .. mas em navegadores que não suportam-lo, eles serão ocultados.

eoleary
fonte
4

Dê uma olhada nesta pergunta e as respostas -

Desativar selecionar opções ...

Olhando para o seu código, pode ser necessário citar o valor do atributo

$("#edit-field-service-sub-cat-value option[value='title']").hide();

de seletores de atributo jQuery

As aspas são opcionais na maioria dos casos, mas devem ser usadas para evitar conflitos quando o valor contém caracteres como "]"

EDITAR:

Acabei de perceber que você está obtendo o título do parâmetro de função, caso em que a sintaxe deve ser

$("#edit-field-service-sub-cat-value option[value='" + title + "']").hide();
Russ Cam
fonte
4

Em referência à sugestão do redsquare, acabei fazendo o seguinte:

var selectItems = $("#edit-field-service-sub-cat-value option[value=" + title + "]").detach();

e então para reverter isso:

$("#edit-field-service-sub-cat-value").append(selectItems);
MadTurki
fonte
3

O problema é que o Internet Explorer não parece suportar os métodos de ocultar e mostrar para selecionar opções. Eu queria ocultar todas as opções do meu ddlReasonCode select que não tinha o tipo selecionado atualmente como o valor do atributo "attType".

Enquanto o adorável Chrome estava bastante satisfeito com:

//Hiding all options
            $("#ddlReasonCode").children().hide();
            //Showing only the relevant options
            $("#ddlReasonCode").children("option[atttype=\"" + CurrentType + "\"]").show();

Isso é o que o IE requer (crianças, não tente fazer isso no CHROME :-)):

//Hiding all options
            $("#ddlReasonCode option").each(function (index, val) {
                if ($(this).is('option') && (!$(this).parent().is('span')) && ($(this).atttype != CurrentType))
                    $(this).wrap('<span>').hide();
            });
            //Showing only the relevant options
            $("#ddlReasonCode option").each(function (index, val) {
                if (this.nodeName.toUpperCase() === 'OPTION') {
                    var span = $(this).parent();
                    var opt = this;
                    if ($(this).parent().is('span') && ((this).atttype == CurrentType)) {
                        $(opt).show();
                        $(span).replaceWith(opt);
                    }
                }
            });

Eu encontrei essa ideia de embrulho em http://ajax911.com/hide-options-selecbox-jquery/

Oranit Dar
fonte
3

Depois de testadas, as soluções postadas acima por vários, incluindo o caos, para ocultar elementos agora funcionam nas versões mais recentes do Firefox (66.0.4), Chrome (74.0.3729.169) e Edge (42.17134.1.0)

$("#edit-field-service-sub-cat-value option[value=" + title + "]").hide();
$("#edit-field-service-sub-cat-value option[value=" + title + "]").show();

Para o IE, isso não funciona, mas você pode desativar a opção

$("#edit-field-service-sub-cat-value option[value=" + title + "]").attr("disabled", "disabled");
$("#edit-field-service-sub-cat-value option[value=" + title + "]").removeAttr("disabled");

e então forçar a seleção de um valor diferente.

$("#edit-field-service-sub-cat-value").val("0");

Observe que para uma opção desabilitada, o valor do menu suspenso agora será nulo, não o valor da opção selecionada se estiver desabilitada.

Steven Poole
fonte
2

Parece que você também precisa atualizar o atributo "selecionado". Caso contrário, a opção atualmente selecionada pode continuar a ser exibida - embora provavelmente desapareça quando você realmente for selecionar uma opção (foi o que fez para mim): Tente fazer isto:

$('#mySelector').children('option').hide();
$('#mySelector').children('option').removeAttr("selected"); //this may be overkill.
$('#mySelector').children('option[value="'+SelVal+'"]').show();  
$('#mySelector').children(':visible').attr('selected','selected'); //assuming that something is still on the list.
djoeberry
fonte
2

Eu estava tentando ocultar opções de uma lista de seleção com base na opção selecionada de outra lista de seleção. Estava funcionando no Firefox3, mas não no Internet Explorer 6. Tenho algumas idéias aqui e tenho uma solução agora, então gostaria de compartilhar:

O código JavaScript

function change_fruit(seldd) {
    var look_for_id=''; var opt_id='';
    $('#obj_id').html("");
    $("#obj_id").append("<option value='0'>-Select Fruit-</option>");
    if(seldd.value=='0') {
        look_for_id='N';
    }
    if(seldd.value=='1'){
        look_for_id='Y';
        opt_id='a';
    }
    if(seldd.value=='2') {
        look_for_id='Y';
        opt_id='b';
    }
    if(seldd.value=='3') {
        look_for_id='Y';
        opt_id='c';
    }

    if(look_for_id=='Y') {
        $("#obj_id_all option[id='"+opt_id+"']").each(function() {
          $("#obj_id").append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
        });
    }
    else {
        $("#obj_id_all option").each(function() {
          $("#obj_id").append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
        });
    }
}

O HTML

<select name="obj_id" id="obj_id">
    <option value="0">-Select Fruit-</option>
    <option value="1" id="a">apple1</option>
    <option value="2" id="a">apple2</option>
    <option value="3" id="a">apple3</option>
    <option value="4" id="b">banana1</option>
    <option value="5" id="b">banana2</option>
    <option value="6" id="b">banana3</option>
    <option value="7" id="c">Clove1</option>
    <option value="8" id="c">Clove2</option>
    <option value="9" id="c">Clove3</option>
</select>

<select name="fruit_type" id="srv_type" onchange="change_fruit(this)">
    <option value="0">All</option>
    <option value="1">Starts with A</option>
    <option value="2">Starts with B</option>
    <option value="3">Starts with C</option>
</select>

<select name="obj_id_all" id="obj_id_all" style="display:none;">
    <option value="1" id="a">apple1</option>
    <option value="2" id="a">apple2</option>
    <option value="3" id="a">apple3</option>
    <option value="4" id="b">banana1</option>
    <option value="5" id="b">banana2</option>
    <option value="6" id="b">banana3</option>
    <option value="7" id="c">Clove1</option>
    <option value="8" id="c">Clove2</option>
    <option value="9" id="c">Clove3</option>
</select>

Foi verificado como funcionando no Firefox 3 e Internet Explorer 6.

Souvik
fonte
5
De acordo com o W3C, o idatributo deve ser único: id = Este atributo atribui um nome a um elemento. Este nome deve ser único em um documento.
Jasper
1

Para evitar a concatenação de strings, você pode usar jQuery.grep

$($.grep($("#edit-field-service-sub-cat-value option"),
         function(n,i){
           return n.value==title;
         })
 ).hide()
Rretzbach
fonte
1

Provavelmente não tão elegante ou reutilizável como um plugin jquery. mas outra abordagem é simplesmente salvar os elementos de opção e trocá-los conforme necessário:

var SelectFilter = function ()
        {
            this.allOptions = $("#someSelect option");

            this.fooBarOptions= $("#someSelect option[value='foo']");
            this.fooBarOptions= this.fooBarOptions.add($("#someSelect option[value='bar']"));


            this.showFooBarOptions = function()
            {
                $("#someSelect option").remove();
                $("#someSelect").append(this.fooBarOptions);
            };
            this.showAllOptions = function()
            {
                $("#someSelect option").remove();
                $("#someSelect").append(this.allOptions);
            };



        };

faça isso para usar o objeto:

var filterObject = new SelectFilter();
filterObject.showFooBarOptions (); 
Squìvel
fonte
1

Implementei uma solução usando uma função que filtra um combobox ( <select>) com base em atributos de dados personalizados. Esta solução suporta:

  • Ter um <option>para mostrar quando o filtro deixaria o select vazio.
  • Respeita os atributos selecionados existentes.
  • <option> elementos sem o atributo de filtro de dados são deixados intocados.

Testado com jQuery 2.1.4 e Firefox, Chrome, Safari e IE 10+.

Este é o exemplo de HTML:

<select id="myCombobox">
  <option data-filter="1" value="AAA">Option 1</option>
  <option data-filter="1" value="BBB">Option 2</option>
  <option data-filter="2" value="CCC">Option 3</option>
  <option data-filter="2" value="DDD">Option 4</option>
  <option data-filter="3" value="EEE">Option 5</option>
  <option data-filter="3" value="FFF">Option 6</option>
  <option data-filter-emptyvalue disabled>No Options</option>
</select>

O código jQuery para a filtragem:

function filterCombobox(selectObject, filterValue, autoSelect) {

  var fullData = selectObject.data("filterdata-values");
  var emptyValue = selectObject.data("filterdata-emptyvalue");

  // Initialize if first time.
  if (!fullData) {
    fullData = selectObject.find("option[data-filter]").detach();
    selectObject.data("filterdata-values", fullData);
    emptyValue = selectObject.find("option[data-filter-emptyvalue]").detach();
    selectObject.data("filterdata-emptyvalue", emptyValue);
    selectObject.addClass("filtered");
  }
  else {
    // Remove elements from DOM
    selectObject.find("option[data-filter]").remove();
    selectObject.find("option[data-filter-emptyvalue]").remove();
  }

  // Get filtered elements.
  var toEnable = fullData.filter("option[data-filter][data-filter='" + filterValue + "']");

  // Attach elements to DOM
  selectObject.append(toEnable);

  // If toEnable is empty, show empty option.
  if (toEnable.length == 0) {
    selectObject.append(emptyValue);
  }

  // Select First Occurrence
  if (autoSelect) {
    var obj = selectObject.find("option[selected]");
    selectObject.val(obj.length == 0 ? toEnable.val() : obj.val());
  }
}

Para usá-lo, basta chamar a função com o valor que deseja manter.

filterCombobox($("#myCombobox"), 2, true);

Então, a seleção resultante será:

<select id="myCombobox">
  <option data-filter="2" value="CCC">Option 3</option>
  <option data-filter="2" value="DDD">Option 4</option>
</select>

Os elementos originais são armazenados pela função data (), portanto, as chamadas subsequentes adicionarão e removerão os elementos corretos.

Alberto Hormazabal
fonte
Esta é uma ótima solução reutilizável, que é a única que encontrei que funciona no Safari. Obrigado!
Echilon de
0

A resposta indica que @é inválido para iterações jQuery mais recentes. Embora isso esteja correto, alguns IEs mais antigos ainda não ocultam elementos de opção. Para quem precisa lidar com a ocultação de elementos de opção nessas versões afetadas, publiquei uma solução alternativa aqui:

http://work.arounds.org/issue/96/option-elements-do-not-hide-in-IE/

Basicamente, basta envolvê-lo com uma extensão e substituí-lo na exibição.

Meder Omuraliev
fonte
0

Qualquer pessoa que encontrar essa questão também pode considerar o uso de Escolhidos , que expande muito as capacidades dos selecionados.

Charles Wood
fonte
0
$("option_you_want_to_hide").addClass('hidden')

Então, em seu css, certifique-se de ter

.hidden{
    display:none;
}
clod986
fonte
0

Eu sei que esta pergunta foi respondida. Mas minha exigência era ligeiramente diferente. Em vez de valor, eu queria filtrar por texto. Portanto, modifiquei a resposta de @William Herry assim.

var array = ['Administration', 'Finance', 'HR', 'IT', 'Marketing', 'Materials', 'Reception', 'Support'];
if (somecondition) {
   $(array).each(function () {
       $("div#deprtmnts option:contains(" + this + ")").unwrap();
   });
}
else{
   $(array).each(function () {
       $("div#deprtmnts option:contains(" + this + ")").wrap('<span/>');
   });
}

Desta forma, você pode usar o valor também substituindo contém como este

 $("div#ovrcateg option[value=" + this + "]").wrap('<span/>');
jkjhse
fonte
0

Para ocultar a opção em uso selecionado :

option_node.hidden = true; # For hide selcet item
option_node.hidden = false; # For show selcet item

Onde option_node é HTMLOptionElement

PS: Eu não uso JQuery, mas suponho que funcione:

$('.my_select option[value="my_cool_value"]').hidden = true
DAVIDhaker
fonte
O IE não suporta ocultar em opções selecionadas
RitchieD
stackoverflow.com/questions/2031740/… PS: IE não é navegador. IE - programa para navegador de download! :)
DAVIDhaker
0

Achei melhor apenas remover o DOM completamente.

$(".form-group #selectId option[value='39']").remove();

Compatível com vários navegadores. Funciona no IE11 também

Vishal
fonte
0
 $('#id').val($('#id option:eq(0)').hide());

opção: eq (0) - oculta a opção no índice '0' na caixa de seleção.

Kiran
fonte
-1

$ ("# ddtypeoftraining option [value = 5]"). css ("display", "none"); $ ('# ddtypeoftraining'). selectpicker ('atualizar');

Hemant yadav
fonte
Adicione uma descrição à sua solução!
Philipp M