Sorting table rows according to table header column using javascript or jquery
Solution 1
You might want to see this page:
http://blog.niklasottosson.com/?p=1914
I guess you can go something like this:
DEMO:http://jsfiddle.net/g9eL6768/2/
HTML:
<table id="mytable"><thead>
<tr>
<th id="sl">S.L.</th>
<th id="nm">name</th>
</tr>
....
JS:
// sortTable(f,n)
// f : 1 ascending order, -1 descending order
// n : n-th child(<td>) of <tr>
function sortTable(f,n){
var rows = $('#mytable tbody tr').get();
rows.sort(function(a, b) {
var A = getVal(a);
var B = getVal(b);
if(A < B) {
return -1*f;
}
if(A > B) {
return 1*f;
}
return 0;
});
function getVal(elm){
var v = $(elm).children('td').eq(n).text().toUpperCase();
if($.isNumeric(v)){
v = parseInt(v,10);
}
return v;
}
$.each(rows, function(index, row) {
$('#mytable').children('tbody').append(row);
});
}
var f_sl = 1; // flag to toggle the sorting order
var f_nm = 1; // flag to toggle the sorting order
$("#sl").click(function(){
f_sl *= -1; // toggle the sorting order
var n = $(this).prevAll().length;
sortTable(f_sl,n);
});
$("#nm").click(function(){
f_nm *= -1; // toggle the sorting order
var n = $(this).prevAll().length;
sortTable(f_nm,n);
});
Hope this helps.
Solution 2
use Javascript sort() function
var $tbody = $('table tbody');
$tbody.find('tr').sort(function(a,b){
var tda = $(a).find('td:eq(1)').text(); // can replace 1 with the column you want to sort on
var tdb = $(b).find('td:eq(1)').text(); // this will sort on the second column
// if a < b return 1
return tda < tdb ? 1
// else if a > b return -1
: tda > tdb ? -1
// else they are equal - return 0
: 0;
}).appendTo($tbody);
If you want ascending you just have to reverse the > and <
Change the logic accordingly for you.
Solution 3
Offering an interactive sort handling multiple columns is nothing trivial.
Unless you want to write a good amount of code handling logic for multiple row clicks, editing and refreshing page content, managing sort algorithms for large tables… then you really are better off adopting a plug-in.
tablesorter, (with updates by Mottie) is my favorite. It’s easy to get going and very customizable. Just add the class tablesorter
to the table you want to sort, then invoke the tablesorter plugin in a document load event:
$(function(){
$("#myTable").tablesorter();
});
You can browse the documentation to learn about advanced features.
Solution 4
I think this might help you:
Here is the JSFiddle demo:
And here is the code:
var stIsIE = /*@cc_on!@*/ false;
sorttable = {
init: function() {
if (arguments.callee.done) return;
arguments.callee.done = true;
if (_timer) clearInterval(_timer);
if (!document.createElement || !document.getElementsByTagName) return;
sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
forEach(document.getElementsByTagName('table'), function(table) {
if (table.className.search(/\bsortable\b/) != -1) {
sorttable.makeSortable(table);
}
});
},
makeSortable: function(table) {
if (table.getElementsByTagName('thead').length == 0) {
the = document.createElement('thead');
the.appendChild(table.rows[0]);
table.insertBefore(the, table.firstChild);
}
if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
if (table.tHead.rows.length != 1) return;
sortbottomrows = [];
for (var i = 0; i < table.rows.length; i++) {
if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
sortbottomrows[sortbottomrows.length] = table.rows[i];
}
}
if (sortbottomrows) {
if (table.tFoot == null) {
tfo = document.createElement('tfoot');
table.appendChild(tfo);
}
for (var i = 0; i < sortbottomrows.length; i++) {
tfo.appendChild(sortbottomrows[i]);
}
delete sortbottomrows;
}
headrow = table.tHead.rows[0].cells;
for (var i = 0; i < headrow.length; i++) {
if (!headrow[i].className.match(/\bsorttable_nosort\b/)) {
mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
if (mtch) {
override = mtch[1];
}
if (mtch && typeof sorttable["sort_" + override] == 'function') {
headrow[i].sorttable_sortfunction = sorttable["sort_" + override];
} else {
headrow[i].sorttable_sortfunction = sorttable.guessType(table, i);
}
headrow[i].sorttable_columnindex = i;
headrow[i].sorttable_tbody = table.tBodies[0];
dean_addEvent(headrow[i], "click", sorttable.innerSortFunction = function(e) {
if (this.className.search(/\bsorttable_sorted\b/) != -1) {
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted',
'sorttable_sorted_reverse');
this.removeChild(document.getElementById('sorttable_sortfwdind'));
sortrevind = document.createElement('span');
sortrevind.id = "sorttable_sortrevind";
sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴';
this.appendChild(sortrevind);
return;
}
if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted_reverse',
'sorttable_sorted');
this.removeChild(document.getElementById('sorttable_sortrevind'));
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
this.appendChild(sortfwdind);
return;
}
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell) {
if (cell.nodeType == 1) {
cell.className = cell.className.replace('sorttable_sorted_reverse', '');
cell.className = cell.className.replace('sorttable_sorted', '');
}
});
sortfwdind = document.getElementById('sorttable_sortfwdind');
if (sortfwdind) {
sortfwdind.parentNode.removeChild(sortfwdind);
}
sortrevind = document.getElementById('sorttable_sortrevind');
if (sortrevind) {
sortrevind.parentNode.removeChild(sortrevind);
}
this.className += ' sorttable_sorted';
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
this.appendChild(sortfwdind);
row_array = [];
col = this.sorttable_columnindex;
rows = this.sorttable_tbody.rows;
for (var j = 0; j < rows.length; j++) {
row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
}
row_array.sort(this.sorttable_sortfunction);
tb = this.sorttable_tbody;
for (var j = 0; j < row_array.length; j++) {
tb.appendChild(row_array[j][1]);
}
delete row_array;
});
}
}
},
guessType: function(table, column) {
sortfn = sorttable.sort_alpha;
for (var i = 0; i < table.tBodies[0].rows.length; i++) {
text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
if (text != '') {
if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
return sorttable.sort_numeric;
}
possdate = text.match(sorttable.DATE_RE)
if (possdate) {
first = parseInt(possdate[1]);
second = parseInt(possdate[2]);
if (first > 12) {
return sorttable.sort_ddmm;
} else if (second > 12) {
return sorttable.sort_mmdd;
} else {
sortfn = sorttable.sort_ddmm;
}
}
}
}
return sortfn;
},
getInnerText: function(node) {
if (!node) return "";
hasInputs = (typeof node.getElementsByTagName == 'function') &&
node.getElementsByTagName('input').length;
if (node.getAttribute("sorttable_customkey") != null) {
return node.getAttribute("sorttable_customkey");
} else if (typeof node.textContent != 'undefined' && !hasInputs) {
return node.textContent.replace(/^\s+|\s+$/g, '');
} else if (typeof node.innerText != 'undefined' && !hasInputs) {
return node.innerText.replace(/^\s+|\s+$/g, '');
} else if (typeof node.text != 'undefined' && !hasInputs) {
return node.text.replace(/^\s+|\s+$/g, '');
} else {
switch (node.nodeType) {
case 3:
if (node.nodeName.toLowerCase() == 'input') {
return node.value.replace(/^\s+|\s+$/g, '');
}
case 4:
return node.nodeValue.replace(/^\s+|\s+$/g, '');
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += sorttable.getInnerText(node.childNodes[i]);
}
return innerText.replace(/^\s+|\s+$/g, '');
break;
default:
return '';
}
}
},
reverse: function(tbody) {
// reverse the rows in a tbody
newrows = [];
for (var i = 0; i < tbody.rows.length; i++) {
newrows[newrows.length] = tbody.rows[i];
}
for (var i = newrows.length - 1; i >= 0; i--) {
tbody.appendChild(newrows[i]);
}
delete newrows;
},
sort_numeric: function(a, b) {
aa = parseFloat(a[0].replace(/[^0-9.-]/g, ''));
if (isNaN(aa)) aa = 0;
bb = parseFloat(b[0].replace(/[^0-9.-]/g, ''));
if (isNaN(bb)) bb = 0;
return aa - bb;
},
sort_alpha: function(a, b) {
if (a[0] == b[0]) return 0;
if (a[0] < b[0]) return -1;
return 1;
},
sort_ddmm: function(a, b) {
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3];
m = mtch[2];
d = mtch[1];
if (m.length == 1) m = '0' + m;
if (d.length == 1) d = '0' + d;
dt1 = y + m + d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3];
m = mtch[2];
d = mtch[1];
if (m.length == 1) m = '0' + m;
if (d.length == 1) d = '0' + d;
dt2 = y + m + d;
if (dt1 == dt2) return 0;
if (dt1 < dt2) return -1;
return 1;
},
sort_mmdd: function(a, b) {
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3];
d = mtch[2];
m = mtch[1];
if (m.length == 1) m = '0' + m;
if (d.length == 1) d = '0' + d;
dt1 = y + m + d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3];
d = mtch[2];
m = mtch[1];
if (m.length == 1) m = '0' + m;
if (d.length == 1) d = '0' + d;
dt2 = y + m + d;
if (dt1 == dt2) return 0;
if (dt1 < dt2) return -1;
return 1;
},
shaker_sort: function(list, comp_func) {
var b = 0;
var t = list.length - 1;
var swap = true;
while (swap) {
swap = false;
for (var i = b; i < t; ++i) {
if (comp_func(list[i], list[i + 1]) > 0) {
var q = list[i];
list[i] = list[i + 1];
list[i + 1] = q;
swap = true;
}
}
t--;
if (!swap) break;
for (var i = t; i > b; --i) {
if (comp_func(list[i], list[i - 1]) < 0) {
var q = list[i];
list[i] = list[i - 1];
list[i - 1] = q;
swap = true;
}
}
b++;
}
}
}
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", sorttable.init, false);
}
/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
sorttable.init(); // call the onload handler
}
};
/*@end @*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
sorttable.init(); // call the onload handler
}
}, 10);
}
/* for other browsers */
window.onload = sorttable.init;
function dean_addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
if (!element.events) element.events = {};
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
handlers[handler.$$guid] = handler;
element["on" + type] = handleEvent;
}
};
dean_addEvent.guid = 1;
function removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else {
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
}
};
function handleEvent(event) {
var returnValue = true;
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
var handlers = this.events[event.type];
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
}
if (!Array.forEach) {
Array.forEach = function(array, block, context) {
for (var i = 0; i < array.length; i++) {
block.call(context, array[i], i, array);
}
};
}
Function.prototype.forEach = function(object, block, context) {
for (var key in object) {
if (typeof this.prototype[key] == "undefined") {
block.call(context, object[key], key, object);
}
}
};
String.forEach = function(string, block, context) {
Array.forEach(string.split(""), function(chr, index) {
block.call(context, chr, index, string);
});
};
var forEach = function(object, block, context) {
if (object) {
var resolve = Object;
if (object instanceof Function) {
resolve = Function;
} else if (object.forEach instanceof Function) {
object.forEach(block, context);
return;
} else if (typeof object == "string") {
resolve = String;
} else if (typeof object.length == "number") {
resolve = Array;
}
resolve.forEach(object, block, context);
}
}
table.sortable thead {
background-color: #eee;
color: #666666;
font-weight: bold;
cursor: default;
}
<table class="sortable">
<thead>
<tr>
<th>S.L.</th>
<th>name</th>
<th>Goal</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Ronaldo</td>
<td>120</td>
</tr>
<tr>
<td>2</td>
<td>Messi</td>
<td>66</td>
</tr>
<tr>
<td>3</td>
<td>Ribery</td>
<td>10</td>
</tr>
<tr>
<td>4</td>
<td>Bale</td>
<td>22</td>
</tr>
</tbody>
</table>
JS is used here without any other JQuery Plugin.
Related videos on Youtube
Comments
-
user3508453 over 3 years
I have something like this
<table> <thead> <tr> <th>S.L.</th> <th>name</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Ronaldo</td> </tr> <tr> <td>2</td> <td>Messi</td> </tr> <tr> <td>3</td> <td>Ribery</td> </tr> <tr> <td>4</td> <td>Bale</td> </tr> </tbody> </table>
What i want is to sort the
<tr>
of<tbody>
when clickedth
in ascending and descending order alternatively in according to the followingth
clicked.- so if some one clicks the
S.L
th
then it shows the table rows in descending and then ascending order alternatively at every click. - When clicked
Name
th
it should show the names in descending order and then ascending order without change in their respectiveS.L
here is fiddle
-
Bhavik almost 10 years
-
Ryan Brewer almost 10 years@Bhavik your "Working Fiddle" does not work.
-
Bhavik almost 10 years
-
user3508453 almost 10 yearscan u implement it in jquery using my solution coz i am little weak in javascript @Bhavik
-
Bhavik almost 10 years@user3508453
here you go
-
user3508453 almost 10 yearsi got it but my curiosity is how u did it ? canu explain in an answer ? coz i did not understood the functions u used. @Bhavik
-
Bhavik almost 10 yearsUpdated it with few comments.. jsfiddle.net/a2seK/6
-
user3508453 almost 10 yearsbut if we dont know the second parameter in your function
sort_table
i.e thenth child
how do we do it ? @Bhavik -
Dexygen over 5 yearsDo any of the solutions use memoization, that is, do they store their results so they can be used again? Thinking about it a little harder, this might require a full page refresh if table rows are added/edited/deleted. Another idea is to create the necessary additional data structure(s) and pre-sort the data.
- so if some one clicks the
-
user3508453 almost 10 yearswhy have u used
sortTable(variable,0)
&sortTable(variable,1)
? -
naota almost 10 years@user3508453, I appended explanation of parameter of
sortTable
on my answer above. On thesortTable(f,n)
,f
: 1 ascending order, -1 descending order , andn
: n-th child(<td>) of <tr> -
user3508453 almost 10 yearsif we are unknown about nth child how do we get the
n
oftd
? @naota -
naota almost 10 years@user3508453, thanks. Could you explain more about "unknown about nth"? What kind of case do you consider?
-
user3508453 almost 10 yearsi consider adding
table headers
unknown numbers of time as done ingoogle forms
then i dont know how many table headers my user creates..... -
user3508453 almost 10 yearsU almost solved it. But if i have
SL
in digits of tens or thousands or even more its causing a problem and mistake while ordering it. Suppose s.l are in range of 1-1000 then it would order it incorrectly. -
Kraang Prime over 8 yearsSorry to necro this, but there is a problem when sorting a numeric column as shown in this updated fiddle > jsfiddle.net/a2seK/567 <
-
Kraang Prime over 8 yearsThis one also fails to sort numerically properly > jsfiddle.net/8kp2vjm3/59
-
Kraang Prime over 8 yearsThis plugin works well unless the table has been modified at runtime. It doesn't take into account changes made to the cell contents. Even running .tablesorter() a second time after modification, it fails to see the new data.
-
naota about 8 years@SanuelJackson: Thank you for pointing me out the issue. I edited my code above. In the new code, each value is checked if it is Numeric or not.
-
Vishal about 7 yearsTo make is work numerically just update the code tda < tdb to +tda< +tdb and it will work > See updated fiddle >> jsfiddle.net/vishal_vash/8kp2vjm3/131
-
Severe Torture over 6 yearsThanks for great solution. It´s works well not only on tables, but on "tables makes via divs". +1
-
jouell over 5 yearswhere would that function() call go? It's not obvious.
-
kamalav about 5 yearsgreat solution ji
-
Muhammad Hafiz Hussin over 4 yearsI like this one. Solve my problem for decimal figures. I made it ascending and descending by changing the error. thanks SharmaPattar
-
Pradeep Kumar about 4 yearsnumbers with decimal gives wrong sorting order. example(for me): 8.67, 8.31, 8.59 – removing if($.isNumeric(v)){ v = parseInt(v,10); } fixed decimal sorting issue
-
Ynjxsjmh almost 4 yearsThe js code looks silimar with kryogenix.org/code/browser/sorttable/sorttable.js. For how to use it, visit kryogenix.org/code/browser/sorttable.