So, I am trying to add a countdown timer on a table that gets the value of the due date and adds a cell showing the remaining time. Currently, it works with one record but on adding two or more rows, I get a replica of the last row timer duplicating on all the records' timer cells
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> <sup><span class="badge badge-warning"> {{ new}} New</span></sup>New Orders From Clients
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<td>Reference Code</td>
<td>Title</td>
<td>Number of Pages</td>
<td>Take this Task</td>
<td>Due Date</td>
<td>Remaining Time</td>
</thead>
{% for t in order %}
<tbody>
<tr>
<td>
<a href="{% url 'view_order' pk=t.pk %}">{{ t.urlhash }}</a>
</td>
<td>{{ t.title }}</td>
<td>{{ t.Number_of_pages }}</td>
<td>
{% if t.status == False %}
<a href="{% url 'claim' pk=t.pk %}" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm">Take order</a>{% else %}
<span>✔ Taken</span> {% endif %}
</td>
<td>{{ t.due_date }} </td>
<td id="time" class="text-warning"></td>
</tr>
<script>
// Set the date we're counting down to
var countDownDate = new Date("{{ t.due_date.isoformat }}").getTime();
// console.log(dex);
//var countDownDate = new Date("July 18, 2020 19:27:25").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get today's date and time
var now = new Date().getTime();
// Find the distance between now and the count down date
var distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="time"
document.getElementById("time").innerHTML = "Remaining time " + days + " Days " + hours + " hours " + minutes + " minutes " + seconds + "s ";
// If the count down is finished, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("time").innerHTML = "EXPIRED";
}
}, 1000);
</script>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
the aboe code works well with one record but on adding two or more only the first row shows the timer with the others as empty.If i make the css dynamic and unique across each row by giving the reference code it replicates across each row as one timer
I don't understand what's the problem.
This isn't really a DataTables question but it was fun so this is what I worked up:
(() => {
setInterval(() => {
const table = document.getElementById("dataTable")
for (var i = 0, row; row = table.rows[i]; i++) {
const dueDate = row.querySelector('.due-date')
if (dueDate) {
const dateBits = dueDate.innerHTML.split('/')
const dateDue = new Date(dateBits[2], dateBits[1], dateBits[0]).getTime()
const now = new Date().getTime()
const distance = dateDue - now
const countDownDate = row.querySelector('.text-warning')
if (distance < 0) {
countDownDate.innerHTML = 'EXPIRED'
} else {
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
countDownDate.innerHTML = `Remaining time ${days} Days ${hours} hours ${minutes} minutes ${seconds}s`
}
}
}
}, 1000)
})()
What we're doing here is grabbing the table every second, iterating through the table rows and checking to see if there's the appropriate cell called due-date
. If there is then we check the distance, if it's negative then we set the cell with the class text-warning
to be EXPIRED otherwise, we add the appropriate message. I hope that helps? Working JSFiddle here.