Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Parser for jQuery Tablesorter

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.

like image 646
Tim Graham Avatar asked Jun 01 '09 13:06

Tim Graham


2 Answers

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

like image 195
antony.trupe Avatar answered Oct 23 '22 12:10

antony.trupe


I had a similar issue and discovered the textExtraction option which is recommended when your cells contain markup. However, it works perfectly well as a pre-format formatter!

$('table').tablesorter({
  textExtraction: function(s) {
    var text = $(s).text();
    if (text.charAt(0) === '$') {
      return text.replace(/[^0-9-.]/g, '');
    } else {
      return text;
    }
  }
});
like image 33
mcNux Avatar answered Oct 23 '22 11:10

mcNux