views:

5054

answers:

4

I have a snippet of code that I'm working with to filter rows in a table. It works perfectly in every browser other than Firefox v3.0.x (works fine with 3.1 beta 2). When I run the snippet in Firefox 3.0.x, it says that children is undefined. I am using jQuery v1.2.6 also.

Code Snippet:

var bodyRows = $("#resultsTable tbody tr");
bodyRows.each(function(n){
    if(!filterPattern.test($.trim(this.children[2].innerHTML))){ //errors here
      this.style.display = 'none';
    }
    else {
      this.style.display = '';
    }
});

The code selects all table rows and then loops through them, testing the innerHTML text of the 3rd column. If the RegEx test fails, the row is hidden, else it is displayed.

Has anyone seen this issue and / or know how to get it working?

Thanks

EDIT: Here is the HTML markup for the table. For brevity, I'm only giving 2 record in it though more are populated.

<table id="resultsTable" cellpadding="0" cellspacing="0">
    <thead>
     <tr>
      <th>First</th>
             <th>Last</th>
      <th>City</th>
      <th>State</th>
      <th>Zip</th>
      <th>Email</th>
      <th>&nbsp;</th>
     </tr>
    </thead> 
    <tbody id="resultsBody">
     <tr>
      <th>James</th>
             <th>Eggers</th>
      <th>SomeCity</th>
      <th>IA</th>
      <th>55555</th>
      <th>[email protected]</th>
      <th>&nbsp;</th>
     </tr>
     <tr>
      <th>John</th>
             <th>Doe</th>
      <th>SomeCity</th>
      <th>KY</th>
      <th>88888</th>
      <th>[email protected]</th>
      <th>&nbsp;</th>
     </tr>
    </tbody>  
</table>
A: 

you might want to check the number of elements in children before trying to access the 3rd one.

John Boker
This wouldn't help with the error saying children is undefined. Good idea anyway, but doesn't solve the problem.
Ray Booysen
There are plenty 6 columns in the table so children[2] should be legit. I am also expecting the same tests to be successful in all browsers but only FF3.0 is failing.
JamesEggers
A: 

Do you explicitly add a

<tbody>
   ...
</tbody>

tag to your table? If not, I would say to drop the 'tbody' portion from: $("#resultsTable tbody tr");

to just $("#resultsTable tr");

I'm curious if this version of Firefox isn't implicitly creating it for you.

scunliffe
I have explicitly added the tbody tab. I'm going update the main question with the html markup now.
JamesEggers
+4  A: 

Why not use jQuery to traverse the DOM elements instead.

var bodyRows = $("#resultsTable tbody tr");
bodyRows.each(function(){
    var thirdCell = $(this).find('td').eq(2);
    if(!filterPattern.test($.trim(thirdCell.html()))){
        this.style.display = 'none';
    } else {
        this.style.display = '';
    }
});

You could also use '.text()' if you just want the text without any possible markup to be returned.

The property children is an IE only DOM property which no other browser has (to my knowledge). Firefox uses the standard property childNodes for accessing children. The problem with childNodes is that it considers whitespace and text to be a node (or at least Firebug says so) which makes it (in my opinion) very difficult to deal with. If you have a JavaScript API, you should take advantage of it so that you don't have to deal with the differences between browsers' DOM traversal techniques.

Dan Herbert
I'm using jQuery 1.2.6. After changing children to childNodes like you mentioned, it began working w/o issue. Thanks!
JamesEggers
The reason I suggested using jQuery was because different browsers require different code to access elements. If you use jQuery instead of 'childNodes' or 'children', you don't have to worry about which property to use.
Dan Herbert
+1  A: 
if(!filterPattern.test($.trim(this.children[2].innerHTML)))

When an 'each' callback is invoked by jQuery, 'this' is a direct browser DOM node, not a jQuery object.

Confusion occurs because jQuery offers a 'children' method on its DOM wrappers, and IE offers a non-standard 'children' collection on its native DOM nodes, but the two interfaces are almost totally incompatible.

So use $(this).children()[2] or similar for the jQuery version, or this.getElementsByTagName('td')[2] for the standard DOM version.

(Assuming you meant to make the table data elements 'td' rather than 'th', which you probably did. Also you probably want to grab the raw text of the cell rather than the innerHTML version which may have characters escaped in unexpected ways.)

bobince