Learning jQuery - Column Highlighting
It can be a nice user interface enhancement to visually remind the user of what has been done in the past. By highlighting the column that was most recently used for sorting, we can focus the user's attention on the part of the table that is most likely to be relevant. Fortunately, since we've already determined how to select the table cells in the column, applying a class to those cells is simple:
$table.find('td').removeClass('sorted') .filter(':nth-child(' + (column + 1) + ')').addClass('sorted');
%24table.find%28%27td%27%29.removeClass%28%27sorted%27%29%20%0A%0D%0A.filter%28%27%3Anth-child%28%27%20%2B%20%28column%20%2B%201%29%20%2B%20%27%29%27%29.addClass%28%27sorted%27%29%3B%20
Note that we have to add one to the column index we found earlier, since the :nth-child() selector is one-based rather than zero-based. With this code in place, we get a highlighted column after any sort operation:

Alternating Sort Directions
Our final sorting enhancement is to allow for both ascending and descending sort orders. When the user clicks on a column that is already sorted, we want to reverse the current sort order.
To reverse a sort, all we have to do is to invert the values returned by our comparator. We can do this with a simple variable:
if (a.sortKey < b.sortKey) return -newDirection; if (a.sortKey > b.sortKey) return newDirection;
if%20%28a.sortKey%20%3C%20b.sortKey%29%20return%20-newDirection%3B%20%0A%0D%0Aif%20%28a.sortKey%20%3E%20b.sortKey%29%20return%20newDirection%3B
If newDirection equals 1, then the sort will be the same as before. If it equals -1, the sort will be reversed. We can use classes to keep track of the current sort order of a column:
$.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. ]*/, '')); }; } 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 newDirection = 1; if ($(this).is('.sorted-asc')) { newDirection = -1; } 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 -newDirection; if (a.sortKey > b.sortKey) return newDirection; return 0; }); $. each(rows, function(index, row ) { $table.children('tbody').append(row); row.sortKey = null; }); $table.find('th').removeClass('sorted-asc') .removeClass('sorted-desc'); var $sortHead = $table.find('th').filter(' :nth-child(' + (column + 1) + ')'); if (newDirection == 1) { $sortHead.addClass('sorted-asc'); } else { $sortHead.addClass('sorted-desc'); } $table.find('td').removeClass('sorted') .filter(':nth-child(' + (column + 1) + ')') .addClass('sorted'); $table.alternateRowColors($table); }); } }); }); });
%24.fn.alternateRowColors%20%3D%20function%28%29%20%7B%20%0A%0D%0A%24%28%27tbody%20tr%3Aodd%27%2C%20this%29.removeClass%28%27even%27%29.addClass%28%27odd%27%29%3B%20%0A%0D%0A%24%28%27tbody%20tr%3Aeven%27%2C%20this%29.removeClass%28%27odd%27%29.addClass%28%27even%27%29%3B%20%0A%0D%0Areturn%20this%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%24%28document%29.ready%28function%28%29%20%7B%20%0A%0D%0Avar%20alternateRowColors%20%3D%20function%28%24table%29%20%7B%20%0A%0D%0A%24%28%27tbody%20tr%3Aodd%27%2C%20%24table%29.removeClass%28%27even%27%29.addClass%28%27odd%27%29%3B%20%0A%0D%0A%24%28%27tbody%20tr%3Aeven%27%2C%20%24table%29.removeClass%28%27odd%27%29.addClass%28%27even%27%29%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%24%28%27table.sortable%27%29.each%28function%28%29%20%7B%20%0A%0D%0Avar%20%24table%20%3D%20%24%28this%29%3B%20%0A%0D%0A%24table.alternateRowColors%28%24table%29%3B%20%0A%0D%0A%24%28%27th%27%2C%20%24table%29.each%28function%28column%29%20%7B%20%0A%0D%0Avar%20findSortKey%3B%20%0A%0D%0Aif%20%28%24%28this%29.is%28%27.sort-alpha%27%29%29%20%7B%20%0A%0D%0AfindSortKey%20%3D%20function%28%24cell%29%20%7B%20%0A%0D%0Areturn%20%24cell.find%28%27.sort-key%27%29.text%28%29.toUpperCase%28%29%20%2B%20%27%20%27%20%2B%20%0A%0D%0A%24cell.text%28%29.toUpperCase%28%29%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%7D%20%0A%0D%0Aelse%20if%20%28%24%28this%29.is%28%27.sort-numeric%27%29%29%20%7B%20%0A%0D%0AfindSortKey%20%3D%20function%28%24cell%29%20%7B%20%0A%0D%0Avar%20key%20%3D%20parseFloat%28%24cell.text%28%29.replace%28%2F%5E%5B%5E%5Cd.%5D%2A%2F%2C%20%27%27%29%29%3B%20%0A%0D%0Areturn%20isNaN%28key%29%20%3F%200%20%3A%20key%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%7D%20%0A%0D%0Aelse%20if%20%28%24%28this%29.is%28%27.sort-date%27%29%29%20%7B%20%0A%0D%0AfindSortKey%20%3D%20function%28%24cell%29%20%7B%20%0A%0D%0Areturn%20Date.parse%28%271%20%27%20%2B%20%24cell.text%28%29%29%3B%20%0A%0D%0A%7D%3B%20%0A%0D%0A%7D%20%0A%0D%0Aif%20%28findSortKey%29%20%7B%20%0A%0D%0A%24%28this%29.addClass%28%27clickable%27%29.hover%28function%28%29%20%7B%20%0A%0D%0A%24%28this%29.addClass%28%27hover%27%29%3B%20%0A%0D%0A%7D%2C%20function%28%29%20%7B%20%0A%0D%0A%24%28this%29.removeClass%28%27hover%27%29%3B%20%0A%0D%0A%7D%29.click%28function%28%29%20%7B%20%0A%0D%0A%2Bvar%20newDirection%20%3D%201%3B%0A%0D%0Aif%20%28%24%28this%29.is%28%27.sorted-asc%27%29%29%20%7B%20%0A%0D%0AnewDirection%20%3D%20-1%3B%20%0A%0D%0A%7D%20%0A%0D%0Avar%20rows%20%3D%20%24table.find%28%27tbody%20%3E%20tr%27%29.get%28%29%3B%0A%0D%0A%24.each%28rows%2C%20function%28index%2C%20row%29%20%7B%20%0A%0D%0Arow.sortKey%20%3D%20%0A%0D%0AfindSortKey%28%24%28row%29.children%28%27td%27%29.eq%28column%29%29%3B%20%0A%0D%0A%7D%29%3B%20%0A%0D%0Arows.sort%28function%28a%2C%20b%29%20%7B%20%0A%0D%0Aif%20%28a.sortKey%20%3C%20b.sortKey%29%20return%20-newDirection%3B%20%0A%0D%0Aif%20%28a.sortKey%20%3E%20b.sortKey%29%20return%20newDirection%3B%20%0A%0D%0Areturn%200%3B%20%0A%0D%0A%7D%29%3B%20%0A%0D%0A%24.each%28rows%2C%20function%28index%2C%20row%29%20%7B%20%0A%0D%0A%24table.children%28%27tbody%27%29.append%28row%29%3B%20%0A%0D%0Arow.sortKey%20%3D%20null%3B%20%0A%0D%0A%7D%29%3B%20%0A%0D%0A%24table.find%28%27th%27%29.removeClass%28%27sorted-asc%27%29%20%0A%0D%0A.removeClass%28%27sorted-desc%27%29%3B%20%0A%0D%0Avar%20%24sortHead%20%3D%20%24table.find%28%27th%27%29.filter%28%27%20%0A%0D%0A%3Anth-child%28%27%20%2B%20%28column%20%2B%201%29%20%2B%20%27%29%27%29%3B%20%0A%0D%0Aif%20%28newDirection%20%3D%3D%201%29%20%7B%20%0A%0D%0A%24sortHead.addClass%28%27sorted-asc%27%29%3B%20%0A%0D%0A%7D%20else%20%7B%20%0A%0D%0A%24sortHead.addClass%28%27sorted-desc%27%29%3B%20%0A%0D%0A%7D%20%0A%0D%0A%24table.find%28%27td%27%29.removeClass%28%27sorted%27%29%20%0A%0D%0A.filter%28%27%3Anth-child%28%27%20%2B%20%28column%20%2B%201%29%20%2B%20%27%29%27%29%20%0A%0D%0A.addClass%28%27sorted%27%29%3B%20%0A%0D%0A%24table.alternateRowColors%28%24table%29%3B%20%0A%0D%0A%7D%29%3B%20%0A%0D%0A%7D%20%0A%0D%0A%7D%29%3B%20%0A%0D%0A%7D%29%3B%20%0A%0D%0A%7D%29%3B
As a side benefit, since we use classes to store the sort direction we can style the columns headers to indicate the current order as well:

Trackback(0)
|