Search code examples
tablesorter

Incorrect sort order


I am using the tablesorter on a basic table. 2 table headers, the first column is ordering the following items as follows:

000
00
0
000
00
0
1
2
3
etc.

With other data, it is being sorted as:

0
1
10
11
12
2

I have tried adding the class to each th of "sorter-digits" and it made no difference. Also configured tablesorter with:

$("#myTable").tablesorter({
     sortList: [[1,0]],
     headers: {
          0: { sorter: "digit" }
          1: { sorter: "digit" }
       }
});

...but again, am getting the above results. Feels like i'm missing something obvious?


Solution

  • If you are using the original tablesorter (v2.0.5b), then you can use a custom parser. This parser isn't ideal since it gives the zeroes a negative decimal value to maintain your desired sort order. It shouldn't be a problem if your data does not include any negative numbers - demo.

    $(function() {
    
      $.tablesorter.addParser({
        id: 'zeros',
        is: function() {
          return false;
        },
        format: function(s, table) {
          var number = parseFloat(s);
          if (number === 0) {
            // add a negative decimal place to maintain sorting
            // using "5" assuming the max zero length is 5 ("00000")
            number = -1/(5 - s.length);
          }
          return number;
        },
        type: 'number'
      });
    
      $('table').tablesorter({
        headers: {
          0: { sorter: 'zeros' }
        }
      });
    
    });
    

    If you are using my fork of tablesorter, then you can add a custom textSorter to specifically handle zeros with different lengths - demo.

    $(function() {
    
      $('table').tablesorter({
        theme: 'blue',
        textSorter: {
          0: function(a, b, direction, columnIndex, table) {
            x = parseFloat(a);
            y = parseFloat(b);
            return x === 0 && y === 0 ?
                b.length - a.length : x - y;
          }
        }
      });
    });
    

    Update: For mixed content, instead of returning x - y, use the built-in sortNatural function - demo

    $(function() {
    
      $('table').tablesorter({
        theme: 'blue',
        textSorter: {
          0: function(a, b) {
            x = parseFloat(a);
            y = parseFloat(b);
            return x === 0 && y === 0 ?
              b.length - a.length :
              $.tablesorter.sortNatural(a, b);
          }
        }
      });
    });