Tutorial :jquery selection of elements with no visible children



Question:

Here's my goal: do something on an element, an <optgrooup>, if all of its children are invisible.

My code below outlines the in red if it has any invisible children. But I want to do so only if all the children are invisible. If the element has any children that are visible, then don't highlight it.

How can I tweak the jQuery selector to do that?

Thanks in advance.

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

Screenshot of image here: http://img144.imageshack.us/img144/556/selectexample.gif


Solution:1

Assuming you want to exclude elements with no child elements:

 $(":has(*):not(:has(:visible))")  

Working example.

UPDATE: This has much better performance than my original answer:

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


Solution:2

This has much better performance than my original answer:

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


Solution:3

How about two lines to do it? One to turn it on for every single element, and one to turn it off again for every one with a visible child?

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


Solution:4

Credit goes to Jed Schmidt. The following code works in IE8.

Note that IE8 does not actually hide the <option> elements despite the display: none style. Also IE8 doesn't seem to accept border styles for <optgroup> elements.

Working sample: http://jsbin.com/aquya (Editable via 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  });  


Solution:5

// answer to question changing css as desired

    if($.browser.msie || $.browser.safari){            $('optgroup:not(:has(:hidden))').css("border","3px solid red");        } else {            $('optgroup:not(:has(:visible))').css("border","3px solid red");        }  

// remove empty optgroups example

    if($.browser.msie || $.browser.safari){            $('optgroup:not(:has(:hidden))').remove();        } else {            $('optgroup:not(:has(:visible))').remove();        }  


Solution:6

You'll need to compare an array of all the :visible vs. :hidden

here is some pseudo code

if ($("#element:hidden").length == $("#element:visible").length) {    // Do  stuff  } ...  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »