Creating a Custom Countdown Timer - javascript

I'm a graphic designer who has also been tasked with building a website for the church that I work for. I've built many websites in the past, so this isn't an issue at all, however, something that I'm looking to do with this site is to have as many elements that can just simply run on their own as possible. I'm a complete beginner when it comes to JavaScript, and honestly don't really have an idea at all about what I'm doing.
I'd like for the new site to have a custom countdown timer that will count down to when we go live, and then display a link for our live stream for a set period of time, and then reset. The code below shows what I've already managed to write from just searching around on the internet. The problem with it is that it relies on a person (which half of the time is a web-volunteer) to remember to change the date and time to the next service after the current service is finished, and 90% of the time they forget.
In a perfect world, I'd like for this countdown timer to automatically countdown to the nearest Tuesday at 6:00 pm, then show a link to our live stream for 20 minutes, then reset. Or if Sunday at 10:00 am comes first, countdown to Sunday at 10am, then show a link to our live stream for one hour and 15 minutes, and then reset. Theoretically I would imagine this could run indefinitely as it would just check for if Tuesday at 6pm comes first, or if Sunday at 10am comes first, then countdown to those times, pause, show some hyperlinked text, and then repeat.
I apologize if this has already been talked about here, I tried searching as thoroughly as I could and couldn't find anything.
Any help at all would be greatly appreciated.
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p id="demo" class="countdown-live" style="text-align:center;"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("October 20, 2020 18:00:00").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays 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);
// Output the result in an element with id="demo"
document.getElementById("demo").innerHTML = days + " d " + hours + " h "
+ minutes + " m & " + seconds + " s";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = 'Watch Live!';
}
}, 1000);
</script>
</body>
</html>

This is a little delayed but here's something that works with a little maintenance.
(() => {
var currentDate = new Date();
currentDate = currentDate.toLocaleString("en-US", {
timeZone: "America/New_York"
});
// Service times
var serviceTEN = "2021/12/06 11:15";
var serviceTWELVE = "2021/12/06 13:45";
var serviceTWO = "2021/12/06 15:45";
var serviceFIVE = "2021/12/06 16:45";
var serviceSEVEN = "2021/12/06 19:45";
var waiting;
// Set current service
var currentService = serviceTEN;
function pad(num, size) {
var s = "0" + num;
return s.substr(s.length - size);
}
// Get the current time, set the correct timezone, and parse it to the same layout.
// Find the difference between the current date and the service time.
// Have that be the time remaining.
function getTimeRemaining(endtime) {
var now = new Date();
now = now.toLocaleString("en-US", {
timeZone: "America/New_York"
});
// Parse the date to find each variable (seconds, minutes, hours, days)
let t = Date.parse(endtime) - Date.parse(now);
let seconds = Math.floor((t / 1000) % 60);
let minutes = Math.floor((t / 1000 / 60) % 60);
let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
let days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
total: t,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds,
};
}
// the id refers to "js-clock" which is the beginning of the ID, this can be changed
function clock(id, endtime) {
let days = document.getElementById(id + "-days");
let hours = document.getElementById(id + "-hours");
let minutes = document.getElementById(id + "-minutes");
let seconds = document.getElementById(id + "-seconds");
let timeinterval = setInterval(function() {
let t = getTimeRemaining(endtime);
// Look through the service times and figure out which service it should be.
if (t.total <= 0) {
if (waiting === true) {
location.reload();
} else if (t.total < -300000) {
switch (endtime) {
case serviceTEN:
endtime = serviceTWELVE;
break;
case serviceTWELVE:
endtime = serviceTWO;
break;
case serviceTWO:
endtime = serviceFIVE;
break;
case serviceFIVE:
endtime = serviceSEVEN;
break;
default:
break;
}
} else {
clearInterval(timeinterval);
}
} else {
waiting = true;
// Edit the 2 or 3 to change amount of digits
days.innerHTML = pad(t.days, 3);
hours.innerHTML = pad(t.hours, 2);
minutes.innerHTML = pad(t.minutes, 2);
seconds.innerHTML = pad(t.seconds, 2);
}
}, 1000);
}
clock("js-clock", currentService);
})();
<div class="mainOverlayCountdown-k" id="mainOverlayCountdownID-k">
<h1 id="countdownHeader-k">Next service begins in:</h1>
<div class="countdown-cover">
<div id="js-clock" class="countdowntimer">
<div id="js-clock-days" class="clock-number">00</div>
<div class="clock-label">Days</div>
<div id="js-clock-hours" class="clock-number">00</div>
<div class="clock-label">Hrs</div>
<div id="js-clock-minutes" class="clock-number">00</div>
<div class="clock-label">Min</div>
<div id="js-clock-seconds" class="clock-number">00</div>
<div class="clock-label">Sec</div>
</div>
</div>
</div>
To change the service times, edit the service'TIME' Variables. You might have to play around with it to get the correct timezone.
to add/delete service times, but make sure you also add/delete it in the variables where you set the date, and the switch function.
Hope this helps!

