jQuery TableSorter Comma Parser

Last night I needed a simple HTML table with sortable columns, and after a quick Googling, found the TableSorter jQuery plugin.  I'd come across it before, but never actually used it.  Added a class to my table (for targeting and to leverage the CSS that it comes with), added the required line of JavaScript to initialize it, and I was up and running.

As I tuned the presentation, however, I ran into a couple issues.  First, the included styling sets the table width to 100%, but that was easily fixed with a .css("width", "auto") call.  I also wanted alternating row backgrounds, and a quick look showed that there is a 'zebra' widget built in that does exactly that, it just has to be enabled.

The biggest problem was with number formatting.  Some of the sortable columns contained large numbers, and when I wrapped the output with numberFormat() to add commas, the sorting reverted to textual instead of numeric.  A quick look through the source showed why: the 'digit' parser respects only numbers, the decimal point, and an optional leading +/-.  So the commas made it skip any numeric sorting and fall back to textual sorting.  Fortunately, the fix was simple.  Before initializing the table, I just added a new parser that piggybacks on the 'digit' parser's implementation:

jQuery.tablesorter.addParser({
  id: "commaDigit",
  is: function(s, table) {
    var c = table.config;
    return jQuery.tablesorter.isDigit(s.replace(/,/g, ""), c);
  },
  format: function(s) {
    return jQuery.tablesorter.formatFloat(s.replace(/,/g, ""));
  },
  type: "numeric"
});

The only difference between it and the 'digit' parser is that it strips all commas from the string before handing off to the backing methods (the blue stuff).  Works like a champ.  The separator should probably be parameterized like the decimal stuff is, but I only deal with comma separators in this app, so I didn't bother.

The only thing I wasn't able to figure out (though I'll admit I didn't try very hard) was setting the initial sort to be descending, so when you click a column header for the first time it does a descending sort rather than ascending (with subsequent clicks reversing the sort as normal).  Setting up the on-initialization sort to be descending is simple, but I didn't see a way to parameterize user-triggered sorts.

