使用jQuery选择没有可见子元素的元素

8
这是我的目标:如果一个<optgrooup>元素的所有子元素都不可见,则对其执行某些操作。
下面的代码会在<optgrooup>元素中任意一个子元素不可见时将其轮廓线变成红色。但是我只想在所有子元素都不可见时这样做。如果该元素有任何可见的子元素,则不要突出显示它。
如何调整jQuery选择器来实现这一点?
提前感谢您。
<select multiple="multiple" name="availableInstanceId" id="availableInstanceId">
<optgroup label="Option Group 1">
   <option >visible item 1</option>
   <option >visible item 2</option>
</optgroup>
<optgroup label="Option Group 2 - Should be highlighted">
   <option style="display:none;">invisible A</option>
   <option style="display: none">invisible B</option>
</optgroup>

<optgroup label="Option Group 3 - Should not be highlighted">
  <option >visible C</option>
  <option style="display: none">invisible D</option>
</optgroup></select>

<script type="text/javascript">
var filterOptions = function(e) {
  // Goal: highlight the <optgroup>'s that have *only* invisible children
  $( '#availableInstanceId > * > *:hidden').parent().css("border","3px solid red");
} 
$(document).ready(function() {
  filterOptions();
});
</script>

这里是图片截图:http://img144.imageshack.us/img144/556/selectexample.gif


比较不可见和总子项数组的长度如何? - Tom Ritter
6个回答

13
假设您想排除没有子元素的元素:
 $(":has(*):not(:has(:visible))")

实际工作示例。

更新:这比我的原始答案性能要好得多。

$(":hidden").parent().not( $(":visible").parent() )

实际上,有一种更快的方法可以使用遍历而不是选择:https://dev59.com/hUfRa4cB1Zd3GeqP9oO3#841568 - Jed Schmidt
这个工作示例在我的FF中运行良好,但在IE8(在XP上)上没有 - jQuery和IE8是否存在已知问题? - Glen
Jed的两个答案在IE8中都不起作用,这并不是因为jQuery出了问题,而是因为IE8无法隐藏选项! - brianpeiris
不错,Brian。如果你使用这个,它能工作吗?$("option") .filter( function return(){ this.style.display == "none" }) .parent().not( $(":visible").parent() ) - Jed Schmidt
它不太起作用。你必须再往前走一步。我添加了一个带有正确代码的社区答案。 - brianpeiris

2
这比我的原始回答性能更好:
$(":hidden").parent().not( $(":visible").parent() )

1

// 回答更改所需的 CSS 问题

    if($.browser.msie || $.browser.safari){

        $('optgroup:not(:has(:hidden))').css("border","3px solid red");

    } else {

        $('optgroup:not(:has(:visible))').css("border","3px solid red");

    }

// 删除空的 optgroups 示例

    if($.browser.msie || $.browser.safari){

        $('optgroup:not(:has(:hidden))').remove();

    } else {

        $('optgroup:not(:has(:visible))').remove();

    }

1

用两行代码怎么样?一行用于打开每个元素,另一行用于关闭所有具有可见子元素的元素。

$('#availableInstanceId > *').css("border","3px solid red");
$('#availableInstanceId > * > *:visible').parent().css("border","none");

1

感谢 Jed Schmidt。以下代码适用于IE8。

请注意,尽管使用了display:none样式,但IE8实际上并没有隐藏<option>元素。此外,IE8似乎不接受<optgroup>元素的border样式。

工作示例:http://jsbin.com/aquya(可通过http://jsbin.com/aquya/edit进行编辑)

$(document).ready(function() {
  // Prevent CSS inherits
  $("option").css('backgroundColor', 'white')

  $("option")
    .filter(function(){
      return this.style.display == 'none';
    })
    .parent()
    .not($('option').filter(function(){
      return this.style.display != 'none';
    }).parent())
    .css('backgroundColor', 'blue')
    .css('border', '1px solid red'); //this doesn't work in IE8
});

谢谢,这很棒,至少能够突出显示。不幸的是,我真正想做的是隐藏optgroup,而不是突出显示。我应该在最初的问题中说过这一点 - 我没有想到这会有什么区别,因为我的主要关注点是选择器 - 但事实证明这确实有所不同,因为正如你之前提到的那样,IE 存在隐藏选择选项(以及 optgroup - 请参见http://dev.jquery.com/ticket/1100)的 bug。所以看来我在 IE 上没戏了。 - Glen
如果您不介意额外的工作和复杂性,您可能可以通过暂时删除要隐藏的元素来模拟它(我猜测,IE 也许也不喜欢这样做)。 - brianpeiris

0
你需要比较一个包含所有可见和隐藏元素的数组。
以下是一些伪代码。
if ($("#element:hidden").length == $("#element:visible").length) {
  // Do  stuff
} ...

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