JokerMartini
JokerMartini

Reputation: 6147

Implement numerical sorting for html table?

Could someone help me modify this code to support numerical sorting. Currently it only supports sorting alphabetically and I'm not a js writer myself, i found this online. I only need it to sort numerical, not alphabetical.

bonus: would it be possible to make it support numbers and strings

Here is the working link of it sorting alphabetical. jsfiddle.net

Thank you.

function sortTable(table, col, reverse) {
    var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
        tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
        i;
    reverse = -((+reverse) || -1);
    tr = tr.sort(function (a, b) { // sort rows
        return reverse // `-1 *` if want opposite order
            * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
                .localeCompare(b.cells[col].textContent.trim())
               );
    });
    for(i = 0; i < tr.length; ++i) tb.appendChild(tr[i]); // append each row in order
}

function makeSortable(table) {
    var th = table.tHead, i;
    th && (th = th.rows[0]) && (th = th.cells);
    if (th) i = th.length;
    else return; // if no `<thead>` then do nothing
    while (--i >= 0) (function (i) {
        var dir = 1;
        th[i].addEventListener('click', function () {sortTable(table, i, (dir = 1 - dir))});
    }(i));
}

function makeAllSortable(parent) {
    parent = parent || document.body;
    var t = parent.getElementsByTagName('table'), i = t.length;
    while (--i >= 0) makeSortable(t[i]);
}

window.onload = function () {makeAllSortable();};

Upvotes: 3

Views: 4893

Answers (3)

6502
6502

Reputation: 114481

You should change the comparison code to

return reverse * ((+a.cells[col].textContent) - (+b.cells[col].textContent))

the unary + in Javascript can be used to convert a string to its numeric value.

Sorting a single column that can contain both numbers and non-numbers is trickier because you need to establish a transitive sorting criteria... for example:

  • all number-like strings come before other strings
  • number-like strings are sorted according to numeric value
  • other strings are sorted alphabetically

in code:

function xcmp(a, b) {
    if (isNan(a)) {
       if (isNan(b)) {
           return a.localeCompare(b);
       } else {
           return +1; // a non-numeric, b numeric: a > b
       }
    } else {
       if (isNan(b)) {
           return -1; // a numeric, b non-numeric: a < b
       } else {
           return a - b;
       }
    }
}

Simpler criteria like "compare them as numbers if both are numbers and as strings otherwise" don't work well because

  • "2" < "10"
  • "10" < "10a"
  • "10a" < "2"

i.e. you can create logical "loops" for which the very concept of sorting doesn't make sense.

Upvotes: 1

Man Programmer
Man Programmer

Reputation: 5356

This is working in both string and numbers

if(!isNaN(a.cells[col].textContent) && !isNaN(b.cells[col].textContent))
        return reverse * ((+a.cells[col].textContent) - (+b.cells[col].textContent))
       return reverse // `-1 *` if want opposite order
            * (a.cells[col].textContent.trim() // using `.textContent.trim()` for test
                .localeCompare(b.cells[col].textContent.trim())
               );

https://jsfiddle.net/oqr0mjc6/3/

Upvotes: 3

Jkike
Jkike

Reputation: 805

In your sort function you can try to transform the a.cells[col].textContent.trim() into a number. If it is not a number you compare it lexiografically, otherwise you compare the numbers

Upvotes: 0

Related Questions