views:

514

answers:

3

This seems like it should be fairly easy - but I can't find the right selector for it

According to the docs (http://api.jquery.com/hidden-selector/ and http://api.jquery.com/visible-selector/)...

Elements can be considered hidden for several reasons:

An ancestor element is hidden, so the element is not shown on the page.

What I want to detect is "this element is visible, but is contained in a hidden parent". Ie, if I made the parent visible, this element would also be visible.

A: 

I don't think just one selector would work, but

<script>
function parentHidden(id) {
    return (!$(id).is(':hidden')) && $(id).parent().is(':hidden')));
}        
</script>

should return what you need. If you need to check it's ancestors and not just it's parent, you could just replace the $(id).parent().is(':hidden') part with a function that would recurse up the 'ancestor chain'.

W_P
But that's exactly what I don't want...particularly the point 4. It also says "An element is assumed to be hidden if it or any of its parents consumes no space in the document"
Paul
ah, i see, sorry about that. updating answer.
W_P
But that doesn't get me whether the element is actually visible - it just says whether the parent is visible, which wasn't quite the question
Paul
W_P
A: 

If it is a specific element that you are looking for then you could check it's display property

$('#element').css('display') != 'none';

If it wasn't a specific element then you could find the parent nodes that are hidden using :hidden then use a custom function to look for nodes of the type you want. E.g.

$('parent-selector:hidden').find('node-selector').each(function(){
  if($(this).css('display') != 'none') {
    // do what you wanted
  }
});

If you want a clean selector then i think that you're going to be out of luck as i don't think what you want is part of the CSS spec, so won't be there as a selector in jQuery.

Barney Scott
+4  A: 

If this is something you'll commonly use, make your own selector :) Here's an example:

jQuery.expr[':'].hiddenByParent = function(a) { 
   return jQuery(a).is(':hidden') && jQuery(a).css('display') != 'none'; 
};

You can use it like this, test markup:

<div style="display: none" id="parent">
  <div>
      <div id="child">Test</div>
  </div>
</div>
​

Examples of use:

$("div:hiddenByParent").length;​​​​​​​​​​​​​​​​​​ // "2" (plain div + child match)
$("#child").is(":hiddenByParent"); // true

Alternatively, you can use the .filter() function like this:

$('selector').filter(function() {
  return $(this).is(':hidden') && $(this).css('display') != 'none';
}
Nick Craver
Great answer as always Nick! But if an element has the visibility set to hidden, then you will need to use this as the selector `return $(a).is(':hidden') `
fudgey
@fudgey - Good point, `visible` stuff isn't "hidden" though, it does still occupy the space on the page. I guess it depends if you're looking for totally hidden things or things that take up no room on the page at all. Whatever definition you're after, use that approach for sure.
Nick Craver