Juris Juris - 13 days ago 6
jQuery Question

How to sort table rows when cells contain nested tables?

I am using this jQuery code to add sorting (changing order based on values in a column) functionality to tables:

$('th.sortBy').click(function(){
var table = $(this).parents('table').eq(0);
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
this.asc = !this.asc;
if (!this.asc){rows = rows.reverse()};
for (var i = 0; i < rows.length; i++){table.append(rows[i])};
});

function comparer(index) {
return function(a, b) {
var valA = getCellValue(a, index), valB = getCellValue(b, index);
return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB);
};
};

function getCellValue(row, index){ return $(row).children('td').eq(index).html(); };


However, on a table where cells contain another table, the sorting breaks all - it takes all of the table rows including the nested and reorders them all. I, of course, need the nested rows to stay within their tables and not get sorted on another, unrelated level.

What should I do to fix this behaviour?

I tried to change

var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));


to

var rows = table.children('tr:gt(0)').toArray().sort(comparer($(this).index()));


but it still selects and orders all of the rows, including nested ones.

Answer

The problem is that .find is getting ALL tr in the rows var (except the very first, because of :gt(0)), even those in a nested table.

The only thing I can suggest, based on that examble, is to use a class on the second level trs...
So you can filter them using .not().

$('th.sortByOK').click(function(){
    var table = $(this).parents('table').eq(0);
    var rows = table.find("tr:gt(0)").not(".secondLevel").toArray().sort(comparer($(this).index()));
    this.asc = !this.asc;
    if (!this.asc){rows = rows.reverse()};
    for (var i = 0; i < rows.length; i++){table.append(rows[i])};
});

CodePen
Hoping it helps.