Related

Auto Submit Answers With Timer (Javascript)

I'm trying to make a timer that will be auto-submit all the answers when times up. But now, it just shows that the time is expired and it is not redirecting to the final score page.My answers are stored in the database, i dont think it is related. Here is the code :
$(document).ready(function() {
var endTime = localStorage.getItem("endTime");
console.log(endTime);
if (endTime != 'underfined' && endTime != null) {
startCountdownTimer();
//localStorage.removeItem("endTime");
}
});
function setEndTime() {
var currentTime = new Date().getTime();
var endTime = new Date(currentTime + 1*60000);
localStorage.setItem("endTime", endTime);
// alert('Set end time ' + endTime);
startCountdownTimer();
}
function startCountdownTimer() {
// Set the date we're counting down to
var endTime = localStorage.getItem("endTime");
var countDownDate = new Date(endTime).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="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is finished,[ I want to make it is redirecting to score page ]
if (distance <= 0) {
clearInterval(x);
setTimeout("document.quiz.submit()",1);
window.location = "http://localhost/quizzer%202/final.php"
}
},1000);
}
Here's a solution with JavaScript's native setTimeout function to auto-submit your form:
// The following ($function() {}) is equivalent to $(document).ready(function() {.
$(function() {
setTimeout(function() {
setTimeout(function() {$('#idOfYourForm').submit()},1);
window.location = "http://localhost/quizzer%202/final.php"
}, 1000 * 60 * 10); // This is the amount of milliseconds your test will last. I set this to ten minutes
});
Also, it doesn't look like the submit command is correct. Since you're using jQuery, I'll show you the jQuery way.
Make an ID for your form
Submit it with $('#idOfYourForm').submit() (one problem was that you put quotation marks around it)
One last thing, when you submit a form, the default action is that you will be redirected, so your last redirect won't do anything. For what you did to work, consider using AJAX. See this post.

How can I organize my code more in order to prevent the undesired behavior?

As of now, I've written a script for a timer to countdown to a specific day. The problem is that the moment you refresh the browser, it takes 1 second for it to appear as opposed to it appearing instantly.
I actually did figure out a way to make it appear instantly but I had to repeat the block of code with countDownDate, now, timeDifference, oneDay, days, hours, minutes, seconds and document.getElementById("timer").innerHTML = ...; by placing it directly on top of timer() which's totally inefficient.
In my attempt below, the countdown appears about one second upon the browser refreshing but I want it to appear instantly. My goal here is to create reusable code.
What am I doing wrong and how can I fix it?
Here's the html:
<h1 id="timer"></h1>
Here's the js:
function conversion() {
var countDownDate = new Date("June 1, 2019 24:00:00");
var now = new Date().getTime();
var timeDifference = countDownDate - now;
var oneDay = 1000 * 60 * 60 * 24;
var days = Math.floor(timeDifference / (oneDay));
var hours = Math.floor((timeDifference % (oneDay)) / (1000 * 60 * 60));
var minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
document.getElementById("timer").innerHTML = days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
}
function timerCountdown() {
var timer = setInterval(function() {
conversion();
if(timeDifference < 0) {
clearInterval(timer);
document.getElementById("timer").innerHTML = "Timer's over.";
}
}, 1000);
}
timerCountdown();
Put the setInterval callback into a variable, and both call setInterval with that function and call it immediately on pageload:
function timerCountdown() {
var timer = setInterval(intervalCb, 1000);
function intervalCb() {
conversion();
if(timeDifference < 0) {
clearInterval(timer);
document.getElementById("timer").innerHTML = "Timer's over.";
}
}
intervalCb();
}
timerCountdown();
Just call conversion() immeadiately.

create a countdown that the remain time is equal no mather the country

i can image someone had donde this already or it can be considered a duplicated question, i've been searching for weeks and i can't figure out how to accomplish this.
I have a countdown made in js, the problem i'm facing is that when ever i test it in another country the times throw out different hours example.
i'm in centralamerica, end date is apr 16, 2018 23:59:59" if i test this in centralamerica it says 6 days and 10 hours remaining, if i run this in italy for example it says 6 days and 3 hours remaining, i need it to be equal all the time and that the timezone doesn´t affects, is this even possible, and please help on how to get it done.
the script i have is working but not the way i need to, i have a promo that will expire on "apr 16, 2018 23:59:59" so if it only has 5 hours remaining it shout say 5 hours remaining no matter where its been seeing from, but that is not happening.
$("#masterslider").append("<p id='demo'>.</p>")
$("#masterslider").append("<span> remaining time </span>")
//******************************** update date here ************************
var serverDate = new Date("apr 16, 2018 23:59:59");
var offset = serverDate.getTimezoneOffset();
serverDate = addOffset(serverDate, offset);
setInterval(function(){
updateCountdown();
}, 1000);
function addOffset(date, offset) {
var time = date.getTime() ;
return new Date(time + offset * 6000);
}
function updateCountdown() {
var userDate = new Date();
var distance = serverDate.getTime() - userDate.getTime();
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(serverDate.getTime() > userDate.getTime()){
$('#demo').html( days +"day(s)"+ " / " + hours + "hour(s)" + minutes + "minutes(s)");
}
else
{
$("#demo").html(mas);
$("#masterslider span").hide();
}
}
</script>
I've checked and setting correct timezone for "event timestamp" works for me regardless local client timezone I use.
let targetDate = new Date("2018-04-11 23:59:59 GMT-0800");
let refreshDelayMs = 1000;
function updateCounter() {
let distance = (targetDate - new Date()) / 1000;
let seconds = Math.floor(distance % 60).toString().padStart(2, '0');
distance = distance / 60;
let minutes = Math.floor(distance % 60).toString().padStart(2, '0');
distance = distance / 60;
let hours = Math.floor(distance % 24).toString().padStart(2, '0');
let days = Math.floor(distance / 24).toString().padStart(2, '0');
document.querySelector('.counter').innerHTML = `${days} days ${hours}:${minutes}:${seconds}`;
setTimeout(updateCounter, refreshDelayMs);
}
updateCounter();
Remains: <span class="counter"></span>
You can use moment-timezone from CDN or use NPM
repl.it sample
const moment = require("moment-timezone");
function toTimeZone(time, offset) {
var format = 'YYYY/MM/DD HH:mm:ss ZZ';
return moment(time, format).utcOffset(offset).format(format);
}
toTimeZone("2018/04/10 15:37", "+0730")

create countdown based on server hour

I´m facing a need of creating a coundown to display when ever a certain promo will be over, all i have is front-end access via google tag manager, first i manage to get the server hour with js, now i need to set the countdown hour based on the server hour and not local hour.
<script>
// it´s giving the correct hour
var getserver = new Date();
getserver.setHours(getserver.getHours());
var newtets = getserver.toUTCString();
alert(newtets);
// using a basic countdown
var countDownDate = new Date("Sep 5, 2018 15:37:25").getTime();
// Update the count down every 1 second
var x = setInterval(function() {
// Get todays date and time
var now = new Date().getTime();
/*
var now = new Date();
now.setHours(now.getHours());
var newnow = now.toUTCString();
i tried to replace now with newnow but is not working, how can i transform this
*/
// Find the distance between now an 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);
// Output the result in an element with id="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "EXPIRED";
}
}, 1000);
</script>
var now = new Date().getTime(); is what getting the time and use it to countdown, this is taking local time, how can i get var now = new Date().getTime(); to be server hour, which i obtained with the 1 script
The only way to get your updated server hour is using an ajax call.
The problem is that the request to the server is not immediate so you will have a delay.
Maybe it would be better to get the user timezone and calculate the promo ending with this information.
You can get the user timezone offset using:
var offset = new Date().getTimezoneOffset();

Memory Leak with setInterval

I'm currently having an issue with what in belive is a memory leak on a custom PHP website that utilises JS SetInterval
My site loads values from an external PHP file every 30 seconds and appends them to a HTML object, a <p> tag in this case.
<script>
$(window).on('load', function() {
setInterval (function foo1(){
$.get("scriptref.php", function( data ) { //receiving the echo from the php data file
$("#ref").html(data); //putting the echoed value directly into the p tag
});
return foo1;
}(), 30000)});
</script>
I also have a countdown timer that counts downwards in seconds to a specified value.
<script>
var timer = document.getElementById("demo");
var snd = new Audio("/assets/audio/horn.wav"); // buffers automatically when created
// Update the count down every 1 second
var x = setInterval(function() {
var jsnextbreach = document.querySelector("#test").innerHTML;
// Set the date we're counting down to
var countDownDate = new Date(jsnextbreach).getTime();
// Get todays date and time
var now = new Date().getTime();
// Find the distance between now an 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);
// Output the result in an element with id="demo"
document.getElementById("demo").innerHTML = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
// If the count down is over, write some text
if (distance < 0) {
document.getElementById("demo").innerHTML = "BREACHED";
}
// If the count down is less than an hour replace demo class to warning.
if (distance < 3600000 ) {
timer.className = "warning" ;
}
if (distance > 3600001 ) {
timer.className = "normal" ;
}
if (distance < 3600000 && distance > 3598000) {
snd.play();
}
},1000);
</script>
My problem is that after the page is displayed for an hour or so i get the "Aw snap, google chrome ran out of memory while trying to display this webpage" error. Looking at the profiler I can see that memory usage increases slowly, however I have no idea where to start looking to find out what is causing this leak.
If anyone is able to advise anything that may be wrong with my code or alternatively how i can start troubleshooting what specific element is causing the leak i would be truly grateful!

Categories