I've got a table with a large number of rows that is not suitable for paging. The rows in this table can be sorted by clicking a column header which triggers a client side sorting algoritm based on http://www.exforsys.com/tutorials/jquery/jquery-basic-alphabetical-sorting.html The function dynamically adds an "expando" property to each row, thereby caching the key pre-sort:
row.sortKey = $(row).children('td').eq(column).text().toUpperCase();
As you can see, the property values are simply set to the contents of the column that was clicked and they are discarded (nulled) once the sorting has finished. Performance is actually surprisingly good - but columns that contain more text appear to be slower to sort.
As the sorting is only done to make it easier for the user to find the row(s) that they are looking for I figured things could be speeded up by cropping the key values with substr(0,7) or something (eight chars should provide more than enough precision). However, I found that doing a substr() incurred more performance cost than it saved, and if anything it made sorting slower.
Does anyone know any (other) optimisations that can be applied to this method?
Here is a more complete example:
var rows = $table.find('tbody > tr').get();
$.each(rows, function(index, row) {
row.sortKey = $(row).children('td').eq(column).text().toUpperCase()
})
rows.sort(function(a, b) {
if (a.sortKey < b.sortKey) return -1
if (a.sortKey > b.sortKey) return 1
return 0
})
$.each(rows, function(index, row) {
$table.children('tbody').append(row)
row.sortKey = null
})
EDIT: Here is the final version of my code, incorporating many of the optimisations provided in the answers below:
$('table.sortable').each(function() {
var $table = $(this);
var storage = new Array();
var rows = $table.find('tbody > tr').get();
$('th', $table).each(function(column) {
$(this).click(function() {
var colIndex = this.cellIndex;
for(i=0;i<rows.length;i++) {
rows[i].sortKey = $(rows[i].childNodes[colIndex]).text().toUpperCase();
}
rows.sort(function(a, b) {
if (a.sortKey < b.sortKey) return -1;
if (a.sortKey > b.sortKey) return 1;
return 0;
});
for(i=0;i<rows.length;i++) {
storage.push(rows[i]);
rows[i].sortKey = null;
}
$table.children('tbody').append(storage);
});
});
});