使用jQuery隐藏下拉列表中的选项

107

我有一个包含键/值对选项的对象,我想将其从选择列表中隐藏或删除。

以下两个选项选择器都不起作用。我错过了什么?

$.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();
}); 

12
您确定被接受的答案在所有浏览器上都有效吗? ;) 我不希望其他人通过谷歌找到这个问答并对其产生错误的印象! - redsquare
@redsquare - 这正是我发布另一个关于在选择中隐藏选项元素不跨浏览器的问题链接的原因 :) - Russ Cam
我发现在Chrome 57.0中,如果使用hide()方法隐藏元素后,如果该元素被隐藏了,则还必须取消选择该元素。 - omarjebari
25个回答

144

说句实话,在jQuery 1.3中,第二种形式(带有@)不存在。第一种方式不起作用,因为显然你期望变量插入,尝试这个:

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

请注意,如果title包含jQuery选择器元字符,则可能会以各种可怕的方式破坏。


56
隐藏选项不是跨浏览器兼容的。 - mpen
1
使用单引号可以解决大多数 jQuery 元字符问题。 - peterjwest
12
这是一个在不同浏览器上都可用的答案,其中包含一个示例,您可以在此处查看:http://jsbin.com/anoci。 - Tr1stan
这个概念帮助我找到了另一个解决方案。谢谢。 - Ajay Kumar
当隐藏 <options /> 时要小心,因为这样经常不会更新所选值。在隐藏后,您需要选择一个新选项。如果您正在 optgroup 中工作,则遍历 DOM 变得棘手。 - png

81

跨浏览器中不能这样做。如果我没记错,IE会有问题。 最简单的方法是在删除项目之前保留


2
获取选项不会成为问题,因为它是依赖下拉菜单的一部分,每次更改都会使用Ajax调用服务器来更新选项。但是在IE中,hide()方法是否无效呢? - hitfactory
确实,IE不会隐藏它们。不确定IE8,但肯定有一种IE版本无法正常工作。 - redsquare
过去的粘贴链接示例在Chrome中也没有隐藏选项。 - slolife
5
这是一个可以跨浏览器运行的答案,这里有一个示例(http://jsbin.com/anoci)- 我在IE6-9、Chrome和Firefox中进行了测试。 - Tr1stan
请看下面我的答案,在IE、FF、Chrome和Safari中都可以工作。这是最灵活的选项(允许从显示文本中获取不同的值)。 - Sablefoste

58

我找到了一种更好的方法,而且非常简单:

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

要再次显示选项,只需找到该选项(不是 span 元素),并使用 $("option_you_want_to_show").unwrap() 命令。

已在 Chrome 和 Firefox 上测试通过。


4
你绝对是个天才!只需一行代码就能实现跨浏览器的魔法。 - manudea
很酷,相当好地处理了跨浏览器问题。 - Subrat Pattnaik
1
我点赞了这个,但如果没有正确实现,它会出错:例如,您不能使用 $(“select”).val(“0”).trigger(“change”)。更简单的解决方案是这个 - clod986
3
使用wrap/unwrap会失去太多控制力。很容易意外地取消尚未包装的元素,因此使它们失去其父元素。 此外,这可能会搞乱CSS选择器。 使用show/hide更好,但您仍然需要记得取消选择任何已选择的元素,方法是: $('selector-for-dropdown').val(''); - omarjebari
1
我喜欢包装/解包的解决方案。只需要确保我们不会对已经包装的内容进行双重包装。未包装的内容也是类似的想法。 - anon
显示剩余5条评论

48

这是我的改良版本,由于使用了本地DOM方法,所以可能会更快。

$.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();
      }
    });
});

15

可以跨浏览器完成,只需要一些自定义编程。请查看我的fiddle:http://jsfiddle.net/sablefoste/YVMzt/6/。它已在Chrome、Firefox、Internet Explorer和Safari中测试通过。

简而言之,我有一个隐藏字段#optionstore,按顺序存储该数组(因为JavaScript中不能有关联数组)。当您更改类别时,它会解析现有选项(仅第一次通过),将其写入#optionstore,擦除所有内容,并仅放回与所选类别相关的选项。

注意:我创建此功能是为了允许用户从文本中显示不同的选项值,因此它非常灵活。

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>

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;
    }
}

请问能否解释一下resultgood变量的用途?我们已经将其删除,因为当用户有一个过滤列表并且输入一个意味着没有要显示的项目的字符时,实际上不会显示空列表 - 代码继续列出与搜索词匹配的项目而没有额外的字符。我们的用例与示例略有不同 - 我们使用一个输入字段来接受搜索词的输入。 - B5A7
resultgood 只是一个检查是否添加了任何 optionlisting 的方法。如果有,就会返回 <option> 列表。如果没有,则不返回任何内容,这正是您希望的,如果您意外地包含了一个实际上不存在的类(在此示例中,例如 sub-Food6)。要在下拉列表中返回空白,请将函数开头的声明行更改为 var optionlisting="<option value=''></option>"; - Sablefoste
顺便说一下,如果我今天要写这个,我可能不会使用类作为信息载体,而是使用data属性;这更符合语义。 - Sablefoste
是的,我们做了同样的事情。 - B5A7

14

这在Firefox 3.0中有效,但在MSIE 8和Opera 9.62中无效:

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

但是不必隐藏一个选项,可以直接禁用它:

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

上述两行代码中的第一行是针对Firefox的,它将焦点传递给第二个选项(假设其value="2")。如果我们省略它,该选项将被禁用,但在我们展开下拉菜单之前,仍会显示"enabled"选项。因此,我们将焦点传递给另一个选项以避免这种情况。


5
您最好的选择是在您想要禁用的选项上设置disabled=true,然后在CSS中设置。
option:disabled {
    display: none;
}

这样即使浏览器不支持隐藏禁用项,它仍然无法被选中。但是在支持它的浏览器上,它们将被隐藏。


5

请看这个问题和答案 -

禁用选择选项...

查看你的代码,你可能需要引用属性值。

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

来自jQuery属性选择器

引号是可选的,但在值包含“]”等字符时应使用引号以避免冲突。

编辑:

刚刚意识到您从函数参数中获取标题,在这种情况下,语法应为

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

5

经过测试,包括chaos在内的其他人发布的隐藏元素的解决方案,现在无法在最新版的Firefox(66.0.4),Chrome(74.0.3729.169)和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();

对于IE浏览器,此方法不起作用,不过您可以禁用该选项。
$("#edit-field-service-sub-cat-value option[value=" + title + "]").attr("disabled", "disabled");
$("#edit-field-service-sub-cat-value option[value=" + title + "]").removeAttr("disabled");

然后强制选择一个不同的值。

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

请注意,对于禁用的选项,下拉列表的值现在将为null,而不是所选选项的值(如果该选项已禁用)。


4

参考redsquare的建议,我最终做了这个:

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

接着要反转它:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接