Dynamic JavaScript time counter - javascript

I'm trying to make a dynamic time counter/timer in JavaScript.
Why dynamic? Well I would like to display days/hours/minutes/seconds if the time stamp is bigger enough to display days or hours and so on.
In case the timestamp is less than a day I would like that the script dynamically displays only the hours.
1D 0H 59M 59S
23H 59M 59S
59M 59S
59S
MESSAGE
Here is the code I try to make it work.
<center>
<script>
var countDownDate = new Date("2017-11-17T20:10:30Z").getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
// Seconds
if (distance < 1000){
document.getElementById("count1").innerHTML = seconds + "s ";
}
// Minutes
if (distance < 60000){
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("count1").innerHTML = minutes + "m " + seconds + "s ";
}
// Hours
if (distance < 3600000){
var hours = Math.floor(distance / (1000 * 60 * 60 * 1));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
document.getElementById("count1").innerHTML = hours + "h " + minutes + "m " + seconds + "s ";
}
// Days
if(distance > 3600001){
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);
document.getElementById("count1").innerHTML = days + "d " + hours + "h " + minutes + "m " $
}
if (distance < 0) {
clearInterval(x);
document.getElementById("count1").innerHTML = "You will be redirected now";
}
}, 1000);
</script>
<p id="count1"></p>
</center>
I think that my problem is related with math confusion in milliseconds but I can't find out what is wrong.

