Learning jQuery - Sorting Other Types of Data
Our sort routine should be able to handle not just the Title and Author columns, but the Publish Dates and Price as well. Since we streamlined our comparator function, it can handle all kinds of data, but the computed keys will need to be adjusted for other data types. For example, in the case of prices we need to strip off the leading $ character and parse the rest, then compare them:
Sample Code
var key = parseFloat($cell.text().replace(/^[^\d.]*/, ''))
row.sortKey = isNaN(key) ? 0 : key
Copyright exforsys.com
The result of parseFloat() needs to be checked, because if no number can be extracted from the text, NaN is returned, which can wreak havoc on .sort(). For the date cells, we can use the JavaScript Date object:
Sample Code
row.sortKey = Date.parse('1 ' + $cell.text())
Copyright exforsys.com
The dates in this table contain a month and year only; Date.parse() requires a fully‑specified date, so we prepend the string with 1. This provides a day to complement the month and year, and the combination is then converted into a timestamp, which can be sorted using our normal comparator.
We can apportion these expressions across separate functions, and call the appropriate one based on the class applied to the table header:
Sample Code
$.fn.alternateRowColors = function() {
$('tbody tr:odd', this).removeClass('even').addClass('odd')
$('tbody tr:even', this).removeClass('odd').addClass('even')
return this
}
$(document).ready(function() {
var alternateRowColors = function($table) {
$('tbody tr:odd', $table).removeClass('even').addClass('odd')
$('tbody tr:even', $table).removeClass('odd').addClass('even')
}
$('table.sortable').each(function() {
var $table = $(this)
$table.alternateRowColors($table)
$('th', $table).each(function(column) {
var findSortKey
if ($(this).is('.sort-alpha')) {
findSortKey = function($cell) {
return $cell.find('.sort-key').text().toUpperCase()
+ ' ' + $cell.text().toUpperCase()
}
}
else if ($(this).is('.sort-numeric')) {
findSortKey = function($cell) {
var key = parseFloat($cell.text().replace(/^[^\d.]*/, ''))
return isNaN(key) ? 0 : key
}
}
else if ($(this).is('.sort-date')) {
findSortKey = function($cell) {
return Date.parse('1 ' + $cell.text())
}
}
if (findSortKey) {
$(this).addClass('clickable').hover(function() {
$(this).addClass('hover')
}, function() {
$(this).removeClass('hover')
}).click(function() {
var rows = $table.find('tbody > tr').get()
$.each(rows, function(index, row) {
row.sortKey =
findSortKey($(row).children('td').eq(column))
})
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
})
$table.alternateRowColors($table)
})
}
})
})
})
Copyright exforsys.com
The findSortKey variable doubles as the function to calculate the key and a flag to indicate whether the column header is marked with a class making it sortable. We can now sort on date or price:
