54

Using jQuery, how would you figure out how many columns are in a table?

<script>
    alert($('table').columnCount());
</script>

<table>
    <tr>
        <td>spans one column</td>
        <td colspan="2">spans two columns</td>
        <td colspan="3">spans three columns</td>
    <tr>
</table>

The total number of columns in this example is 6. How could I determine this using jQuery?

Andrew
  • 227,796
  • 193
  • 515
  • 708
  • 2
    Attaching an id to the row, looping through `HTMLTableRowElement.cells` for that row, and adding up the `colSpan` DOM property for each cell would probably get the job done. However, that's without jQuery. –  Jul 13 '11 at 18:45
  • How do you count six columns in your example? – George Cummins Jul 13 '11 at 18:46
  • When you say `6`, do you mean a `td` of `colspan="2"` would count as two? – kei Jul 13 '11 at 18:46
  • Right, so if you have 5 rows, do you want a result of 6 or 30? – Incognito Jul 13 '11 at 19:45
  • If a TD spans more than one column, then it counts as more than one column. A table cell does not necessarily = a column since a cell can span multiple columns. – Andrew Jul 13 '11 at 21:09

16 Answers16

59

Here you go:

jsFiddle

$(function() {
    var colCount = 0;
    $('tr:nth-child(1) td').each(function () {
        if ($(this).attr('colspan')) {
            colCount += +$(this).attr('colspan');
        } else {
            colCount++;
        }
    });
});
Craig M
  • 5,598
  • 4
  • 32
  • 43
  • One note... I noticed that some examples work better when you make the first line of your function - $(this).find('tr:nth-child(1) td').each(function() { ... – rahkim Jun 14 '12 at 12:25
  • 5
    This also might need to be adjusted if the first row contains th elements instead of td. I used ('tr:last-child td') – drinkdecaf Sep 12 '12 at 17:54
  • When a table has thead and tbody, the code doesn't work. – Gqqnbig Jul 15 '15 at 20:27
  • 3
    You can replace the entire IF with just `colCount += this.colSpan;` which returns 1 when it's not set in the HTML. No point in using jQuery when the DOM already provides better functionality. – Tobia Nov 25 '15 at 16:24
40
$("table").find("tr:first td").length;

I edited as I didn't realize you were counting the colspan's.

If you want to include using colspan try a loop through the td's in the first row:

var cols = $("table").find("tr:first td");
var count = 0;
for(var i = 0; i < cols.length; i++)
{
   var colspan = cols.eq(i).attr("colspan");
   if( colspan && colspan > 1)
   {
      count += colspan;
   }else{
      count++;
   }
}
scrappedcola
  • 10,423
  • 1
  • 32
  • 43
  • 1
    +1 because you left your original answer that doesn't involve column spans b/c that's what I needed now, almost two years later. $('#myTable tr').length; – gloomy.penguin Mar 12 '13 at 15:51
  • @gloomy.penguin Just to be clear: `$('#myTable tr').length;` will give you the number of _rows_ in the table, or rather the number of `tr` elements. – mflodin Jun 12 '13 at 08:41
  • 1
    There may be tables within tables: `$("table > tbody").find("> tr:first > td").length` – Evan Moran Jun 16 '13 at 23:42
35

This is the cleanest in my opinion. It handles tables within tables. And is short and simple:

$("table > tbody > tr:first > td").length
lxg
  • 12,375
  • 12
  • 51
  • 73
Evan Moran
  • 3,825
  • 34
  • 20
5

In POJS (Plain Old JavaScript):

HTML:

<table id="foo">
    <thead></thead>
    <tbody>
        <tr>
            <td>1</td>
            <td colspan="2">2</td>
            <td colspan="3">3</td>
        </tr>
    </tbody>
    <tfoot></tfoot>
</table>

JS:

var foo = document.getElementById("foo"), i = 0, j = 0, row, cell, numCols = 0;
//loop through HTMLTableElement.rows (includes thead, tbody, tfoot)
for(i;i<foo.rows.length;i++)
{
    row = foo.rows[i];
    //loop through HTMLTableRowElement.cells
    for(j = 0;j<row.cells.length;j++)
    {
        cell = row.cells[j];
        numCols += cell.colSpan;
        cell = null;
    }
    row = null;
}

alert(numCols) //6;

HTMLTableElement.rows will collect rows from every HTMLTableSectionElement (THead, TBody, and TFoot). Each section also has its own rows HTMLCollection, so you can filter them if need be.

4

To be robust..I'd do something like this

alert(numCol("table") + " is the max number of cols");

function numCol(table) {
    var maxColNum = 0;

    var i=0;
    var trs = $(table).find("tr");

    for ( i=0; i<trs.length; i++ ) {
        maxColNum = Math.max(maxColNum, getColForTr(trs[i]));
    }

    return maxColNum;
}

function getColForTr(tr) {

    var tds = $(tr).find("td");

    var numCols = 0;

    var i=0;
    for ( i=0; i<tds.length; i++ ) {
        var span = $(tds[i]).attr("colspan");

        if ( span )
            numCols += parseInt(span);
        else {
            numCols++;
        }
    }
    return numCols;
}

Just in case we have some funkiness going on between different rows.

vinceh
  • 3,490
  • 1
  • 21
  • 24
1

Pass in a table with something like $('foo#table') or $('table:first')

function getColumnCount(e) { //Expects jQuery table object
    var c= 0;
    e.find('tbody tr:first td').map(function(i,o) { c += ( $(o).attr('colspan') === undefined ? 1 : parseInt($(o).attr('colspan')) ) } );
    return c;
}
rainabba
  • 3,804
  • 35
  • 35
1

To circumvent the td/th issue (and also fix a potential issue where attr('colspan') was giving me strings) I went with this:

var colspan = 0;
$('#table').find('tr:first').children().each(function(){
    var cs = $(this).attr('colspan');
    if(cs > 0){ colspan += Number(cs); }
    else{ colspan++; }
});
T.J. Compton
  • 405
  • 2
  • 11
1
/**
 * Get number of columns in table.
 * @param {string} table jQuery selector
 * @param {boolean} [malformed=false] whether to inspect each row of malformed table;
 * may take some time for large tables
 * @returns {?number} number of columns in table, null if table not found.
 */
function getTableColumnsCount(table, malformed) {
    malformed = malformed || false;

    var $table = $(table);
    if (!$table.length) {
        return null;
    }

    var rows = $table.children('thead, tfoot, tbody').children('tr');
    if (!malformed) {
        // for correct tables one row is enough
        rows = rows.first();
    }
    var maxCount = 0;
    rows.each(function () {
        var currentCount = 0;
        $(this).children('th, td').each(function () {
            currentCount += this.colSpan;
        });
        maxCount = Math.max(maxCount, currentCount);
    });

    return maxCount;
}

See in action https://jsfiddle.net/kqv7hdg5.

  • Takes colspan into account.
  • Works for nested tables.
  • Works for <thead>, <tfoot>, <tbody>.
  • Works for mix of <th> and <td>.
  • Works for malformed tables.

Slightly modified version for those who would like to pass jQuery object instead of selector https://jsfiddle.net/5jL5kqp5.

kdmitry
  • 359
  • 3
  • 12
1

http://jsfiddle.net/WvN9u/

Just paying attention to colspan attr

Joe
  • 80,724
  • 18
  • 127
  • 145
0

I simplified answer of Craig M. And modified to apply to both td and th tag.

function GetColumnCount($Table)
{
    var ColCount = 0;
    $Table.find("tr").eq(0).find("th,td").each(function ()
    {
        ColCount += $(this).attr("colspan") ? parseInt($(this).attr("colspan")) : 1;
    });

    return ColCount;
}
doctorgu
  • 616
  • 6
  • 9
0
var foo = document.getElementById("price-test-table")
foo.tBodies["0"].firstElementChild.children.length
  1. Give your table an id name
  2. Assume your rows all have the same amount of columns and you have a table body
  3. Use above code, which I think is the simplest on here, similar to first answer but provides a little more detail
ByteMe
  • 1,159
  • 2
  • 15
  • 28
0

With jQuery and reduce it could look like this:

$.fn.tableCellCount = function() {
    return $(this).find('tr:first td, tr:first th').get().reduce(function(a,b) {
        return a + ($(b).attr('colspan') ? parseInt($(b).attr('colspan')) : 1);
    },0)
}

$('table').tableCellCount();

Or even simpler:

$.fn.tableCellCount = function() {
    return $(this).find('tr:first td, tr:first th').get().reduce(function(a,b) {
        return a + (b.colSpan ? parseInt(b.colSpan) : 1);
    },0)
}

$('table').tableCellCount();
shaedrich
  • 5,457
  • 3
  • 26
  • 42
0

This is the simple solution I have done: In case you are using TR change TH for TR. Using JQUERY:

<script>
        $(document).ready(function() {
            var number = $("table > tbody > tr:first > th").length;
            for(var i=0; i <= number; i++){
                $('th:nth-child('+ i +')').hide();
            }
        });
</script>
0

You have to set an ID to the header row:

<table>
    <tr id="headerRow">
        <td>spans one column</td>
        <td colspan="2">spans two columns</td>
        <td colspan="3">spans three columns</td>
    </tr>
</table>

And then you can use the following function:

function getColumnCount(headerRowId) {
    var columnCount = 0;
    $('#' + headerRowId + ' > td').each(function() {
        var colspanValue = $(this).attr('colspan');
        if (colspanValue == undefined) {
            columnCount++;
        } else {
            columnCount = columnCount + parseInt(colspanValue);
        }
    });
    return columnCount;
}
Nicolae Albu
  • 1,235
  • 6
  • 6
0

One Line:

$('.table-responsive tr th').children().length;
-1
function(){
    num_columns = 0;
    $("table td]").each(function(){
        num_columns = num_columns + ($(this).attr('colspan') == undefined ? 1 : $(this).attr('colspan'));
    });
    return num_columns;
}
  • At least provide working syntax please, if not an alternative answer. Even without the syntax error, this just returns a string of colspan for every td in the table. Nothing useful. – rainabba Feb 03 '14 at 16:32