These changes made it work for me:
<center>
<script>
var countDownDate = new Date("2017-11-17T21:30:30Z").getTime();
var x = setInterval(function () {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
// Seconds
if (distance <= 60000) {
document.getElementById("count1").innerHTML = seconds + "s ";
}
// Minutes
else if (distance <= 3600000) {
document.getElementById("count1").innerHTML = minutes + "m " + seconds + "s ";
}
// Hours
else if (distance <= 86400000) {
document.getElementById("count1").innerHTML = hours + "h " + minutes + "m " + seconds + "s ";
}
// Days
else if (distance > 86400000) {
document.getElementById("count1").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
if (distance < 0) {
clearInterval(x);
document.getElementById("count1").innerHTML = "You will be redirected now";
}
}, 1000);
</script>
<p id="count1"></p>
I changed the milliseconds accordingly, and in your days you had a "$" so i changed that.
I changed the date around and got the effect I think you were going for.

It looks like you're doing this the absolute hardest way possible, and also reinventing the wheel. There are a lot of great references to built in javascript functions (like MDN) that you should really take a look at.
If you're doing this as an intellectual exercise think about restructuring your code into something like this (obviously just psuedocode):
let dateHTML = "";
if (time1.seconds - time2.seconds > 0) {
dateHTML = (time1.seconds - time2.seconds) + "s";
}
if (time1.minutes-time2.minutes > 0) {
dateHTML = (time1.minutes-time2.minutes) + "m " + dateHTML;
}
//So on and so forth for the maximum interval you want to account for.
document.getElementById("count1").innerHTML = dateHTML;
You can probably get really clever with null operators, putting the time unit distances into an array to clean up the syntax and avoid doing calculations twice etc. but this should cut down on what you're doing significantly.
Do keep in mind that there are JS libraries built to do this exact sort of thing really well, so if you're working on a "real" project consider that.

Here is the whole script in working order in case somebody else need it:
The whole script is meant to be reused multiply times in a single page by changing the ID in the $FD['id'] array variable and copy pasting the function that prints/echoing the function content.
PHP FUNCTION INCLUDE FILE (count.php):
<?php
// JS Date format
// 2017-11-14T12:00:00Z
function counter($FD){
$date=$FD['date'];
$id=$FD['id'];
$display_start_1=$FD['display_start_1'];
$display_start_2=$FD['display_start_2'];
$display_end=$FD['display_end'];
echo $counter=<<<a
<center>
<script>
var countDownDate$id = new Date("$date").getTime();
var x$id = setInterval(function () {
var now$id = new Date().getTime();
var distance$id = countDownDate$id - now$id;
var days$id = Math.floor(distance$id / (1000 * 60 * 60 * 24));
var hours$id = Math.floor((distance$id % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes$id = Math.floor((distance$id % (1000 * 60 * 60)) / (1000 * 60));
var seconds$id = Math.floor((distance$id % (1000 * 60)) / 1000);
// Seconds
if (distance$id <= 60000) {
document.getElementById("count$id").innerHTML ="$display_start_1 " + seconds$id + "s " + " $display_start_2";
}
// Minutes
else if (distance$id <= 3600000) {
document.getElementById("count$id").innerHTML ="$display_start " + minutes$id + "m " + seconds$id + "s " + " $display_start_2";
}
// Hours
else if (distance$id <= 86400000) {
document.getElementById("count$id").innerHTML ="$display_start_1 " + hours$id + "h " + minutes$id + "m " + seconds$id + "s " + " $display_start_2";
}
// Days
else if (distance$id > 86400000) {
document.getElementById("count$id").innerHTML ="$display_start_1 " + days$id + "d " + hours$id + "h " + minutes$id + "m " + seconds$id + "s " + " $display_start_2";
}
if (distance$id < 0) {
clearInterval(x$id);
document.getElementById("count$id").innerHTML = "$display_end";
}
}, 1000);
</script>
<p id="count$id"></p>
a;
}
?>
PHP DISPLAY FILE (count_display.php):
<?php
$now = time();
// Simulation of utc time (-1 hour +1 minute)
// By modifying the amount of seconds you set/define the amount of seconds that will counted down
$timestamp_new=$now-3600+10;
// Time formattig for JavaScript code
$date_new=date('Y-m-d\TH:i:s\Z', $timestamp_new);
// Include the function file once only
include'count.php';
// Define variables for the first counter
$FD1['date']="$date_new";
$FD1['id']='1';
$FD1['display_start_1']="Please wait for another:<br >";
$FD1['display_start_2']="<br />We are preparing your playground for you.";
$FD1['display_end']="Your Playground is ready at:<br /><a href='http://555.555.555.555'>Game server 01</a>";
counter($FD1);
// Define variables for the second counter
$timestamp_new=$now-3600+15;
$date_new=date('Y-m-d\TH:i:s\Z', $timestamp_new);
// The second count down timer
$FD2['date']="$date_new";
$FD2['id']='2';
$FD2['display_start_1']="Please wait for another:<br >";
$FD2['display_start_2']="<br />We are preparing your playground for you.";
$FD2['display_end']="Your Playground is ready at:<br /><a href='http://100.100.100.100'>Game server 02</a>";
counter($FD2);
// And so on ....
?>
Hoping that this will save a lot of time to somebody else ;)
Have a great life (you who can and know how) ;)

Related

Check if the time distance is between different times

I made a countdown using javascript and php from my functions the countdown works but now I want to have 3 options:
if the countdown is longer than 24 hours show te selector.next(".countdown").html(expiry); date
if the countdown is 6 hours or less show the timer selector.next(".countdown").html(days + "d " + hours + "h " + minutes + "m " + seconds + "s ");
else the countdown is less than 0 show that the endend selector.next(".countdown").html(<p>Closed</p>);
$(".expiry").each(function() {
var expiry = new Date($(this).text());
var selector = $(this)
var x = setInterval(function() {
var currentDateObj = new Date();
var numberOfMlSeconds = currentDateObj.getTime();
var addMlSeconds = 60 * 60 * 1000;
var now = new Date(numberOfMlSeconds - addMlSeconds);
var distance = expiry - now;
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);
if( distance >= 86400000 && distance < 21600000){
selector.next(".countdown").html(expiry);
}else if ( distance <= 21600000 && distance > 0){
selector.next(".countdown").html(days + "d " + hours + "h " + minutes + "m " + seconds + "s ");
}else{
selector.next(".countdown").html('<p>error</p>');
}
}, 1000);
});
Is the first line of your IF statement correct? Are you wanting to check if it's between those 2 numbers? If so, should the condition not be:
if(distance <= 86400000 && distance > 21600000)
I.E. If the distance is LESS THAN OR EQUAL TO 86400000 AND GREATER THAN 21600000
At the moment you're checking if distance is both GREATER THAN OR EQUAL TO 86400000 and LESS THAN 21600000 which will always produce false
EDIT
See full if statement block with condition for GREATER THAN 86400000
if (distance > 86400000) {
selector.next(".countdown").html('<p>A LOOOOOONG Way off expiring</p>');
}
else if (distance <= 864000000 && distance > 432000000) {
selector.next(".countdown").html(expiry);
}
else if (distance <= 432000000 && distance > 0) {
selector.next(".countdown").html(days + "d " + hours + "h " + minutes + "m " + seconds + "s ");
}
else if (distance < 0) {
selector.next(".countdown").html('<p>afgelopen</p>');
}
else {
selector.next(".countdown").html('<p>Error</p>');
}

Countdown timer in Javascript shows the old data too after new data is entered

