views:

1565

answers:

2

How do you select only visible elements using jQuery?

jQuery selectors :visible and :hidden only respects display:none as really hidden? NOT visibility:hidden or visibility:visible.

I understand they are not technically hidden because they still take their space. I just want to know their state so I can check checkboxes that are visible.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>jQuery :visiblity Selector Test</title>

<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>

<script type="text/javascript">
    $(document).ready(function() {
        $("#VisibleCount").text($("input[type=checkbox]:visible").length); //returns 3. I think it should be 2
        $("#HiddenCount").text($("input[type=checkbox]:hidden").length); //returns 1. I think it should be 2
    });
</script>

<style type="text/css">
    #TestArea
    {
        border: solid red 1px;
    }
    #Results
    {
        background-color: Lime;
    }
    .container
    {
        border: solid black 1px;
    }
</style>
</head>
<body>
<div id="TestArea">
    <div class="container">
        visibility: hidden;<div style="visibility: hidden;">
            <input id="Checkbox1" type="checkbox" />
        </div>
    </div>
    <div class="container">
        visibility: visible;<div style="visibility: visible;">
            <input id="Checkbox2" type="checkbox" />
        </div>
    </div>
    <div class="container">
        display: none;<div style="display: none;">
            <input id="Checkbox3" type="checkbox" />
        </div>
    </div>
    <div class="container">
        display: inline;<div style="display: inline;">
            <input id="Checkbox4" type="checkbox" />
        </div>
    </div>
</div>
<div id="Results">
    <div>
        Visible Count: <span id="VisibleCount"></span>
    </div>
    <div>
        Hidden Count: <span id="HiddenCount"></span>
    </div>
</div>
</body>
</html>
+2  A: 

From the jQuery 1.3.2 release notes (:visible/:hidden Overhauled):

  • In jQuery 1.3.1 (and older) an element was visible if its CSS
    "display" was not "none", its CSS
    "visibility" was not "hidden", and
    its type (if it was an input) was not "hidden".
  • In jQuery 1.3.2 an element is visible if its browser-reported *offsetWidth or offsetHeight is* greater than 0.

What does this change mean? It means that if your element's CSS display is "none", or any of its parent/ancestor element's display is "none", or if the element's width is 0 and the element's height is 0 then an element will be reported as hidden.

karim79
+1 for digging up what's happening (even if it doesn't provide a solution to the problem).
Guffa
+5  A: 

You can use the css function to get the style of the element, and the filter function to select them from a collection of elements:

var visible = $('input[type=checkbox]').filter(function() {
   return !($(this).css('visibility') == 'hidden' || $(this).css('display') == 'none');
});
Guffa
+1 for providing a solution (even if you didn't dig up what's happening :)
karim79
Great, thanks guys! I ended up using this with chaining to reduce my result set: $("input[type=checkbox]").filter(function() { return !($(this).css('visibility') == 'hidden' || $(this).css('display') == 'none'); }).each(function() { this.checked = true; });
Peter Samuel