Helloooo...I've been tasked with creating a web page that contains a count down clock. I have managed to create the clock with HTML and Javascript but what I am having trouble with is the formatting. The client wants the days, hours and minutes in separate individual circles. Not animated, just plain. I've tried a few things with no results. I thought maybe if I created a separate clock for the Days, hours and minutes, that that would work, but when I do this, the clocks disappear. Would love some advice. Thanks a million.
The code for the clock I used is as follows:
<script>
var countDownDate = new Date("Feb 14, 2021 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 + "d " + hours + "h "
+ minutes + "m ";
if (distance < 0) {
clearInterval(x);
document.getElementById("demo").innerHTML = "We Are Live!";
}
}, 1000);
</script>
The CSS I used is as follows but I can only get that to work when I just have one time from the clock, like just the days for instance.
.demo{
border-radius: 50%;
width: 50px;
height: 50px;
padding: 10px;
background: #fff;
border: 3px solid #000;
color: #000;
text-align: center;
font: 30px cantata;
display: flex; /* or inline-flex */
align-items: center;
justify-content: center;
}
</style>
Just place the hours, minutes, and seconds within their own containers and style them separately, e.g:
<div id="demo">
<span id="hours"/>:
<span id="minutes"/>:
<span id="seconds"/>
</div>
I am building a deal page with countdown timer to show how much time is remaining to claim the offer. I have the countdown timer working to show how many days, hours, minutes and seconds are left, but would like to have a visual progress bar under the time that fills up based on the days left.
For example, the offer goes live July 1 and expires July 31. If the user loads the page on July 1, the progress bar would be at 0%. On July 31, the progress bar would be set to 100%.
I am currently using the progress bar styling and HTML code used by Bootstrap 3.
I've been trying to the width style property for "progress-bar" to the days remaining, but have not been able to get them to link up
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {clearInterval(timeinterval); } } updateClock(); var timeinterval=setInterval(updateClock, 1000); } var deadline=new Date("july 31, 2019 23:59:59"); initializeClock('clockdiv', deadline);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="clockdiv" style="font-weight:600;text-transform: uppercase">Time Remaining:<span class="days"></span>:<span class="hours"></span>:<span class="minutes"></span>:<span class="seconds"></span></div>
<div class="progress" style="margin-bottom:8px;border-radius: 4px">
<div class="progress-bar progress-bar-striped active" style="width:%;border-radius: 4px">
</div>
</div>
Here is a working demo using
Math.round(((today - start) / (end - start)) * 100) + '%';
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime, starttime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
var $progress = $('.progress-bar')
function updateClock() {
var t = getTimeRemaining(endtime);
var p = Math.round(((new Date() - starttime) / (endtime - starttime)) * 100) + '%';
$progress.css('width', p);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
var starttime = new Date("july 1, 2019 23:59:59");
var deadline = new Date("july 31, 2019 23:59:59");
initializeClock('clockdiv', deadline, starttime);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div id="clockdiv" style="font-weight:600;text-transform: uppercase">Time Remaining:<span class="days"></span>:<span class="hours"></span>:<span class="minutes"></span>:<span class="seconds"></span></div>
<div class="progress" style="margin-bottom:8px;border-radius: 4px">
<div class="progress-bar progress-bar-striped active" style="width:%;border-radius: 4px">
</div>
</div>
Note: It is not necessary to update progress bar every second, It's fine in minutes
You can use document.querySelector('.progress-bar') and then use .style.width = 'xx %' to set the width.
I've refactored the code a bit to make it more readable :)
Working example:
function Clock(id, startDate, endDate) {
this.clock = document.getElementById(id);
this.timeEl = this.clock.querySelector('.time');
this.progressEl = this.clock.querySelector('.progress-bar');
this.startDate = startDate;
this.endDate = endDate;
this.updateClock();
this.interval = setInterval(this.updateClock.bind(this), 1000);
}
Clock.prototype.updateClock = function() {
var rem = this.getTimeRemaining();
// Update time element
var duration = [
rem.days,
this.padLeft(rem.hours),
this.padLeft(rem.minutes),
this.padLeft(rem.seconds)
];
this.timeEl.innerHTML = duration.join(":");
// Update progress
var progress = this.getProgress(rem.total);
this.progressEl.style.width = (progress * 100) + "%";
// Clear intervall when done
if(rem.t === 0 && this.interval) {
clearInterval(this.interval);
delete this.interval;
}
};
Clock.prototype.padLeft = function(number) {
return ('0' + number).slice(-2);
};
Clock.prototype.getTimeRemaining = function() {
var t = this.endDate - new Date();
if(t < 0) t = 0;
return {
total: t,
days: Math.floor(t / (1000 * 60 * 60 * 24)),
hours: Math.floor((t / (1000 * 60 * 60)) % 24),
minutes: Math.floor((t / 1000 / 60) % 60),
seconds: Math.floor((t / 1000) % 60)
};
};
Clock.prototype.getProgress = function(remainingTime) {
var totalTime = this.endDate - this.startDate;
return 1 - (remainingTime / totalTime);
};
// Example. Replace startDate and endDate with your dates (30sec for demo)
var startDate = new Date();
var endDate = new Date(Date.now() + 30 * 1000);
new Clock("clockdiv", startDate, endDate);
#clockdiv {
font-weight: 600;
text-transform: uppercase;
}
.progress {
margin-bottom: 8px;
border-radius: 4px;
}
.progress-bar {
width: 100%;
border-radius: 4px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="clockdiv">
<div>
Time Remaining:
<span class="time"></span>
</div>
<div class="progress">
<div class="progress-bar progress-bar-striped active"></div>
</div>
</div>
I have a count down clock on my site but it resets if you clear your browser history. Is there a way to stop this from happening. I found the code on a website that you can download from. I was not expecting it to reset when you clear your browser history. Can this code be modified or would it be better for me to find another code for it.
Thanks
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
var deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
#clockdiv {
color: #ffffff;
display: inline-block;
font-size: 14px;
font-weight: 100;
text-align: center;
}
#clockdiv > div {
background: #0294cb;
border-radius: 3px;
display: inline-block;
padding: 8px;
}
#clockdiv div > span {
background: #42baff;
border-radius: 3px;
display: inline-block;
padding: 15px;
}
.smalltext {
font-size: 14px;
padding-top: 5px;
}
<div id="clockdiv">
<div>
<span class="days"></span>
<div class="smalltext">Days</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Hours</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div>
</div>
You can save the initial deadline time in localStorage(But this will get cleared on erasing history) and then use that instead of resetting it again on reload, If you want your timer to not reset when clearing data, you will have to maintain a server side state.
You can add this piece of code to the bottom of your script. Instead of initializing new deadline each time, you check whether the deadline has already been initialized and stored in localStorage, if so then fetch the deadline from it. If no, the create the new deadline like you did in your original code and store it in localStorage.
Note that you need to use JSON.stringify and JSON.parse methods if you want to store and later retrieve an object from localStorage because it can only hold strings and default string representation of an object isn't very useful.
This code will not reset the countdown on page reload and you can clean history as well but you can't clear localStorage (cached files and cookies) for it to work.
if (!localStorage.getItem('deadline')) {
const deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
localStorage.setItem('deadline', JSON.stringify(deadline));
initializeClock('clockdiv', deadline);
} else {
const deadline = JSON.parse(localStorage.getItem('deadline'));
initializeClock('clockdiv', deadline);
}
See the snippet for full code, but note that it will not work here because localStorage is not accessible on SO. You will need to copy and paste it and test it in your browser.
function getTimeRemaining(endtime) {
var t = Date.parse(endtime) - Date.parse(new Date());
var seconds = Math.floor((t / 1000) % 60);
var minutes = Math.floor((t / 1000 / 60) % 60);
var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
var days = Math.floor(t / (1000 * 60 * 60 * 24));
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = getTimeRemaining(endtime);
daysSpan.innerHTML = t.days;
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
if (t.total <= 0) {
clearInterval(timeinterval);
}
}
updateClock();
var timeinterval = setInterval(updateClock, 1000);
}
if (!localStorage.getItem('deadline')) {
const deadline = new Date(Date.parse(new Date()) + 15 * 24 * 60 * 60 * 1000);
localStorage.setItem('deadline', JSON.stringify(deadline));
initializeClock('clockdiv', deadline);
} else {
const deadline = JSON.parse(localStorage.getItem('deadline'));
initializeClock('clockdiv', deadline);
}
#clockdiv {
color: #ffffff;
display: inline-block;
font-size: 14px;
font-weight: 100;
text-align: center;
}
#clockdiv > div {
background: #0294cb;
border-radius: 3px;
display: inline-block;
padding: 8px;
}
#clockdiv div > span {
background: #42baff;
border-radius: 3px;
display: inline-block;
padding: 15px;
}
.smalltext {
font-size: 14px;
padding-top: 5px;
}
<div id="clockdiv">
<div>
<span class="days"></span>
<div class="smalltext">Days</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Hours</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minutes</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Seconds</div>
</div>
</div>
My countdown timer I want to put on a site is having some issues. Countdown is normal, everything is fine, but at the end of the timer, instead of it to clear the timer and display the end message or a call back, it will rather display the end message by the side while time continues to read in the negative.
Can anyone show me what went wrong?
This is my code:
// Set the date we're counting down to
var countDownDate = new Date("March 31, 2017 09:35:00 PM").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 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("days").innerHTML = days;
document.getElementById("hours").innerHTML = hours;
document.getElementById("minutes").innerHTML = minutes;
document.getElementById("seconds").innerHTML = seconds;
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("endmessage").innerHTML = "EXPIRED";
}
}, 1000);
body {
background: #f6f6f6;
}
.countdownContainer{
position: absolute;;
top: 50%;
left: 50%;
transform : translateX(-50%) translateY(-50%);
text-align: center;
background: #ddd;
border: 1px solid #999;
padding: 10px;
box-shadow: 0 0 5px 3px #ccc;
}
.info {
font-size: 80px;
}
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<table class="countdownContainer">
<tr class="info">
<td colspan="4">Countdown to April fool</td>
</tr>
<tr class="info">
<td id="days">00</td>
<td id="hours">00</td>
<td id="minutes">00</td>
<td id="seconds">00</td>
<td id="endmessage"></td>
</tr>
<tr>
<td>Days</td>
<td>Hours</td>
<td>Minutes</td>
<td>Seconds</td>
</tr>
</table>
<p id="demo"></p>
<script>
</script>
</body>
</html>
I have made some changes to your code. Please find it below,
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
body {
background: #f6f6f6;
}
.countdownContainer{
position: absolute;;
top: 50%;
left: 50%;
transform : translateX(-50%) translateY(-50%);
text-align: center;
background: #ddd;
border: 1px solid #999;
padding: 10px;
box-shadow: 0 0 5px 3px #ccc;
}
.info {
font-size: 80px;
}
</style>
</head>
<body>
<table class="countdownContainer">
<tr class="info">
<td colspan="4">Countdown to April fool</td>
</tr>
<tr class="info">
<td id="days">00</td>
<td id="hours">00</td>
<td id="minutes">00</td>
<td id="seconds">00</td>
<td id="endmessage"></td>
</tr>
<tr>
<td>Days</td>
<td>Hours</td>
<td>Minutes</td>
<td>Seconds</td>
</tr>
</table>
<p id="demo"></p>
<script>
// Set the date we're counting down to
var countDownDate = new Date("April 01, 2017 12:00:30 PM").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 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);
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("endmessage").innerHTML = "EXPIRED";
}
else{
// Output the result in an element with id="demo"
document.getElementById("days").innerHTML = days;
document.getElementById("hours").innerHTML = hours;
document.getElementById("minutes").innerHTML = minutes;
document.getElementById("seconds").innerHTML = seconds;
}
}, 1000);
</script>
</body>
</html>
Each time the countdown is printed, it should be done only if the difference is greater than 0. So moved that part inside the else condition of your IF. Adjust the date accordingly to test your countdown.
Is it not already the 1st of april? It is counting down to a day already passed as in the 31 of march?
Also, you do not need PM, remove PM and just have 09 or 21 etc. Not AM/PM
<script>
// Set the date we're counting down to
var countDownDate = new Date("April 1, 2017 09:35: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 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("days").innerHTML = days;
document.getElementById("hours").innerHTML = hours;
document.getElementById("minutes").innerHTML = minutes;
document.getElementById("seconds").innerHTML = seconds;
// If the count down is over, write some text
if (distance < 0) {
clearInterval(x);
document.getElementById("endmessage").innerHTML = "EXPIRED";
}
}, 1000);
</script>
This counts down to 09:35, today.
I have searched the web but all the ones readily available are where you specificy a date and it counts down to that date. What I need is something which will simply count down from "27 minutes and 43 seconds" (in that format) all the way down to 0 from whenever they land on the page, anyone got any snippets available?
Something like this should do the trick. I'm bored and decided to do it myself instead of Googling. Just set the minutes and seconds at the top and change the call to countdown inside the onload to the id of the element you want it to update.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script>
var interval;
var minutes = 1;
var seconds = 5;
window.onload = function() {
countdown('countdown');
}
function countdown(element) {
interval = setInterval(function() {
var el = document.getElementById(element);
if(seconds == 0) {
if(minutes == 0) {
el.innerHTML = "countdown's over!";
clearInterval(interval);
return;
} else {
minutes--;
seconds = 60;
}
}
if(minutes > 0) {
var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
} else {
var minute_text = '';
}
var second_text = seconds > 1 ? 'seconds' : 'second';
el.innerHTML = minute_text + ' ' + seconds + ' ' + second_text + ' remaining';
seconds--;
}, 1000);
}
</script>
</head>
<body>
<div id='countdown'></div>
</body>
</html>
I have made a simple countdown you can use.
It is generating the format:
DAYS X, HOURS X, MINUTES X, SECONDS X
The JS:
countIt();
function countIt(){
year = 2013;
month = 05;
day = 28;
hours = 12;
minutes = 00;
seconds = 00;
setTimeout(function(){
endDate = new Date(year, (month - 1), day, hours, minutes, seconds, 00);
thisDate = new Date();
thisDate = new Date(thisDate.getFullYear(), thisDate.getMonth(), thisDate.getDate(), thisDate.getHours(), thisDate.getMinutes(), thisDate.getSeconds(), 00, 00);
var daysLeft = parseInt((endDate-thisDate)/86400000);
var hoursLeft = parseInt((endDate-thisDate)/3600000);
var minutsLeft = parseInt((endDate-thisDate)/60000);
var secondsLeft = parseInt((endDate-thisDate)/1000);
seconds = minutsLeft*60;
seconds = secondsLeft-seconds;
minutes = hoursLeft*60;
minutes = minutsLeft-minutes;
hours = daysLeft*24;
hours = (hoursLeft-hours) < 0 ? 0 : hoursLeft-hours;
days = daysLeft;
startCount(days, hours, minutes,seconds);
}, 1000);
}
function startCount(days, hours, minutes, seconds){
document.getElementById("counter").innerHTML="DAYS "+days+", HOURS "+hours+", MINUTES "+minutes+", SECONDS: "+seconds;
countIt();
}
The HTML:
<div id="counter"></div>
Click here to see it live
I think you're looking for something like this.
um, why not just use this:
<div id="countdown">countdown displayed here</div>
<script type="text/javascript">
$(document).ready(function() {
//time to count down
hoursToGo = 0;
minutesToGo = 27;
secondsToGo = 43;
var startTime = new Date();
var endTime = new Date();
endTime.setHours(
startTime.getHours() + hoursToGo,
startTime.getMinutes() + minutesToGo,
startTime.getSeconds() + secondsToGo,
startTime.getMilliseconds()
);
//function to update counter
function update(){
var currentTime = new Date();
var remainingTime = new Date();
remainingTime.setTime(endTime.getTime()-currentTime.getTime());
$("#countdown").text(remainingTime.getHours()+":"+remainingTime.getMinutes()+":"+remainingTime.getSeconds());
//call itself every second
setTimeout(update,1000);
}
//start the countdown
update();
});
</script>
EDIT
As an added thought, you could implement this over multiple pages by passing the end time onto the next page as the value of a hidden form element. Or at least thats what i am going to do with it ;-)
jCounter is a plugin that also accepts custom values to display any countdown you want
I also made a count-down clock but with html5 canvas.
Feel free to use it if you like it. (Run the code snipet below)
(function() {
/**
* WlCounter pure JS class
*
* #class WlCounter
* #Author: Wiktor Lis
*/
var WlCounter = function(){
// date settings - REMEMBER months in Date object are counted as an Array from 0! So months range is between 0 to 11. Other than that everything is just as you would expect it to be.
this.setEventDate(new Date(2017, 03, 22, 22, 5, 0), 'Curently Unused'); // NOTE! months are represented from 0 to 11 in Date objects
this.setEventEndDate(new Date(2019, 04, 03, 22, 9, 0), 'Curently Unused', 'Curently Unused'); // NOTE! months are represented from 0 to 11 in Date objects
// CLOCK SETTINGS
// clock size
this.container = {
x: 0,
y: 0,
w: 150,
h: 150
};
// ring stroke
this.stroke = this.container.w / 10;
// number font size
this.numFontSize = this.container.w / 6 +'px';
// label font size
this.labelFontSize = this.container.w / 10 +'px';
// colors
this.colorRing = "hsla(355, 0%, 90%, 1)";
this.colorActive = "hsla(355, 100%, 50%, 1)";
this.colorTimedOut = "hsla(355, 0%, 50%, 0.3)";
// OTHER
// init objets
this.curent = {};
this.counter = {};
}
/**
* This method creates canvas based on css id
*
* #method createCanvas
* #param {String} cssId of canvas DOM object
*/
WlCounter.prototype.createCanvas = function(cssId){
this.canvas = document.getElementById(cssId);
this.canvas.setAttribute("width", this.container.w);
this.canvas.setAttribute("height", this.container.h);
this.c = this.canvas.getContext('2d');
return this.c
}
/**
* Init all canvas objects and start counting down
*
* #method init
*/
WlCounter.prototype.init = function(){
this.daysBox = this.createCanvas('canvas-d');
this.hoursBox = this.createCanvas('canvas-h');
this.minutesBox = this.createCanvas('canvas-m');
this.secoundsBox = this.createCanvas('canvas-s');
this.msBox = this.createCanvas('canvas-ms');
this.startCounting();
this.intervalClock();
}
/**
* Assign curent time to class properities
*
* #method getTime
*/
WlCounter.prototype.getTime = function() {
this.curent.time = new Date();
this.curent.days = this.curent.time.getDay();
this.curent.hours = this.curent.time.getHours();
this.curent.minutes = this.curent.time.getMinutes();
this.curent.seconds = this.curent.time.getSeconds();
this.curent.milliseconds = this.curent.time.getMilliseconds();
}
/**
* Creates event start date // and its message
*
* #method setEventDate
* #param {Object Date} date - defines event start date
* #param {String} messageBefore - curently unused
*/
WlCounter.prototype.setEventDate = function(date, messageBefore) {
this.eventStarts = date;
this.messageBefore = messageBefore;
}
/**
* Define event end date
*
* #method setEventEndDate
* #param {Object Date} date
* #param {String} messageDuring
* #param {String} messageAfter
*/
WlCounter.prototype.setEventEndDate = function(date, messageDuring, messageAfter) {
this.eventEnds = date;
this.messageDuring = messageDuring;
this.messageAfter = messageAfter;
}
/**
* Substract curent time from event date and define how many of days, hours, min, s, ms are left
* If event starts counter finished -> change counter color to greenish (hsla(160, 100%, 38%, 1)) and count to events End time.
*
* #method startCounting
*/
WlCounter.prototype.startCounting = function() {
this.intervalToEvent = setInterval(function() {
this.getTime();
if (this.curent.time < this.eventStarts) {
this.subject = this.eventStarts;
} else if(this.curent.time < this.eventEnds) {
// change colors
this.colorActive = "hsla(160, 100%, 38%, 1)";
this.subject = this.eventEnds;
} else {
this.stagnate();
return;
}
var until = this.subject - this.curent.time;
this.counter.ms = Math.floor(until % 1000);
this.counter.sec = Math.floor(until / (1000) % 60);
this.counter.min = Math.floor(until / (1000 * 60) % 60);
this.counter.hours = Math.floor(until / (1000 * 60 * 60 ) % 24);
this.counter.days = Math.floor(until / (1000 * 60 * 60 * 24));
// console.log(this.counter);
}.bind(this), 16.666);
}
/**
* If counter will go pass the event start and end date, simply stagneta the clock assigning 0 to each clock
*
* #method stagnate
*/
WlCounter.prototype.stagnate = function() {
clearInterval(this.intervalToEvent);
this.counter.ms = 0;
this.counter.sec = 0;
this.counter.min = 0;
this.counter.hours = 0;
this.counter.days = 0;
}
/**
* Convert deg to radians
*
* #method degToRad
* #param {Integer} deg
*/
WlCounter.prototype.degToRad = function(deg) {
radians = Math.PI / 180;
return radians * deg;
}
/**
* Draw the clock and sign it with the text from the #param2
*
* #method drawClock
* #param {Object} ctx - canvas selection
* #param {Array} timeUnit - example [this.counter.days, 365, 'D'] -> [0] counter number of days -> [1] max days for the clock to count down -> [2] Title that will be assign to the clock under the number
*/
WlCounter.prototype.drawClock = function(ctx, timeUnit) {
// background - gradient
gradient = ctx.createRadialGradient(this.container.w/2, this.container.h/2, 55, this.container.w/2, this.container.h/2, this.container.w/2);
gradient.addColorStop(1, 'rgba(245,245,245, 0.1)');
gradient.addColorStop(0, 'white');
// canvas rect
// ctx.fillStyle = "white";
ctx.fillStyle = gradient;
ctx.fillRect(0,0,this.container.w, this.container.h);
// clock rim
ctx.beginPath();
ctx.strokeStyle = this.colorRing;
ctx.lineWidth = this.container.w / 18;
ctx.arc(this.container.w/2, this.container.h/2,this.container.h/2-this.stroke, this.degToRad(270), this.degToRad(0 - 90));
ctx.stroke();
// clock time
ctx.beginPath();
// ctx.shadowBlur = this.stroke-10;
// ctx.shadowColor = "hsla(355, 100%, 0%, 0.2)";
// ring countdown
// ctx.lineCap = "round";
ctx.strokeStyle = this.colorActive;
if(timeUnit[0] == 0) ctx.shadowColor = ctx.strokeStyle = this.colorTimedOut; // if time is 0 set color to gray
ctx.lineWidth = this.stroke;
// draw ring countdown
ctx.arc(this.container.w/2, this.container.h/2,this.container.h/2-this.stroke, this.degToRad(270), this.degToRad(360 * timeUnit[0] / timeUnit[1] - 90));
// text - number
ctx.font = this.numFontSize+" Arial";
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillStyle = this.colorActive;
if(timeUnit[0] == 0) ctx.fillStyle = this.colorTimedOut;
if(timeUnit[1] == 60000) timeUnit[0] = Math.round(timeUnit[0]/1000);
ctx.fillText(timeUnit[0],this.container.w/2,this.container.h/2);
// text - label
ctx.font = this.labelFontSize+" Arial";
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(timeUnit[2],this.container.w/2,this.container.h/2 + (this.container.w / 5));
// draw!
ctx.stroke();
}
/**
* Set interval to draw clock around 60 frames per seckound (1s / 60 = 16.666)
*
* #method intervalClock
*/
WlCounter.prototype.intervalClock = function() {
var interval = setInterval(function(){
// cl(this.counter.ms);
this.drawClock(this.daysBox, [this.counter.days, 365, 'D']);
this.drawClock(this.hoursBox, [this.counter.hours, 24, 'H']);
this.drawClock(this.minutesBox, [this.counter.min, 60, 'M']);
this.drawClock(this.secoundsBox, [this.counter.sec, 60, 'S']);
this.drawClock(this.msBox, [this.counter.ms, 1000, 'ms']);
}.bind(this), 16.666);
}
/* RUN WlCounter */
var counter = new WlCounter();
// FUTURE -> To Do
// set event start and end
// counter.setEventStart(foo);
// counter.setEventEnd(foo);
// counter.onEventStart(function(){
// ...
// });
// counter.onEventEnd(function({
// ...
// });
counter.init();
})();
* {
padding: 0px;
margin: 0px;
text-decoration: none;
border: none;
}
html, body {
position: relative;
padding-top: 20px;
margin: 0 auto;
}
#wrap, .text {
width: 770px;
margin: auto;
}
canvas {
box-sizing: border-box;
border-bottom: 5px solid gray;
height: 100%;
}
h1, p {
font-weight: 400;
color: #666;
font-size: 2.5em;
width: 100%;
text-align: center;
}
p {
font-size: 1em;
text-align: left;
}
ul ol {
padding-left: 20px;
list-style-type: decimal;
line-height: 2em;
}
<div class="text">
<h1>"WlCounter" pure JS class</h1>
</div>
<div id="wrap">
<canvas id="canvas-d"></canvas>
<canvas id="canvas-h"></canvas>
<canvas id="canvas-m"></canvas>
<canvas id="canvas-s"></canvas>
<canvas id="canvas-ms"></canvas>
</div>
<div class="text">
<p>JS WlCounter class counts-down to the event starting and ending date with color change on reaching the first one. After event start date is reached it changes the color to green and start count-down to events end date (if end date was specyfied and is more then curent time). So when event is ended, counter gets graied out and set 0</p>
</div>