33 responses to “jQuery TableSorter Comma Parser”

  1. Aaron

    Thanks for publishing this. I was researching this very problem and came across your solution. Thanks again.

  2. Phingers

    how do we handle negative numbers? Doesnt seem to like that much.

  3. Webomatica

    Just ran into the exact situation you describe in the last paragraph – would be nice to set the initial user click to sort a column by descending. Looking for a solution right now…

  4. Brian

    Barney, I wrote the docs for Christian for Tablesorter. He's generally very receptive to improvements and plugins so you should drop him a line with your tweak. If nothing else, publishing it on the tablesorter.com site would help others.

  5. pawel

    Thanks for this. But I have one more problem. If i set comma for decimal parameter
    decimal: ',',
    the sort for numbers with leading + and – doesn't work properly :( What's wrong here?

  6. pawel

    My problem is, I would like use comma for decimal and point as thousands separator (german format). But if i set "," as decimal like this:

    $("#stock_table").tablesorter({
      decimal: ',',
      widgets: ['zebra'],
      sortList: [[5,0]],
    }); )
    

    tablesorter can't handle it, when I have some numbers beginning with 0 and leading +/-. Try it out for table with 6 numbers in column: (+1,4; +0,3; -0,13; +4,5; +0,15; -0,1) Commas should be here decimal separator, after i set "decimal: ','". But tablesorter iterprets it not as digit . It doesn't work too, if I use some other symbol for decimal, like "_" or "a". I suppose, the reg expression for Digit ist writtin wrong :( Could You help me with this problem? Thank You for Your answer!

  7. pawel

    I think, I have to email Christian ;-) and report it here later ;-) Anyway, thanks for Your answer.

  8. Serb

    it kinda works and it doesn't for negative numbers that are either use a decimal comma or a decimal period.

    in my case, I found this works just fine (spanning both english and french version of decimal delimiters – commas and points, and both positive/negative number, sorting them in proper order)… I just added this custom parser to jquery.tablesorter.js itself, but you can use the same code for front-end declarations too:

    ts.addParser({
      id: "commaDigit",
      is: function(s, table) {
        var c = table.config;
        return $.tablesorter.isDigit(s.replace(/[,.]/g, ""), c);
      },
      format: function(s) {
        return $.tablesorter.formatFloat(s.replace(/[,.]/g, ""));
      },
      type: "numeric"
    });
    

    Now, I would definitely kill for a tip on how to change the default on-click sorting to DESC instead of ASC… any news there?

  9. Serb

    found it.

    the line that says the following in jquery.tablesorter.js file:

    // get current column sort order
    this.order = this.count++ % 2;

    just change that to this instead:

    this.order = ++this.count % 2;

  10. Serb

    Yeah, it only took me 3 hours and about a dozen posts all over the net to find a clue where to look for it…

  11. Jeremy

    Does anyone know how to configure tablesorter so that some of the columns will sort Descending on first click, while other columns will sort Ascending on first click.
    The "use case" is I want Alpha columns (like people's names) to sort A…Z, but if user clicks on say the number column that it would sort Descending (100…1). I was not successful so far using the "headers" config. I think it is using that in conjunction with sortlist. The sortlist example is always showing it firing on page load.

    Thanks!
    jeremy.

  12. kidcardboard

    This works like a charm as longs as you have values with commas in the first row.

    My problem is my values range from 0 – 2,000 so if the value in the first row doesn't have a comma in it it treats all comma'd values in that corresponding column as strings. For the time being I've put in a hidden row with 9,999 as it's value and it works, but this is obviously not the best solution.

    Any suggestions?

  13. kidcardboard

    That was it. I registered it explicitly for each column and it works now. ty

  14. Ja

    Hi, I'm encountering the same problem as kidcardboard's. What do you mean by "explicitly registering the parser for the table column"? Could you please explain? Thanks.

  15. Jonathan

    Thanks a lot for both solutions: the DESC first, and the thousand separator parser. I was working a lot of time without them but now I can improve my tables, thanks :)

  16. amos

    This is awesome! So helpful.

    How come it didn't make it into the official plugin? I think it's a must!

    Thanks,
    Amos

  17. Charlie

    I'm struggling here, I've tried to add your code, and even explicitly registering the parsers in the th tags, but it's not working. Has a change in jQuery or the tablesorter project changed the way this is implemented?

  18. Charlie

    I'm sorry, please ignore my last comment. All good!

  19. Charlie

    Ugh, apologies for the comment spam! Just to finish this I had to follow instructions here: http://tablesorter.com/docs/example-parsers.html

    That was the only way I was able to get this to work. I'll stop commenting now.

  20. Ryan

    Thank you! Ive been searching for this solution for almost a week and this solved my problem!

  21. ronaldo

    Awesome I was trying to find a solution for this issue and your solution did it….
    thank you ! thank you! thank you!

  22. Jay

    Sorry for the dumb question, but I'm struggling. I put your parser code into my js file and referenced it with: $("table").tablesorter( {sorter:'commaDigit'})

    And it isn't working. Here's my whole JS file if you don't mind telling me what I'm doing wrong (Thanks a ton):

    $(document).ready(function() {
    
    jQuery.tablesorter.addParser({
      id: "commaDigit",
      is: function(s, table) {
        var c = table.config;
        return jQuery.tablesorter.isDigit(s.replace(/,/g, ""), c);
      },
      format: function(s) {
        return jQuery.tablesorter.formatFloat(s.replace(/,/g, ""));
      },
      type: "numeric"
    });
    $(function() {
    $("table").tablesorter( {sorter:'commaDigit'})
    });
    });
    
  23. H@ck!

    it should be

    $(function() {
    $("table").tablesorter( {
    
    headers:{
    3:{sorter:'commaDigit'}//3 referin to the header number
    }
    )
    });
    });
    
  24. Jay

    Thanks for the help.

  25. changeboy

    More Simple:

    $(document).ready(function() {
            var mydigits= function(node)  {
            // extract data from markup and return it
             var s=node.innerHTML;
            return s.replace(/,/g, "");
            }
            $(function() {
            $("#{$chart_id}_table").tablesorter( {
                    textExtraction:mydigits
                    })
            });
    });
    
  26. Ondiege

    Thanks!! I have been trying to figure this out for the past few hours, this worked perfect!