So here I am writing a countdown timer with HTML and Javascript. But I am having an issue with it. It looks like it doesn't ''forget'' the old input data and shows both old and new almost at the same time after I click the Calculate button.
My code seems to work but the problem is that when I enter a new date it shows both old and new timer. For example, if I enter December 7, 2020 it will show 1 day (some minutes and seconds, whatever) and after that if I enter December 8, 2020 within each second it shows 2 days and then it suddenly changes to 1 day then changes to 2 days etc. If I enter another date it will quickly show all three timers. how do I fix this?
I thought that the old information was left and I tried adding a statement to clear the "res" part but it still does the same. I don't know what is the reason.
function calculate() {
var until_date = new Date(document.getElementById("input_date").value).getTime();
var x = setInterval(function() {
var today = new Date().getTime();
var d = until_date - today;
var days = Math.floor(d / (1000 * 60 * 60 * 24));
var hr = Math.floor((d % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var min = Math.floor((d % (1000 * 60 * 60)) / (1000 * 60));
var sec = Math.floor((d % (1000 * 60)) / 1000);
document.getElementById("res").innerHTML = days + "d " + hr + "h " + min + "m " + sec + "s ";
if (d < 0) {
clearInterval(x);
document.getElementById("res").innerHTML = "DONE";
}
}, 1000);
}
<p>Please select a date: <input id="input_date" type="date"></p>
<button id='calulate' onclick="calculate()">Calculate</button>
<p id="res"></p>
Just put the interval variable outside the function and clear the interval when the function is called again outside the loop.
Otherwise each function call you will be creating a new interval which will run parallel to the previous one.
var x;
function calculate() {
clearInterval(x);
var until_date = new Date(document.getElementById("input_date").value).getTime();
x = setInterval(function () {
var today = new Date().getTime();
var d = until_date - today;
var days = Math.floor(d / (1000 * 60 * 60 * 24));
var hr = Math.floor((d % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var min = Math.floor((d % (1000 * 60 * 60)) / (1000 * 60));
var sec = Math.floor((d % (1000 * 60)) / 1000);
document.getElementById("res").innerHTML = days + "d " + hr + "h " + min + "m " + sec + "s ";
if (d < 0) {
clearInterval(x);
document.getElementById("res").innerHTML = "DONE";
}
}, 1000);
}

How can i make this countdown work for other timezones?

Im setting up a new years countdown (bit late i know) but i would like to know how to get this to work for other timezones
I have already got it working for the usual UTC timezone as thats default. I have tried the .toLocalString and it returned NaN on the countdown
var countDownDate = new Date("Dec 31, 2018 23:59:02").getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
document.getElementById("display").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
if (distance < 0) {
clearInterval(x);
document.getElementById("display").innerHTML = "Happy New Year!";
done()
}
}, 1000);
The Date function of javascript returns local time of each timezone depending from where the page is loaded. So you don't have to keep track of each timezone
explained here
You can achieve this with moment.js easily:
var tz = moment.tz.guess();
console.log("Current Timezone: " + tz);
var last = moment.tz("2018-12-31 23:59:02", tz);
setInterval(function(){
var current = moment.tz(tz);
if(current.isBefore(last, "seconds")){
var diff = moment.duration(last.diff(current));
document.getElementById("display").innerHTML = diff.days() + "d " +
diff.hours() + "h " + diff.minutes() + "m " + diff.seconds() + "s";
}else{
document.getElementById("display").innerHTML = "Happy New Year!";
}
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data-2012-2022.min.js"></script>
<div id="display"></div>

Countdown timer expires start a different countdown

I have the following code. I want when this timer expires, another timer should start instead of expired text.
var countDownDate = new Date("Oct 25, 2017 15:37:25").getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
document.getElementById("demo").innerHTML = days + " Days " + hours + " Hrs "
+ minutes + " Min " + seconds + " Sec ";
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "T**imer Expired - instead of this another timer**";
}
}, 1000);
Create a function, and call it every time the timer is finished.
$(document).ready(function() {
var i = 1 ;
setTimer(i) ;
}) ;
function setTimer(i) {
var countDownDate = new Date().getTime() + 3000 ;
var x = setInterval(function() {
var now = new Date().getTime() ;
var distance = countDownDate - now ;
if (distance < 0) {
clearInterval(x);
console.log("Timer " + i + " Finished. New Timer Stated!") ;
setTimer(i+1) ;
}
else {
console.log("Timer " + i + " Running") ;
}
}, 1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This code should do the trick. Each time the counter get to 0, you redefined your count down to the same amount of time there was initially between countDownDate and Now. If this amount is variable, you might modify the assignment of distanceToAdd
// Changed the value to reach for the demo
var countDownDate = new Date().getTime() + 20000;
// Fixed Value to add each time the counter get to 0
var distanceToAdd = countDownDate - new Date().getTime();
var x = setInterval(function() {
var now = new Date().getTime();
var distance = countDownDate - now;
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);
if (distance < 0) {
//Add Time to your timer goal instead of canceling interval
countDownDate += distanceToAdd;
}
else {
document.getElementById("demo").innerHTML = days + " Days " + hours + " Hrs "
+ minutes + " Min " + seconds + " Sec ";
}
}, 1000);
<html>
<head>
</head>
<body>
<div id="demo"></div>
</body>
</html>

Run multiple timers in the same page using javascript

The below code prints the title of many cards and their countdown time.....the problem is that the timer is printed only for the first card. How do i print it for all the cards?I've tried a lot to search it on google but could find a relevant answer.Please help me on how to get timers on each card.
function previewall()
{
$.ajax({
type: "POST",
data: {
},
url: "readall.php",
dataType: "json",
success: function(JSONObject) {
var peopleHTML = "";
for (var key in JSONObject) {
if (JSONObject.hasOwnProperty(key)) {
peopleHTML += "<div class='wrapper'><label>" + JSONObject[key]["title"] + "</label><br>";
peopleHTML += "<p id='demo1'></p><br><p id=demo></p> </div>";
var x = setInterval(function() {
var count =JSONObject[key]["valid_date"];
var dat=JSONObject[key]["started_date"];
var countDownDate = new Date(count).getTime();
var date = new Date(dat).getTime();
// Get todays date and time
var now = new Date().getTime();
var elapsed = now - date;
var distance = countDownDate - now;
var planned= date - 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);
var days1 = Math.floor(elapsed / (1000 * 60 * 60 * 24));
var hours1 = Math.floor((elapsed % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes1 = Math.floor((elapsed % (1000 * 60 * 60)) / (1000 * 60));
var seconds1 = Math.floor((elapsed % (1000 * 60)) / 1000);
var days2 = Math.floor(planned / (1000 * 60 * 60 * 24));
var hours2 = Math.floor((planned % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes2 = Math.floor((planned % (1000 * 60 * 60)) / (1000 * 60));
var seconds2 = Math.floor((planned % (1000 * 60)) / 1000);
if (distance < 0) {
document.getElementById("demo").innerHTML = "EXPIRED";
}
else if(elapsed<0){
document.getElementById("demo1").innerHTML = "Starts in " + days2 + "d " + hours2 + "h " + minutes2 + "m " + seconds2 + "s " ;
}
else
{
document.getElementById("demo1").innerHTML = "Posted <br>" + days1 + "d " + hours1 + "h " + minutes1 + "m " + seconds1 + "s ago" ;
document.getElementById("demo").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s Left" ;
}
});
}
}
$("#people").html(peopleHTML);
}
});
}
The problem is that all timers bind the variable key, so when they fire, they see the final value of key.
Try this instead:
for (var k in JSONObject) {
let key = k;
if (JSONObject.hasOwnProperty(key)) {
...
You have multiple elements sharing the same id (i.e. demo, demo1), the resulting page is broken and this is the cause of the issue.
The fastest fix would be keeping a counter and embedding it in the various ids of the elements you create dinamically.
Something like:
var peopleHTML = "";
var i = -1;
for (var key in JSONObject) {
i++;
if (JSONObject.hasOwnProperty(key)) {
peopleHTML += "<div class='wrapper'><label>" + JSONObject[key]["title"] + "</label><br>";
peopleHTML += "<p id='demoOuter'"+i+"></p><br><p id=demoInner"+i+"></p> </div>";
// [CUT]
f (distance < 0) {
document.getElementById("demoInner"+i).innerHTML = "EXPIRED";
}
else if(elapsed<0){
document.getElementById("demoOuter"+i).innerHTML = "Starts in " + days2 + "d " + hours2 + "h " + minutes2 + "m " + seconds2 + "s " ;
}
else
{
document.getElementById("demoOuter"+i).innerHTML = "Posted <br>" + days1 + "d " + hours1 + "h " + minutes1 + "m " + seconds1 + "s ago" ;
document.getElementById("demoInner"+i).innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s Left" ;
}

Categories

Resources