102

I am having something like:

<table id="tblOne">
            <tbody>
                <tr>
                    <td>
                        <table id="tblTwo">
                            <tbody>
                                <tr>
                                    <td>
                                        Items
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        Prod
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </td>
                </tr>
                <tr>
                    <td>
                        Item 1
                    </td>
                </tr>
                <tr>
                    <td>
                        Item 2
                    </td>
                </tr>
            </tbody>
        </table>

I have written jQuery to loop through each tr like:

$('#tblOne tr').each(function() {...code...});

But problem is that it loops through the "tr" of "tblTwo" also which I don't want. Can anyone please suggest something to solve this?

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
ANP
  • 15,287
  • 22
  • 58
  • 79

3 Answers3

257

In jQuery just use:

$('#tblOne > tbody  > tr').each(function() {...code...});

Using the children selector (>) you will walk over all the children (and not all descendents), example with three rows:

$('table > tbody  > tr').each(function(index, tr) { 
   console.log(index);
   console.log(tr);
});

Result:

0
<tr>
1 
<tr>
2
<tr>

In VanillaJS you can use document.querySelectorAll() and walk over the rows using forEach()

[].forEach.call(document.querySelectorAll('#tblOne > tbody  > tr'), function(index, tr) {
    /* console.log(index); */
    /* console.log(tr); */
});
Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
75

Just a recommendation:

I'd recommend using the DOM table implementation, it's very straight forward and easy to use, you really don't need jQuery for this task.

var table = document.getElementById('tblOne');

var rowLength = table.rows.length;

for(var i=0; i<rowLength; i+=1){
  var row = table.rows[i];

  //your code goes here, looping over every row.
  //cells are accessed as easy

  var cellLength = row.cells.length;
  for(var y=0; y<cellLength; y+=1){
    var cell = row.cells[y];

    //do something with every cell here
  }
}
rlemon
  • 17,518
  • 14
  • 92
  • 123
GNi33
  • 4,459
  • 2
  • 31
  • 44
  • 14
    I agree that jQuery is often not really necessary for this kind of task (especially on newer browser with `.querySelectorAll()`) but if you're already including jQuery it's a waste not to use it (and DOM solution with two `for` loop is not so straightforward, imho) – Fabrizio Calderan May 03 '12 at 13:18
  • But if you're already including jQuery then your doing it wrong and need to remove it ASAP – Raynos May 03 '12 at 13:19
  • ***using*** jQuery also has consequences. $() does about 100 things before it actually selects your element by it's id (as an example) . I'm not saying don't use it... but for trivial things like this where the vanilla js solution is like a few characters more to write you're saving on processing. albeit not much... but why do 10 000/second when you can do 10 000 000.... just makes sense no? – rlemon May 03 '12 at 13:22
  • @F.Calderan I understand what you mean, but like i said, it's a recommendation, because it's very straigth forward. something like accidentaly selecting more tables won't happen here and the iteration with a for-loop is pretty fast. – GNi33 May 03 '12 at 13:23
  • @GNi33 it would be faster if you use `document.querySelectorAll(''#tblOne > tbody > tr')` instead :) - @riemon I suppose jQuery has some internal optimizations so in newer browser it calls native methods like that – Fabrizio Calderan May 03 '12 at 13:25
  • @F.Calderan your joking / trolling / ignorant right? QSA is slow as hell, jQuery optimizes as hard as it can, it's still an order of magnitude slower then the DOM. – Raynos May 03 '12 at 13:26
  • Faster to write, maybe. Faster to run? You have to be kidding. – Florian Margaine May 03 '12 at 13:26
  • @Raynos sorry probably I'm misunderstanding what you're saying. – Fabrizio Calderan May 03 '12 at 13:26
  • @F.Calderan your implying `document.querySelectorAll('#tblOne > tbody > tr')` is faster then `document.getElementById("tblOne").rows` which is simply stupid. – Raynos May 03 '12 at 13:31
  • no, sorry I mean it's faster [but only to write]. It's obvious that second statement will be faster (as execution speed). just a misunderstanding :) – Fabrizio Calderan May 03 '12 at 13:33
  • @F.Calderan What do you mean faster to write, the gEBI & .rows version is 11 characters shorter. Even `id("tblOne").rows` is still 8 characters smaller then `$('#tblOne > tbody > tr')` – Raynos May 03 '12 at 13:38
  • @Raynos using QSA _to me_ is just more immediate. It would be _to me_ more natural use it, so it would be more faster to think and to write Ok? (Probably because I don't think to make an unnecessary optimization over a single selection) – Fabrizio Calderan May 03 '12 at 13:40
  • 1
    I had code that was using JQuery to do simple text searching in tables. With 6000+ rows it was noticeably laggy. Changed it to use regular JS and it was 10 fold faster. – NSjonas Jan 07 '15 at 05:52
  • By using QSA.... your throwing away cross browser support and limiting your website to newer browsers only... The only sad part about web development is this sort of stuff.... – Angry 84 Jan 13 '15 at 23:44
22

Use immediate children selector >:

$('#tblOne > tbody  > tr')

Description: Selects all direct child elements specified by "child" of elements specified by "parent".

Sarfraz
  • 377,238
  • 77
  • 533
  • 578