jQuery: Add table row count column

In this post you will learn how to add a table column with a row count in it. If you are looking for "how to add a new table row", please refer to previous post.

Recently, a user on the jQuery mailing list asked how she could automatically add a table row counter into her table. She wanted to add a new column to her table and display the row number, so that her users could refer to row numbers while communicating. The user had the following HTML table markup:

<table class="transactions">
  <tr>
    <td>Order 1</td>
    <td>$10.99</td>
  </tr>
  <tr>
    <td>Order 2</td>
    <td>$4.50</td>
  </tr>
</table>

For cases like this, where you can be sure that there would be no table cell rowspans and there are only trs and tds. Then, jQuery code to add a counter is straightforward.

$('.transactions tr td:first-child').each(function(i){
  $(this).before('<td>'+(i+1)+'</td>');
});

Here, we are selecting first child td tags of all tr tags in a table with a transactions class. Then, we are iterating through them and passing a zero based index to the loop. While looping though the first row cells, we are adding new column just using .before('<td>'+(i+1)+'</td>') method. The resulting table would have the following markup:

<table class="transactions">
  <tr>
    <td>1</td>
    <td>Order 1</td>
    <td>$10.99</td>
  </tr>
  <tr>
    <td>2</td>
    <td>Order 2</td>
    <td>$4.50</td>
  </tr>
</table>

However, for cases when tables have header rows and footer, the above script may not behave as expected. That is why we have to take into the consideration table headers and footers. So the code snippet above will become:

$(".transactions").each(function(){
  $('th:first-child, thead td:first-child', this).each(function(){
    var tag = $(this).prop('tagName');
    $(this).before('<'+tag+'>#</'+tag+'>');
  });
  $('td:first-child', this).each(function(i){
    $(this).before('<td>'+(i+1)+'</td>');
  });
});

This code takes into the account the table headers and adds "#" header column for the counter. Still, this code is not as universal as it could have been. Let’s take into the account the possibility of row spans and multi line header rows and rewrite the code into the jQuery plugin with options.

So, here is the final code:

(function($){
  $.fn.extend({
    tableAddCounter: function(options) {
      
      // set up default options 
      var defaults = { 
        title:  '#',
        start:  1,
        id:     false, 
        class:  false,
      };

      // Overwrite default options with user provided
      var options = $.extend({}, defaults, options);

      return $(this).each(function(){
        // Make sure this is a table tag
        if($(this).is('table')){

          // Add column title unless set to 'false'
          if(!options.title) options.title = '';
          $('th:first-child, thead td:first-child', this).each(function(){
            var tagName = $(this).prop('tagName');
            $(this).before('<'+tagName+' rowspan="'+$('thead tr').length+'" class="'+options.class+'" id="'+options.id+'">'+options.title+'</'+tagName+'>');
          });
        
          // Add counter starting counter from 'start'
          $('tbody td:first-child', this).each(function(i){
            $(this).before('<td>' + (options.start + i) + '</td>');
          });
        
        }
      });
    }
  });
})(jQuery);

Plugin features

  • Can set custom settings as a hash parameter to the plugin:
    • title - counter column header text
    • start - the number to start the counter
    • id - CSS "id" to add to all the counter tds
    • class - CSS "class" to add to all the counter tds
  • It takes into consideration table header's row and column spans.
  • Gracefully degrade for browsers that do not support javascript.
  • Keeps your HTML mark up clean.
  • Make your tabular data more readable.

Example code

// Add row count with default settings
$('.myTables').tableAddCounter(); 

// Provide your settings for 
// column name, css class and start counter from 26
var options = { 
  name: "Count", 
  class: "counter",
  start: 26
};
$('.myTables').tableAddCounter(options);

Here is the original table (to the left) and new table (to the right) with row columns automatically added.

tableAddCounter jQuery plugin screenshot