Horen
Horen

Reputation: 11382

Select highest level td's in nested table structure with jQuery

I am trying to select the highest level of tds in a nested table structure like this (inside the first level tds there are more tables with more tds that shouldn't be selected

<table>
  <tr>
    <td>        <!-- this is what I want to select -->
      <table /> <!-- more td's inside that I don't want to select -->
    </td>
  </tr>
  <tr>
    <td>        <!-- this is what I want to select -->
      <table /> <!-- more td's inside that I don't want to select -->
    </td>
  </tr>
</table>

To select the desired tds would be easy: table > tr > td. However there might be tables with tbody tags:

<table>
  <tbody>
    <tr>
      <td>        <!-- this is what I want to select -->
        <table /> <!-- more td's inside that I don't want to select -->
      </td>
    </tr>
    <tr>
      <td>        <!-- this is what I want to select -->
        <table /> <!-- more td's inside that I don't want to select -->
      </td>
    </tr>
  </tbody>
</table>

That itself would be easy as well: table > tbody > tr > td.

How can I find an easy expression that doesn't rely on the > child selector and works universally?

Something like table tr > td (which obviously wouldn't work since it selects tds inside the nested table. Thanks!

Upvotes: 0

Views: 171

Answers (2)

Mykola Uspalenko
Mykola Uspalenko

Reputation: 104

The correct answer is:

$('#tbl1').find('tr:first').parent().children().not(':not(td)')

.not(':not(td)') removes not td tags.

Examples:

<table id="tbl1">
<tr>
  <td>1</td>
  <input type="hidden" name="hidden1" value="something"> 
  <td>2</td>
  <td> 
       <table>
          <tr><td>1</td>
            <input type="hidden" name="hidden1" value="something"> 
            <td>2</td>
          </tr>
        </table>
</td>
</tr>
</table>

<table id="tbl2">
<tbody>
<tr>
  <td>1</td>
  <input type="hidden" name="hidden1" value="something"> 
  <td>2</td>
  <td> 
       <table>
          <tr>
            <td>1</td>
            <input type="hidden" name="hidden1" value="something"> 
            <td>2</td>
          </tr>
        </table>
</td>
</tr>
</tbody>
</table>

Code:

var r1 = $('#tbl1').find('tr:first').children();
var r2 = $('#tbl1').find('tr:first').children().not(':not(td)');
var r3 = $('#tbl2').find('tr:first').children();
var r4 = $('#tbl2').find('tr:first').children().not(':not(td)');

console.log ("r1: ", r1.length);
console.log ("r2: ", r2.length);
console.log ("r3: ", r3.length);
console.log ("r4: ", r4.length);

Output:

"r1: ", 4
"r2: ", 3
"r3: ", 4
"r4: ", 3

Upvotes: 0

Felix Kling
Felix Kling

Reputation: 816404

As I expressed in my comment, I'm all in favor of table > tbody > tr > td, but as an alternative, you can use

td:not(td td)

This selects all td elements that are not descendants of a td element. But note that this will only work with jQuery, because you usually cannot use complex selectors with :not.

Alternatively, use the .not method:

$('td').not('td td')

Upvotes: 1

Related Questions