Sorting a table with two header lines
My table structure looks like this:
This is my HTML:
<table id="jackpotwatch" style="width:700px;">
<thead>
<tr>
<th>Location</th>
<th colspan="2">Full Name</th>
<th>Amount</th>
</tr>
<tr >
<th>Asset</th>
<th>Patron ID</th>
<th>User</th>
<th>Date/Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>Salem</td>
<td colspan="2">Bob galvin</td>
<td>$3400</td>
</tr>
<tr>
<td>assert1</td>
<td>1148</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>chennai</td>
<td colspan="2">sally n safer</td>
<td>$400</td>
</tr>
<tr>
<td>sdfsdgt1</td>
<td>4747</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>Mazdgfdg</td>
<td colspan="2">afdagadg</td>
<td>789769</td>
</tr>
<tr>
<td>qwqeqe</td>
<td>47467</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>hurtyry</td>
<td colspan="2">afadfadg</td>
<td>$12000</td>
</tr>
<tr>
<td>afadsf</td>
<td>25426546</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
</tbody>
</table>
When I click on the Amount heading, the sorting amounts ($ 3400, $ 400, $ 12000) should be sorted, etc. Likewise, the Date / Time field must also be sorted based on value.
I used the Tablesorter plugin, but this plugin did not sort all the columns. It is not sorting the last column and the second row header in this table. I also used the Tinysort plugin, but it changes the table structure during sorting.
I cannot change the structure of the table, as this is the biggest requirement of our client. Please provide some guidance on this sorting issue which is very helpful to me.
Any custom sorting that we can apply suggests how I can do this.
source to share
Presumably, you want the two lines for each entry to remain grouped together, in which case the Tablesorter is not designed to do what you want. Tinysort might work, though, if you were willing to put each pair of lines on your own tbody
:
<table id="jackpotwatch" style="width:700px">
<thead>
<tr>
<th>Location</th>
<th colspan="2">Full Name</th>
<th>Amount</th>
</tr>
<tr >
<th>Asset</th>
<th>Patron ID</th>
<th>User</th>
<th>Date/Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>Salem</td>
<td colspan="2">Bob galvin</td>
<td>$3400</td>
</tr>
<tr>
<td>assert1</td>
<td>1148</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
</tbody>
<tbody>
<tr>
<td>chennai</td>
<td colspan="2">sally n safer</td>
<td>$400</td>
</tr>
<tr>
<td>sdfsdgt1</td>
<td>4747</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
</tbody>
...
</table>
Since Tinysort can apparently sort by any element, you must tell it to sort the elements tbody
instead of strings. Your script could do something like this, loosely based on the table example in the Tinysort docs:
$(document).ready(function() {
var aAsc = [];
$("#jackpotwatch>thead th").each(function(nr) {
$(this).click(function() {
aAsc[nr] = aAsc[nr] == 'asc' ? 'desc' : 'asc';
$("#jackpotwatch>tbody").tsort('td:eq(' + nr + ')', {order: aAsc[nr]});
});
});
});
It depends on the fact that the header lines have exactly the same number of cells as the lines of each tbody.
source to share
See Demo here.
I don't have a plugin for you, but for your specific situation, I came up with the following approach:
/**
* This approach assumes that records are always comprised of 2 rows. It is possible to make this configurable.
*/
;(function() {
//Get the table
var table = $("#jackpotwatch");
//Make head header in the THEAD sortable.
$("thead th", table).on("click", onSortableClicked);
//Handle the sortable clicked event.
function onSortableClicked(e) {
//Find the column position.
var c = -1, child = e.target;
while ((child = child.previousSibling) != null)
if (child.nodeType == 3) ++c;
//Find the row position.
var r = -1, child = e.target.parentNode;
while ((child = child.previousSibling) != null)
if (child.nodeType == 3) ++r;
var subject = $("tbody", table);
var replacement = sort(subject, r, c);
subject.replaceWith(replacement);
}
function sort(subject, r, c) {
var rows = $("tr", subject); //Get all the rows from the tbody.
var sorted = document.createElement("tbody");
var vals = [];
for (var i = 0; i < rows.length; i+=2) {
var record = [rows.get(i), rows.get(i+1)]; //Record is two rows.
var sub = record[r].children[c].innerText; //This is our sort subject.
vals.push({"sub": sub, "record": record});
}
vals.sort(compare);
for (var i = 0; i < vals.length; ++i) {
var val = vals[i];
sorted.appendChild(val.record[0]);
sorted.appendChild(val.record[1]);
}
return sorted;
}
function compare(a, b) {
var atext = a.sub.toLowerCase();
var btext = b.sub.toLowerCase();
return atext < btext ? -1 : atext > btext ? 1 : 0;
}
})();
This makes every item TH
in an item THEAD
sortable. It sorts it based on text, bottom, comparison.
It is hard-coded only to work with records that are 2 sets of rows, but can be extended to allow configuration of how many rows are in one record, or even output this automatically by counting how many rows are in THEAD
.
I used this in the following HTML:
<table id="jackpotwatch">
<thead>
<tr>
<th>Location</th>
<th colspan="2">Full Name</th>
<th>Amount</th>
</tr>
<tr>
<th>Asset</th>
<th>Patron ID</th>
<th>User</th>
<th>Date/Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>Salem</td>
<td colspan="2">Bob galvin</td>
<td>$3400</td>
</tr>
<tr>
<td>assert1</td>
<td>1148</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>chennai</td>
<td colspan="2">sally n safer</td>
<td>$400</td>
</tr>
<tr>
<td>sdfsdgt1</td>
<td>4747</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>Mazdgfdg</td>
<td colspan="2">afdagadg</td>
<td>789769</td>
</tr>
<tr>
<td>qwqeqe</td>
<td>47467</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
<tr>
<td>hurtyry</td>
<td colspan="2">afadfadg</td>
<td>$12000</td>
</tr>
<tr>
<td>afadsf</td>
<td>25426546</td>
<td>sjauser</td>
<td>11/12 10:39 AM</td>
</tr>
</tbody>
</table>
Make sure to place the script either after the HTML or in the prepared event handler:
$(document).ready(function() {
//Sorting code from above goes here.
});
source to share