Stefanvds Stefanvds - 1 month ago 8
Javascript Question

Sort a table fast by its first column with Javascript or jQuery

I have a table which is dynamically populated from

FullCalendar
.
The problem is that
FullCalendar
does not care about its original order.

The table looks like this:

<table id="caltbl">
<thead>
<tr> <th> </th> <th> Date </th> <th> hours </th> ... </tr>
</thead>
<tbody>
<tr> <td class="sortnr">1</td> <td></td> ... </tr>
<tr> <td class="sortnr">3</td> <td></td> ... </tr>
<tr> <td class="sortnr">2</td> <td></td> ... </tr>
<tr> <td class="sortnr">4</td> <td></td> ... </tr>
</tbody>
</table>


The first of each row contains the number on which the table should be sorted.

I had this code to sort it:

var rows = $('#caltbl > tbody').children('tr').detach();

for (var counter = 1; counter<=rows.length; counter++) {
$(rows).each(function(index) {
if ($(this).find(".sortnr").text()==counter){
$('#caltbl > tbody:last').append($(this));
}
});
}


This works fine in Firefox but causes me a major headache in Internet Explorer because there are more than 500 items and it hangs. I could add a
setTimeout
but that would not fix the real problem. The sorting is slow. What is a faster way to sort this?

Instead of having to start from the
<table>
html, as I said it gets populated dynamically so I have an
Array
which contains the html. 1 item per
<tr>
(unsorted)

Answer

Fiddle: http://jsfiddle.net/qNwDe/

I've written an efficient, cross-browser method to sort the rows in your table. Multiple JQuery selectors in double loops are causing serious performance issues (as you've noticed), hence I've get rid of JQuery.

An additional advantage of my function is that it doesn't mind missing index numbers. I'm currently referring to the first cell of each row, rather than getting the element by class name. If you want to refer by classname, I will alter my function:

function sortTable(){
    var tbl = document.getElementById("caltbl").tBodies[0];
    var store = [];
    for(var i=0, len=tbl.rows.length; i<len; i++){
        var row = tbl.rows[i];
        var sortnr = parseFloat(row.cells[0].textContent || row.cells[0].innerText);
        if(!isNaN(sortnr)) store.push([sortnr, row]);
    }
    store.sort(function(x,y){
        return x[0] - y[0];
    });
    for(var i=0, len=store.length; i<len; i++){
        tbl.appendChild(store[i][1]);
    }
    store = null;
}

Call sortTable() whenever you want to sort the table.