I am trying to dynamically sort a table with javascript/jQuery. The table rows have 2 attributes:
- deadline (unix timestamp)
- status (1 or 2)
The table needs to be sorted by status (status 1 on top, status 2 on the bottom), and then by deadline (ascending).
For example, the correct order of an example of rows would be:
<table id="todo_table">
<tbody>
<tr deadline="1633333333" status="1"></tr>
<tr deadline="1644444444" status="1"></tr>
<tr deadline="1611111111" status="2"></tr>
<tr deadline="1622222222" status="2"></tr>
</tbody>
</table>
However, due to rows being added and removed dynamically by javascript (or by deadlines or statusses being changed), I want to have a function that re-sorts the table after all these actions.
I was able to write (rather: find on the internet) a piece of code that sorts the table based on 1 attribute:
var $table= $('#todo_table');
var rows = $table.find('tr').get();
rows.sort(function(a, b) {
var keyA = $(a).attr('deadline');
var keyB = $(b).attr('deadline');
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
});
$.each(rows, function(index, row) {
console.log(row);
$table.children('tbody').append(row);
});
However, I cannot figure out how to sort by a second attribute at the same time (while preserving the sort on the other attribute).
Here’s my snippet:
function sort_table(){
var $table= $('#todo_table');
var rows = $table.find('tr').get();
rows.sort(function(a, b) {
var keyA = $(a).attr('deadline');
var keyB = $(b).attr('deadline');
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
});
$.each(rows, function(index, row) {
$table.children('tbody').append(row);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="todo_table">
<tbody>
<tr deadline="1622222222" status="2"><td>Todo 4</td></tr>
<tr deadline="1611111111" status="2"><td>Todo 3</td></tr>
<tr deadline="1644444444" status="1"><td>Todo 2</td></tr>
<tr deadline="1633333333" status="1"><td>Todo 1</td></tr>
</tbody>
</table>
<button onclick="sort_table()">SORT</button>
The end result should be that the rows in this snippet are sorted Todo 1 – Todo 2 – Todo 3 – Todo 4, but right now, because it only sorts on "deadline", the order is 3 – 4 – 1 – 2.
Any help would be greatly appreciated 🙂
2
Answers
You can sort by multiple attributes by chaining the sorting conditions. In this case, you want to sort by status first, and then by deadline. I’m not sure if this is the best way.
This solution produces the same result as Gihan’s answer, only using some builtin functions, like JQuery’s
sort
andempty
, along with modern browsers’localeCompare
to sort the strings, since it returns a value as expected bysort
anyways:While it works, I’d recommend using
data-* attributes
(e.g.data-deadline
insteaddeadline
) to make sure you’re not clashing with any standard HTML attribute.