Dave
Dave

Reputation: 17

children().length is returning an unexpected value

Everything can be found here: http://jsfiddle.net/dweiliu/NBFMq/3/

This is the relevant code in question:

$('article.weeklyStandings').each(function(){
   var numPlayers = $(this).children('table tr').length;
   $(this).children('h2').append(" - " + numPlayers + " Players");
});

I have potentially multiple tables of data with results as displayed in the jsfiddle. I want to point out the number of players who played on any given week by looking up the number of rows in the table.

Why is $(this).children('table tr').length; returning 0 on jsfiddle? Note that on my local machine, this same code is returning 3.

Upvotes: 1

Views: 553

Answers (7)

Smern
Smern

Reputation: 19066

The problem you are having is:

  1. children() will only look at direct children. You'll want to use find() which will find all the table tr within each article.
  2. If you count all of the tr's you will have end up with an extra because your heading will also be counted as a player. For this reason you can subtract 1 from the length of tr's.

Solution

Here is an example implementing the above solutions: Demo

var numPlayers = $(this).find('table tr').length -1;

Alternative (the one I would use)

As you have a record class on your player tr's, you could use .record in your selector instead, this will provide better readability and flexibility if you wish to add other rows in the future that should not be counted as a player: Demo

var numPlayers = $(this).find('.record').length;

Another Alternative

You could also use context selectors like $('.record', this) instead of $(this).find('.record'), but in my opinion it's easier to read find() chaining. Also, as context selectors internally have to use find() anyway, using find() directly will perform slightly better: Performance test

Upvotes: 2

j08691
j08691

Reputation: 207901

Change

var numPlayers = $(this).children('table tr').length;

to

var numPlayers = $(this).find('table tr').length-1;

jsFiddle example

.children() method differs from .find() in that .children() only travels a single level down the DOM tree while .find() can traverse down multiple levels to select descendant elements (grandchildren, etc.) as well

Upvotes: 1

Anton
Anton

Reputation: 32581

Change

var numPlayers = $(this).children('table tr').length;

to

var numPlayers = $('.record', this).length;

DEMO

Upvotes: 1

Anthony Grist
Anthony Grist

Reputation: 38345

The .children() function only looks at immediate descendants, so those that are one level down in the DOM. What you're saying is "look for a <tr> that's inside a <table> and is also the direct descendant of the <article class="weeklyStandings"> element"; that won't ever be the case because the <table> is between those two.

You should use .find() instead, as well as modify your selector so that it doesn't include your header row:

$(this).find('table tr.records').length;

Upvotes: 0

MonkeyZeus
MonkeyZeus

Reputation: 20737

Ditto to other answers:

var numPlayers = $(this).children('table').find('tr').length;

Upvotes: 0

Arun P Johny
Arun P Johny

Reputation: 388316

Try

$(document).ready(function(){
    $('tr.record').each(function(){
        var cells = $(this).children('td');
        var gamesWon = parseInt(cells[1].innerText);
        var gamesPlayed = parseInt(cells[2].innerText);
        var winningPercentage = (gamesWon / gamesPlayed * 100).toFixed(1) + "%";
        $(cells[3]).html(winningPercentage);
    });
    $('article.weeklyStandings').each(function(){
        var numPlayers = $(this).find('tr.record').length;
        $(this).children('h2').append(" - " + numPlayers + " Players");
    });
});

Demo: Fiddle

Upvotes: 0

Robin Leboeuf
Robin Leboeuf

Reputation: 2116

Change children() by find() in your numPlayer affectation :)

Upvotes: 0

Related Questions