tags:

views:

528

answers:

4

Hi,

I have this simple html markup generated from classic asp:

<table>
  <tr class="trClass">
    <td>Hello </td>
  </tr>
  <tr class ="trClass">
    <td>World!</td> 
  </tr>
</table>

If i set the tr belonging to Hello to hide() using Jquery it hides. Good!

But, when i use this $('.trClass:visible').each(function() { alert('visible') }); it shows the output 'visible' twice.

Why is this?

My problem here is that im filtering a table on a column with a selection box. But after filtering i need to perform some calculations on those rows that are visible in the table, but i get all rows right now.

Any ideas?

/Daniel

+12  A: 

The :visible selector does not test the display style property, you want to use :hidden instead, the 1.3.2 release notes say:

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

These will correctly select your visible rows:

$('.trClass:not(:hidden)').each(function() { 
    alert('visible'); 
});

or:

$('.trClass').each(function() { 
    if(!$(this).is(':hidden')) {
        alert('visible'); 
    }
});

or:

$('.trClass').filter('not:(:hidden)').each(function() { 
    alert('visible');
});

hide sets the style to display="none". The release notes for jQuery 1.3.2 also say:

In jQuery 1.3.2 an element is visible if its browser-reported offsetWidth or offsetHeight is greater than 0.

so I guess in this case the :visible selector is erroneously not matching anything because the rows are not occupying any space according to the calculations performed, despite the fact that their CSS display property is not set to none. Conversely, :hidden correctly matches elements with style="display:none" so testing for non :hidden elements works just fine.

karim79
Neither `:hidden` nor `:visible` check the display property. Check the source yourself: http://dev.jquery.com/browser/tags/1.3.2/src/selector.js#L957
Crescent Fresh
It's a legitimate bug according to Resig himself: http://www.nabble.com/Re:-Bug-with-:hidden-selector-and-tbody-in-Internet--Explorer-p24631644s27240.html
Crescent Fresh
@crescentfresh - thanks for that. I've updated my answer.
karim79
Nice edit (removed downvote), although you still *imply* `:hidden` checks the `display` property.
Crescent Fresh
@Crescent - Agreed - It clearly doesn't: http://jsfiddle.net/e38GG/ (in IE8).
Peter Ajtai
+2  A: 

Not sure if this matters, but doesn't hide() set display: none; and not visible: hidden? Meaning that a hidden row is still visible, it just isn't displayed...

Svish
A: 

most likely your trClass collides with the display: none that .hide() sets. when a tag has both class attribute and style attribute only on will be applied. you should inpsect closely your trClass and take out display: stuff from it.

xxxxxxx
+4  A: 

You've found a legitimate bug. It's broken in 1.3.2 but now fixed in trunk.

According to Resig:

we already look for the case of 'tr' which has the same problem, in IE

Thought you'd like to know...

Crescent Fresh
and what caused the bug ?
xxxxxxx
@spx2: regression in 1.3.2. Prior versions checked the `display` property. 1.3.2 used a trick to check the [lack of] dimensions of the element. See @karim79's first quote.
Crescent Fresh
@spx2 - As usual, it was programmers.
aehiilrs
upvoted for pointing out this interesting bit of info.
karim79