Sorting the table on which the header cell was clicked
If I have the following:
<table>
<thead>
<tr>
<th><a href="Index.cfm?Sort=0">First</a></th>
<th><a href="Index.cfm?Sort=1">Second</a></th>
<th><a href="Index.cfm?Sort=2">Third</a></th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td class="num">123</td>
<td><input name="XYZ"></td>
</tr>
</tbody>
</table>
Q: How to sort the body of the table based on which the table header cell was clicked?
<script>
$('th a').click(function() {
var $this = $(this).closest('th');
console.log($this.index());
return false;
});
</script>
(I made each of the hyperlinked table header cells so that if the user has JavaScript disabled, it will follow the link and be sorted server side).
a source to share
function OrderBy(a,b,n) {
if (n) return a-b;
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
$('th a').click(function() {
var $th = $(this).closest('th');
$th.toggleClass('selected');
var isSelected = $th.hasClass('selected');
var isInput= $th.hasClass('input');
var column = $th.index();
var $table = $th.closest('table');
var isNum= $table.find('tbody > tr').children('td').eq(column).hasClass('num');
var rows = $table.find('tbody > tr').get();
rows.sort(function(rowA,rowB) {
if (isInput) {
var keyA = $(rowA).children('td').eq(column).children('input').val().toUpperCase();
var keyB = $(rowB).children('td').eq(column).children('input').val().toUpperCase();
} else {
var keyA = $(rowA).children('td').eq(column).text().toUpperCase();
var keyB = $(rowB).children('td').eq(column).text().toUpperCase();
}
if (isSelected) return OrderBy(keyA,keyB,isNum);
return OrderBy(keyB,keyA,isNum);
});
$.each(rows, function(index,row) {
$table.children('tbody').append(row);
});
return false;
});
a source to share
/**
* This tidy function can sort your rows belonging to TBODY via an ID in your table
* The only thing it does is to sort a specific column in a ascending byte mode
* M.Rasch may 2010 xmlsoap.dk
*/
function sortColumn (id, colNo) {
var zTemp = [];
var rows = document.getElementById(id).getElementsByTagName('tbody')[0].getElementsByTagName('tr');
for(ix=0;ix<rows.length;ix++){
var column = rows[ix].getElementsByTagName('td')[colNo - 1]; // relative column offSet, one-based
zTemp[ix] = []; // prepare 2nd dimension
zTemp[ix][0] = column.innerHTML; // the "value" to sort ...
zTemp[ix][1] = rows[ix]; // and here goes complete row
}
zTemp.sort(function (elmA, elmB){
if (elmA[0] === elmB[0]) return 0;
return (elmA[0] < elmB[0]) ? -1 : 1;
}
);
for(ix=0;ix<rows.length;ix++){ // Remove row collection entirely
var temp = rows[ix].parentNode;
temp.removeChild(rows[ix]);
}
var tBody = document.getElementById(id).getElementsByTagName('tbody')[0];
for(ix=0;ix<zTemp.length;ix++){ // and re-insert them ...
tBody.appendChild(zTemp[ix][1]);
}
}
a source to share
This is not as direct as it seems.
First of all, you need to decide if you will be sorting alphanumeric or dates, numerical values, etc. Then you need to go through the data in each cell, add that to the array, sort the array, remove the tr from the table, and re-add it in the correct order.
As it happens, there is a very nice plugin that does this for you:
a source to share
Another JQuery plugin: http://datatables.net/
I believe it should be jQuery UI compatible.
Edit:
Custom sorting functions are supported.
http://datatables.net/plug-ins/sorting
a source to share
function Ascending(a,b) {
if (a < b) return -1;
if (a > b) return 1;
return 0;
}
$('th a').click(function() {
var $th = $(this).closest('th');
var column = $th.index(); // Todo: url.Sort
var $table = $th.closest('table');
var rows = $table.find('tbody > tr').get();
rows.sort(function(rowA,rowB) {
if (column == 2) {
var keyA = $(rowA).children('td').eq(column).children('input').val().toUpperCase();
var keyB = $(rowB).children('td').eq(column).children('input').val().toUpperCase();
} else {
var keyA = $(rowA).children('td').eq(column).text().toUpperCase();
var keyB = $(rowB).children('td').eq(column).text().toUpperCase();
}
return Ascending(keyA,keyB);
});
$.each(rows, function(index,row) {
$table.children('tbody').append(row);
});
return false;
});
a source to share