简体   繁体   中英

Javascript/Thymeleaf table sort by date/time in format dd-MM-yyyy hh:MM:ss

I am working on a table that displays dates

[![enter image description here][1]][1]

I am fairly new to javascript in general, I am struggling to modify the JS I am using in order to make this sort function work correctly. Currently it isn't comparing the dates properly. I have followed W3's example for this code, but I cannot figure out how to tweak it properly in order to get dates comparing properly.

The HTML:

It is worth noting I have made this table for my question, however in my live version the table is using ThymeLeaf and has dynamic dates rather than hardcoded dates.

<table id="myTable">
<thead>
<tr>
    <th>Name</th>
    <th onclick="sortTable(0)">Date</th>
    <th>Status</th>

</tr>
</thead>
<tbody>
<tr>
    <td>OLR</td>
    <td>12-11-2018 03:11:14</td>
    <td>SUBMITTED</td>
</tr>
<tr>
    <td>AF</td>
    <td>12-11-2018 03:11:12</td>
    <td>SUBMITTED</td>
</tr>
<tr>
    <td>SAF</td>
    <td>12-11-2018 02:11:27</td>
    <td>COLLECTION_COMPLETE</td>
</tr>
<tr>
    <td>CTT</td>
    <td>15-11-2018 11:11:13</td>
    <td>UNSUBMITTED</td>
</tr>
<tr>
    <td>WP</td>
    <td>19-11-2018 02:11:36</td>
    <td>SUBMITTED</td>
</tr>
</tbody>

The JS:

function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("myTable");
switching = true;

dir = "asc";

while (switching) {
    switching = false;
    rows = table.rows;

    for (i = 1; i < (rows.length - 1); i++) {
        shouldSwitch = false;

        x = rows[i].getElementsByTagName("TD")[n];
        y = rows[i + 1].getElementsByTagName("TD")[n];

        if (dir == "asc") {
            if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
                shouldSwitch = true;
                break;
            }
        } else if (dir == "desc") {
            if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
                shouldSwitch = true;
                break;
            }
        }
    }
    if (shouldSwitch) {
        rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
        switching = true;
        switchcount ++;
    } else {
        if (switchcount == 0 && dir == "asc") {
            dir = "desc";
            switching = true;
        }
    }
  }
}

I have been working on this for about 8 hours so far today and I am really struggling. I have attempted to convert the elements to dates first before comparing but haven't been able to get it working.

Any help is appreciated.

After some help below progress has been made, however when I click the header to sort my table, a lot of the content disappears.

My new sort table function:

function sortTable() {

const dates = [...document
    .getElementById('myTable')
    .querySelectorAll('td')
]
    .filter(x => x.textContent.match(/\d{2}\-\d{2}\-\d{2}/))
    .map(x => {
        const [d, t] = x.textContent.trim().split(' ');
        const [day, month, yr] = d.split('-').map(Number);
        const [hr, min, sec] = t.split(':').map(Number);
        return new Date(yr, month - 1, day, hr, min, sec);
    });


const sorted = dates.sort((a, b) => {
    if (a > b) return 1;
    if (b > a) return -1;
    return 0;
});


const html = '<tr><id="timestamp">Last Updated</td></tr>' + sorted
    .map(date => {
        const yr = date.getFullYear();
        const month = date.getMonth() + 1;
        const day = date.getDate();
        const hr = date.getHours();
        const min = date.getMinutes();
        const sec = date.getSeconds();

        const dateString = `${day}-${month}-${yr} ${hr}:${min}:${sec}`;
        return `<tr><td>${dateString}</td></tr>`;
    })
    .join('');

document.getElementById('myTable').innerHTML = html;

}

There's plug-in for jQuery called DataTables which does that and whole lot of other things. Why would you invent your own bicycle?

To get very basic set of features (which includes sorting) you just need to do what DataTables front page suggests: point to jQuery, DataTables and its stylesheet in your header.

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.19/js/jquery.dataTables.min.js"></script>

Or, you may use local copies of those.

Then, you simply call

$(document).ready( function () {
    $('#myTable').DataTable();
} );

And let DataTables take care of the rest http://jsfiddle.net/1fvkp6L0/14/

First is getting the list of dates in a form we can actually sort , ie an array:

const dates = [...document
  .getElementById('id-of-the-table')
  .querySelectorAll('td')
]
.filter(x => x.textContent.match(/\d{2}\-\d{2}\-\d{2}/))
.map(x => {
  const [d, t] = x.textContent.trim().split(' ');
  const [day, month, yr] = d.split('-').map(Number);
  const [hr, min, sec] = t.split(':').map(Number);
  return new Date(yr, month - 1, day, hr, min, sec);
});

Now we can sort them based on the date value:

const sorted = dates.sort((a, b) => {
  if (a > b) return 1;
  if (b > a) return -1;
  return 0;
});

To switch descending/ascending, just reverse the conditional. Then use the sorted values to re-generate the table:

const html = sorted
.map(date => {
  const yr = date.getFullYear();
  const month = date.getMonth() + 1;
  // etc. etc.
  const datestring = `${day}-${month}-${yr} ${hr}:${min}:${sec}`;
  return `<tr><td>${datestring}</td></tr>`;
})
.join('');

document.getElementById('id-for-table').innerHTML = html;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM