views:

1969

answers:

1

I'm using the jQuery Tablesorter and have an issue with the order in which parsers are applied against table columns. I'm adding a custom parser to handle currency of the form $-3.33.

$.tablesorter.addParser({
    id: "fancyCurrency",
    is: function(s) {
      return /^\$[\-]?[0-9,\.]*$/.test(s);
    },
    format: function(s) {
      s = s.replace(/[$,]/g,'');
      return $.tablesorter.formatFloat( s );
    },
    type: "numeric"
});

The problem seems to be that the built-in currency parser takes precedence over my custom parser. I could put the parser in the tablesorter code itself (before the currency parser) and it works properly, but this isn't very maintainable. I can't specify the sorter manually using something like:

headers: {
    3: { sorter: "fancyNumber" },
    11: { sorter: "fancyCurrency" }
}

since the table columns are generated dynamically from user inputs. I guess one option would be to specify the sorter to use as a css class and use some JQuery to explicitly specify a sorter like this question suggests, but I'd prefer to stick with dynamic detection if possible.

+4  A: 

The first option is to give the columns that have currency values the additional class "{'sorter':'currency'}". Also make sure you're including the plugin metadata, which tablesorter supports. This will pull in the per element options and explicitly tell tablesorter how to sort.

<link rel="stylesheet" href="/css/jquery/tablesorter/green/style.css" />
<script src="/js/jquery-1.3.2.js"></script>
<script src="/js/jquery.ui.core.js"></script>
<script src="/js/jquery.metadata.js"></script>
<script src="/js/jquery.tablesorter.js"></script>

<script>
    $(document).ready(function()
    {
    $("#table").tablesorter();
    }
    );
    </script>
</head>
<table id="table" class="tablesorter">
<thead>
  <tr>
    <th class="{'sorter':'currency'}">Currency</th>
    <th>Integer</th>
    <th>String</th>
  </tr>
</thead>
<tbody>
<tr>
  <td class="{'sorter':'currency'}">$3</td>
  <td>3</td>
  <td>three</td>
</tr>
<tr>
  <td class="{'sorter':'currency'}">-$3</td>
  <td>-3</td>
  <td>negative three</td>
</tr>
<tr>
  <td class="{'sorter':'currency'}">$1</td>
  <td>1</td>
  <td>one</td>
</tr>
</tbody>
</table>

Also, there's a bug in the function to format currency: it doesn't handle negative numbers.

I've filed a bug, and am working on landing a patch.

The second option is to apply this fix to your copy of tablesorter. Once you've applied the fix, you won't need to specify the currency sorter in the th or td's(specifying in the td's is over-kill anyway).

Edit line 724 of jquery.tablesorter.js:

return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));

change to:

return $.tablesorter.formatFloat(s.replace(new RegExp(/[^-0-9.]/g),""));

case:

  • values: $-3,$1,$3

  • current asc order: $1,$3,$-3

  • expected asc order $-3,$1,$3

case:

  • values: -$3,$1,$3

  • current asc order: $1,$3,-$3

  • expected asc order $-3,$1,$3

antony.trupe
I do not work with regex's at all, so I'm not positive my solution is the most correct one; I just know the current code does not handle negative currency at all.
antony.trupe
Nice writeup. I ended up using some jQuery to add the sorter metadata for my custom parser based on the slug of the header field name.
Tim