JSFiddle - React, Tailwind, and code Playground
by Michael Prosser
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<table width="100%" border="0" cellspacing="0" cellpadding="5"><tbody class="task-data-headers"><tr><th>Name</th><th>Date</th><th>Time</th><th>Recurrence</th><th>Due Date</th><th>Facility</th><th>Owner</th><th>Description</th><th>Type</th><th>Service</th><th>Scope</th><th>Comments</th></tr></tbody><tbody class="task-data-rows"><tr title="Double-Click to edit this record" data-config-length="3" data-date="2023-10-03" data-task-id="1139" class="original completed" data-event-type="task"><td>New Task</td><td>2023-10-03</td><td>00:00:00</td><td>every-week</td><td>2023-10-24</td><td>Global</td><td>Michael Prosser</td><td></td><td>The cat</td><td>agPROACTIVE</td><td>Maintenance Forms</td><td></td></tr><tr title="Double-Click to edit this record" data-config-length="3" data-date="2023-11-07" data-task-id="1139" data-event-type="task"><td>New Task</td><td>2023-11-07</td><td>00:00:00</td><td>every-week</td><td>2023-11-28</td><td>Global</td><td>Michael Prosser</td><td></td><td>The cat</td><td>agPROACTIVE</td><td>Maintenance Forms</td><td></td></tr><tr title="Double-Click to edit this record" data-config-length="3" data-date="2023-11-14" data-task-id="1139" data-event-type="task"><td>New Task</td><td>2023-11-14</td><td>00:00:00</td><td>every-week</td><td>2023-12-05</td><td>Global</td><td>Michael Prosser</td><td></td><td>The cat</td><td>agPROACTIVE</td><td>Maintenance Forms</td><td></td></tr><tr title="Double-Click to edit this record" data-config-length="3" data-date="2023-11-21" data-task-id="1139" data-event-type="task"><td>New Task</td><td>2023-11-21</td><td>00:00:00</td><td>every-week</td><td>2023-12-12</td><td>Global</td><td>Michael Prosser</td><td></td><td>The cat</td><td>agPROACTIVE</td><td>Maintenance Forms</td><td></td></tr><tr title="Double-Click to edit this record" data-config-length="3" data-date="2023-11-28" data-task-id="1139" data-event-type="task"><td>New...
CSS
table{
font-family: helvetica;
}
table th {
font-size: 12px;
font-weight: bold;
color: #000;
background-color: #FFF;
text-align: left;
}
table>tbody>tr>th {
background-color: #356DB0 !important;
color: #ffffff !important;
white-space: nowrap;
}
table>tbody>tr>th[data-sort-order="ASC"]:after{
content: "";
display: inline-block;
width: 0;
height: 0;
border-style: solid;
border-width: 5px 5px 0 5px;
border-color: #ffffff transparent transparent transparent;
margin-left: 5px;
vertical-align: middle;
white-space: nowrap;
}
table>tbody>tr>th[data-sort-order="DESC"]:after{
content: "";
display: inline-block;
width: 0;
height: 0;
border-style: solid;
border-width: 0 5px 5px 5px;
border-color: transparent transparent #ffffff transparent;
margin-left: 5px;
vertical-align: middle;
white-space: nowrap;
}
table tbody.task-data-rows>tr>td {
background-color: #fff;
padding: 5px;
font-size: 12px;
width: auto;
border: solid 1px #eee;
height: auto !important;
vertical-align: top;
position: relative;
overflow: visible;
cursor: pointer;
}
JavaScript
function Sortable(headerTableBodyElement,contentTableBodyElement){
var t = this;
t.sortOrder = 'ASC';
t.sortColumn = '';
t.sortColumnIndex = -1;
headerTableBodyElement.find('th').attr('data-sort-order','');
headerTableBodyElement.find('th').click(function(){
headerTableBodyElement.find('th').attr('data-sort-order','');
if(t.sortColumnIndex == $(this).index()){
if(t.sortOrder == 'ASC'){
t.sortOrder = 'DESC';
} else {
t.sortOrder = 'ASC';
}
} else {
t.sortOrder = 'ASC';
t.sortColumn = $(this).text();
t.sortColumnIndex = $(this).index();
}
console.log(t);
headerTableBodyElement.find('th').eq(t.sortColumnIndex).attr('data-sort-order',t.sortOrder);
t.sort();
});
t.sort = function(){
// store original elements in an array for comparison
var tr = [];
var search = [];
contentTableBodyElement.find('tr').each(function(index){
tr.push({
element: $(this),
index: index
});
search.push({
value: $(this).find('td').eq(t.sortColumnIndex).text(),
element: $(this)
});
});
if(t.sortOrder == 'ASC'){
search.sort(function(a, b) {
var keyA = a.value,
keyB = b.value;
// Compare the 2 dates
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
});
} else {
search.sort(function(a, b) {
var keyA = a.value,
keyB = b.value;
// Compare the 2 dates
if (keyA < keyB) return -1;
if (keyA > keyB) return 1;
return 0;
}).reverse();
}
for(var i=0;i<search.length;i++){
search[i].detached = search[i].element.detach();
}
for(var i=0;i<search.length;i++){
contentTableBodyElement.append(search[i].detached);
}
...