Reputation: 123
I have three tables on a web page. Each table has a corresponding element nested in <thead>
tags that I need to reflect the number of rows in its respective table, minus the head row and bottom row (-2). When I'm working with a single table, this code works just fine:
HTML Table Snippet:
<table class="table" id="category">
<thead>
<tr>
<th><i class="fa fa-hashtag"></i> headache - <label class="label label-primary" id="tableBadge">0</span></th>
<th><i class="fa fa-calendar"></i> Date Added</th>
<th><i class="fa fa-cog"></i> Options</th>
</tr>
</thead>
<tbody>
<tr>
<td>Test entry</td>
<td>1/19/2016</td>
<td>
<a href="#" class="btn btn-success btn-xs"><i class="fa fa-pencil"></i></a>
<a href="#" class="btn btn-primary btn-xs"><i class="fa fa-calendar"></i></a>
<a href="#" class="btn btn-danger btn-xs"><i class="fa fa-trash"></i></a>
</td>
</tr>
<tr>
<td><a href="#" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> add entry</a></td>
</td>
</tr>
</tbody>
</table>
Javascript:
function catCount() {
var rows = document.getElementById("category").rows.length;
document.getElementById("tableBadge").innerHTML = rows - 2 + " entries";
}
However, respecting the laws of HTML in that ID's are unique to an element, I'm left in a bind. Using getElementsByClassName()
or getElementsByTagName()
the values return 0, telling me it's not working. At least using identical syntax.
I've searched Google et al. for a solution, but they seem to be tailored towards the total amount of rows, rather individual counts respective of their tables.
Any help would be appreciated. Thank you in advance.
Upvotes: 1
Views: 5053
Reputation: 253506
While you've already accepted an answer, I'd suggest that the following might be slightly more useful, and far less-reliant on hard-coding exemptions (and therefore less of a maintenance nightmare for the future).
That said, my solution involves placing the 'footer' inside of a <tfoot>
element, in order that the relevant <tr>
elements are all contained within the <tbody>
element(s) of the <table>
.
The JavaScript function I'd recommend:
// wrapping the function in an Immediately-Invoked Function Expression
// ("IIFE") in order that it runs immediately and does not require
// calling later:
(function() {
// using 'let' (rather than var) to declare local variables, all
// of which are available only within the block in which they're
// declared; here we convert the NodeList returned by
// document.querySelectorAll('span.label') into an Array, using
// Array.from():
let outputs = Array.from(document.querySelectorAll('span.label')),
// declaring another variable for later use:
tbodies;
// iterating over each of the found 'span.label' elements
// in the Array, using Array.prototype.forEach():
outputs.forEach(function(span) {
// the first argument (here 'span') is the current
// array-element of the array over which we're iterating.
// finding the closest ancestor <table> element from the
// current span node, and then finding all the <tbody>
// elements contained within that <table>, and converting
// that NodeList to an Array, again using Array.from() to
// do so:
tbodies = Array.from(span.closest('table').querySelectorAll('tbody'));
// updating the text-content of the span to:
// the sum of the child <tr> elements found in each of
// the <tbody> elements found within the <table>, using
// Array.prototype.reduce() to reduce the Array to a single
// (here numeric) value; here we use an Arrow Function
// to add the number of children of the <tbody> element
// to the initialValue of the reduce method (0, the
// final argument following the comma):
span.textContent = tbodies.reduce((initialValue, tbody) => a + tbody.children.length, 0);
});
// here the function is invoked:
})();
(function() {
let outputs = Array.from(document.querySelectorAll('span.label')),
tbodies;
outputs.forEach(function(span) {
tbodies = Array.from(span.closest('table').querySelectorAll('tbody'));
span.textContent = tbodies.reduce((initialValue, tbody) => initialValue + tbody.children.length, 0);
});
})();
<table class="table category">
<thead>
<tr>
<th><i class="fa fa-hashtag"></i> headache - <span class="label label-primary"></span>
</th>
<th><i class="fa fa-calendar"></i> Date Added</th>
<th><i class="fa fa-cog"></i> Options</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="2"><a href="#" class="btn btn-default btn-xs"><i class="fa fa-plus"></i> add entry</a>
</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Test entry</td>
<td>1/19/2016</td>
<td>
<a href="#" class="btn btn-success btn-xs"><i class="fa fa-pencil"></i></a>
<a href="#" class="btn btn-primary btn-xs"><i class="fa fa-calendar"></i></a>
<a href="#" class="btn btn-danger btn-xs"><i class="fa fa-trash"></i></a>
</td>
</tr>
</tbody>
</table>
It's worth noting that the above approach will handle multiple <table>
elements each with, potentially, multiple <tbody>
elements; and requires no hard-coding of values to discount from the final count, since it selects only those elements that should be counted.
References:
Array.from()
.Array.prototype.forEach()
.Array.prototype.reduce()
.document.querySelectorAll()
.Element.closest()
.let
.Upvotes: 0
Reputation: 696
getElementsByTagName and getElementsByClassNAme return node list, you need to iterate over them.
window.addEventListener('load', function(e) {
//This is a node list you must iterate
var tables = document.getElementsByTagName('table');
for (var i = 0; i < tables.length; i++) {
//This loop will handle each tble selected
var table = tables[i];
var totalRows = table.rows.length;
console.log(totalRows);
//Add your code here
}
}, false);
Upvotes: 0
Reputation: 1462
change id tableBadge to tableBadge_category and similar to othter tables.
'table_id' is a id of table and you span is tableBadge_table_id
function catCount(table_id) {
var rows = document.getElementById(table_id).rows.length;
document.getElementById("tableBadge_"+table_id).innerHTML = rows - 2 + " entries";
}
catCount('category');
catCount('other_table');
Upvotes: 2
Reputation: 20024
Try instead using the querySelectorAll
like:
document.querySelectorAll('.table>thead>tr')
The length of the array may be the answer you are looking for
Upvotes: 0