I'm trying to build a countdown clock that goes from one date to the next. An example would be a count down to Halloween then to Thanksgiving. When the countdown reaches zero, I want the counter to restart and count down to the next holiday.
I've tried separating the events and labeling them differently to target them independently. ANy ideas would be great, this has me stuck.
<div class="container">
<p id="timer">
<span id="timer-days"></span>
<span id="timer-hours"></span>
<span id="timer-minutes"></span>
<span id="timer-seconds"></span>
</p>
</div>
<script>
var holidazeEnd=new Date("Jun, 9 2019 18:19:00").getTime();
var holidazeEnd1=new Date("Jun, 9 2019 18:20:00").getTime();
var timer= setInterval(function(){
let now=new Date().getTime();
let t=holidazeEnd - now;
if (t >= 0)
{
let days = Math.floor(t / (1000 * 60 * 60 * 24));
let hours = Math.floor((t % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let mins = Math.floor((t % (1000 * 60 * 60)) / (1000 * 60));
let secs = Math.floor((t % (1000 * 60)) / 1000);
document.getElementById("timer-days").innerHTML=days+"<span class= 'label'> Days</span>";
document.getElementById("timer-hours").innerHTML=("0"+hours).slice(-2)+"<span class= 'label'> Hours</span>";
document.getElementById("timer-minutes").innerHTML=("0"+mins).slice(-2)+"<span class= 'label'> Minutes</span>";
document.getElementById("timer-seconds").innerHTML=("0"+secs).slice(-2)+"<span class= 'label'> Seconds</span>";
}
else{
document.getElementById("timer").innerHtml=("Happy Independence Day!");}
},1000)
//---------------------------------------------//
var timer1= setInterval(function(){
let now=new Date().getTime();
let t=holidazeEnd1 - now;
if (t >= 0) {
let days1 = Math.floor(t / (1000 * 60 * 60 * 24));
let hours1 = Math.floor((t % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let mins1 = Math.floor((t % (1000 * 60 * 60)) / (1000 * 60));
let secs1 = Math.floor((t % (1000 * 60)) / 1000);
document.getElementById("timer-days").innerHTML=days1+"<span class= 'label'> Days</span>";
document.getElementById("timer-hours").innerHTML=("0"+hours1).slice(-2)+"<span class= 'label'> Hours</span>";
document.getElementById("timer-minutes").innerHTML=("0"+mins1).slice(-2)+"<span class= 'label'> Minutes</span>";
document.getElementById("timer-seconds").innerHTML=("0"+secs1).slice(-2)+"<span class= 'label'> Seconds</span>";
}
else
document.getElementById("timer1").innerHtml="Merry Xmas!";}
,1000);
countdown(holidazeEnd,timer);
countdown(holidazeEnd1,timer1)
What about to use a single setInterval and an array of holidays?
const holidays = [
{
running: "Independence Day",
complete: "Happy Independence Day!",
time: "July 4 2019"
},
{
running: "Christmas",
complete: "Merry Xmas!",
time: "Dec 10 2019"
}
];
We need to know the next holiday to track:
//Get the next holiday index
const nextHolidayIndex = () => holidays.reduce((prevResult,current, i) => {
const timeDif = Date.parse(current.time) - Date.now();
if(timeDif < 0)
return prevResult;
if(prevResult.index == -1 || timeDif < prevResult.diff) return {
index : i,
diff: timeDif
};
return prevResult;
}, {index : -1, diff: 0}).index;
The time remaining, like you did:
//Get time remaining for a given time
const getTimeRemaining = (timeTime) =>{
const t = Date.parse(timeTime) - Date.now();
const seconds = Math.floor( (t/1000) % 60 );
const minutes = Math.floor( (t/1000/60) % 60 );
const hours = Math.floor( (t/(1000*60*60)) % 24 );
const days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
And we need to initialize the component:
const initializeClock = (id, nextHoliday) => {
const clock = document.getElementById(id);
const message = clock.querySelector('.message');
const daysSpan = clock.querySelector('.days');
const hoursSpan = clock.querySelector('.hours');
const minutesSpan = clock.querySelector('.minutes');
const secondsSpan = clock.querySelector('.seconds');
let interval
function updateClock() {
const t = getTimeRemaining(nextHoliday.time);
daysSpan.innerHTML = t.days.toString();
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(interval);
message.innerHTML = nextHoliday.complete
}
}
message.innerHTML = `${nextHoliday.running}`
updateClock();
interval = setInterval(updateClock, 1000);
}
How about the html ?
<div id="timer">
<h1 class="message"></h1>
<div class="countdown">
<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>
</div>
Putting some visual to it:
#timer{
text-align: center;
background: #efefef;
font-family: sans-serif;
font-weight: 100;
display: inline-flex;
flex-direction: column;
padding: 24px;
}
h1{
color: #969696;
font-weight: 100;
font-size: 40px;
margin: 0 0 15px 0;
}
#timer .countdown{
color: #fff;
display: inline-block;
font-weight: 100;
text-align: center;
font-size: 30px;
}
#timer .countdown > div{
padding: 10px;
border-radius: 3px;
background: #6f7b75;
display: inline-block;
}
#timer .countdown div > span{
padding: 15px;
border-radius: 3px;
background: #03A9F4;
display: inline-block;
}
.smalltext{
padding-top: 5px;
font-size: 16px;
}
Then we just run the code:
const next = nextHolidayIndex()
if(next != -1){
initializeClock('timer', holidays[next]);
}
Here you go :)
const holidays = [
{
running: "Independence Day",
complete: "Happy Independence Day!",
time: "July 4 2019"
},
{
running: "Christmas",
complete: "Merry Xmas!",
time: "Dec 10 2019"
}
];
//Get the next holiday index
const nextHolidayIndex = () => holidays.reduce((prevResult,current, i) => {
const timeDif = Date.parse(current.time) - Date.now();
if(timeDif < 0)
return prevResult;
if(prevResult.index == -1 || timeDif < prevResult.diff) return {
index : i,
diff: timeDif
};
return prevResult;
}, {index : -1, diff: 0}).index;
//Get time remaining for a given time
const getTimeRemaining = (timeTime) =>{
const t = Date.parse(timeTime) - Date.now();
const seconds = Math.floor( (t/1000) % 60 );
const minutes = Math.floor( (t/1000/60) % 60 );
const hours = Math.floor( (t/(1000*60*60)) % 24 );
const days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
}
const initializeClock = (id, nextHoliday) => {
const clock = document.getElementById(id);
const message = clock.querySelector('.message');
const daysSpan = clock.querySelector('.days');
const hoursSpan = clock.querySelector('.hours');
const minutesSpan = clock.querySelector('.minutes');
const secondsSpan = clock.querySelector('.seconds');
let interval
function updateClock() {
const t = getTimeRemaining(nextHoliday.time);
daysSpan.innerHTML = t.days.toString();
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(interval);
message.innerHTML = nextHoliday.complete
startNext()
}
}
message.innerHTML = `${nextHoliday.running}`
updateClock();
interval = setInterval(updateClock, 1000);
}
const startNext = () => {
const next = nextHolidayIndex()
if(next != -1){
initializeClock('timer', holidays[next]);
}
}
startNext()
#timer{
text-align: center;
background: #efefef;
font-family: sans-serif;
font-weight: 100;
display: inline-flex;
flex-direction: column;
padding: 24px;
}
h1{
color: #969696;
font-weight: 100;
font-size: 40px;
margin: 0 0 15px 0;
}
#timer .countdown{
color: #fff;
display: inline-block;
font-weight: 100;
text-align: center;
font-size: 30px;
}
#timer .countdown > div{
padding: 10px;
border-radius: 3px;
background: #6f7b75;
display: inline-block;
}
#timer .countdown div > span{
padding: 15px;
border-radius: 3px;
background: #03A9F4;
display: inline-block;
}
.smalltext{
padding-top: 5px;
font-size: 16px;
}
<div id="timer">
<h1 class="message"></h1>
<div class="countdown">
<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>
</div>
In order to restart the counter we need to refresh the page. If you don't want it then, forget about the message, and just init the next after the previous reach 0.
const initializeClock = (id, nextHoliday) => {
//...
if (t.total <= 0) {
clearInterval(interval);
startNext()
}
//...
}
const startNext = () => {
const next = nextHolidayIndex()
if(next != -1){
initializeClock('timer', holidays[next]);
}
}
startNext()
I think this example goes around the question:
- you can add as many dates as you want,
- adjust the end date of their presentation before moving on to the next countdown.
I do some changing for cosmetic reasons...
// Set all the dates you want (no order needed)
const holidays = [
{ dat: 'July, 3 YYYY 23:59:59', end: 'July, 4 YYYY 23:59:59', msg:'Happy Independence Day!', bef:'Independence Day', Bcolor : '#39CCCC' }
, { dat: 'Dec, 24 YYYY 23:59:59', end: 'Dec, 26 YYYY 12:00:00', msg:'Merry Xmas!', bef:'Xmas', Bcolor : '#2ECC40' }
, { dat: 'Oct, 31 YYYY 17:59:59', end: 'Nov, 1 YYYY 06:00:00', msg:'Happy Halloween!', bef:'Halloween', Bcolor : '#F012BE' }
, { dat: 'Dec, 31 YYYY 23:59:59', end: 'Jan, 1 Y+1Y 01:00:00', msg:'Happy New Year!', bef:'New Year', Bcolor : '#FFDC00' }
];
// please note the use of 'YYYY' stand for 'any Year' and 'Y+1Y' stand fort 'any Following Year' for events repeating each year.
// Real year values are ok but old events will be ignored
// The color is here for example, you can disable it or change the idea by placing a picture in the background,
// and do the same countdown for each species
// Ready for everything:
const BODY_color = '#554a63' // standard Color of Background
, timer_on = document.querySelector('#timer-on')
, timer_off = document.querySelector('#timer-off')
, curDT = document.getElementById('currentDateTime')
, tCountDown = document.querySelectorAll('#countdown div span')
, xDays = 0
, xHours = 2
, xMins = 4
, xSecs = 6
, t_msg = document.querySelector('#timer-on h2')
, H_message = document.querySelector('#timer-off h1')
, one_Sec = 1000
, one_Min = one_Sec * 60
, one_Hour = one_Min * 60
, one_Day = one_Hour * 24
, Option_DT = { weekday: 'long', month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit'}
, Intl_F_DT = new Intl.DateTimeFormat('en-US', Option_DT )
;
/* Search function to set the countDown target
do : set interface to correct closest countdown
even if it is during a period before ending event
return : (js object )
start : time target of event
ending : time target of event ending
complete : Boolean value (set to false) according to the countdown is not completed
Bcolor : paint color value for background during ending period
*/
function SetNextHolidayTarget()
{
let now = new Date()
, nowTime = now.getTime()
, thisYear = now.getFullYear()
, closest = one_Day *365 /// start with big closest date
, target = null
;
// default display
timer_on.classList.remove('noDisplay')
timer_off.classList.add('noDisplay')
document.body.style.backgroundColor = BODY_color;
holidays.forEach(H=> // search loop for the closest date in 'holidays'
{
let s_date = H.dat.replace('YYYY', thisYear ) // change 'YYYY' string to current year value
, e_date = H.end.replace('YYYY', thisYear ).replace('Y+1Y', (thisYear +1) )
, t_date = new Date(s_date) // target date
, z_date = new Date(e_date) // target date ending
;
if ( t_date < now && z_date < now ) // if target date and ending are before today, this set them for next year
{
s_date = H.dat.replace('YYYY', (thisYear +1))
e_date = H.end.replace('YYYY', (thisYear +1)).replace('Y+1Y', (thisYear +2) )
t_date = new Date(s_date)
z_date = new Date(e_date)
}
let t_datesDiff = t_date.getTime() - nowTime
, z_datesDiff = z_date.getTime() - nowTime
if ( closest > t_datesDiff && t_datesDiff > 0 ) // if it is closer than the dates already seen
{
closest = t_datesDiff
t_msg.textContent = H.bef
H_message.textContent = H.msg
target = { start: t_date.getTime(), ending: z_date.getTime(), complete: false, Bcolor: H.Bcolor }
}
if ( closest > z_datesDiff && z_datesDiff > 0 ) // case of inside countdown period
{
closest = z_datesDiff
t_msg.textContent = H.bef
H_message.textContent = H.msg
target = { start: z_date.getTime(), ending: z_date.getTime(), complete: true, Bcolor: H.Bcolor }
}
})
if ( target.complete ) // if inside countdown period
{
timer_on.classList.add('noDisplay')
timer_off.classList.remove('noDisplay')
document.body.style.backgroundColor = target.Bcolor;
}
return target
}
// **** INIT ****
var holidazeEnd = SetNextHolidayTarget()
// first TEST to prove -------------------------------------------------------------------
if (true) // (set to false to remove this test)
{
let now = new Date()
, start = new Date()
, ending = new Date()
;
// default display
timer_on.classList.remove('noDisplay')
timer_off.classList.add('noDisplay')
document.body.style.backgroundColor = BODY_color;
start.setTime(now.getTime() + (one_Sec *20) );
ending.setTime(start.getTime() + (one_Sec *15) );
t_msg.textContent = 'Test to 20s'
H_message.textContent = 'happy test ! (15s)'
holidazeEnd = { start , ending , complete: false, Bcolor: 'orange' }
} // =====================================================================================
// TIMER Interval //
// - - - - - - - - //
var timerInterval = setInterval(function ()
{
let now = new Date()
, t = holidazeEnd.start - now.getTime()
;
curDT.textContent = Intl_F_DT.format(now) // show date time upper right
if (t >= 0 )
{
if (!holidazeEnd.complete)
{
tCountDown[xDays].textContent = Math.floor(t / one_Day);
tCountDown[xHours].textContent = ('0' + Math.floor((t % one_Day) / one_Hour)).slice(-2);
tCountDown[xMins].textContent = ('0' + Math.floor((t % one_Hour) / one_Min)).slice(-2);
tCountDown[xSecs].textContent = ('0' + Math.floor((t % one_Min) / one_Sec)).slice(-2);
}
// else { nothing to do }
}
else // elapsed time !
{
if ( holidazeEnd.complete ) // elapsed time of ' holiday ' message
{
holidazeEnd = SetNextHolidayTarget() // searching the next one in the ' holidays ' list
}
else // show ' holiday ' message
{
timer_on.classList.add('noDisplay')
timer_off.classList.remove('noDisplay')
holidazeEnd.complete = true;
holidazeEnd.start = holidazeEnd.ending
document.body.style.backgroundColor = holidazeEnd.Bcolor
}
}
}, 1000);
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
background-color: #554a63;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#currentDateTime {
text-align: right;
padding: .2em 1em 0 0;
color: white;
font-weight: lighter;
font-stretch: expanded
}
.noDisplay {
display:none !important
}
.timer{
position: absolute;
top: 50%;
left: 0;
display: block;
width: 100%;
transform: translateY(-50%);
}
.timer h1 {
text-align: center;
font-size: 4em;
font-weight: bold;
color: white;
background-color: rgba(96, 87, 151, 0.315);
padding: .8em 0;
}
.timer h2 {
text-align: center;
padding: .3em 0;
}
#countdown {
display: table;
margin: 0 auto;
padding: 1em 0;
background-color: rgba(96, 87, 151, 0.315);
min-width: 26em;
}
#countdown div {
display: block;
float: left;
height: 5em;
width: 6em;
border-right: 1px solid grey;
}
#countdown div:first-child {
width: 8em;
}
#countdown div:last-child {
border-right: none;
}
#countdown div span {
display: inline-block;
width: 100%;
text-align: center;
color: white
}
#countdown div span:first-child {
font-size: 3em;
}
#countdown div span:last-child {
font-size: .8em;
padding: 1em .2em;
}
<p id="currentDateTime"></p>
<div id="timer-on" class="timer">
<h2> .. </h2>
<div id="countdown">
<div><span>.</span><span>Days</span></div>
<div><span>.</span><span>Hours</span></div>
<div><span>.</span><span>Minutes</span></div>
<div><span>.</span><span>Seconds</span></div>
</div>
</div>
<div id="timer-off" class="timer noDisplay">
<h1>!</h1>
</div>
Related
When I want to reset my stopwatch and start it again the timer begins at the stop-point of the previous timer execution but I want that the timer begins at zero. I tried different ways to solve this problem but my tries did not work. What is my failure? The considered area in my JavaScript is marked up.
window.onload = function () {
//global variables
let interval = null;
let timerId = null;
let y = 3.90;
let reversal = 20
const output = document.querySelector('output');
let maintime = document.getElementById('maintime');
const start = document.getElementById('actioner');
const clear = document.getElementById('reseter');
let [milliseconds, seconds, minutes, hours] = [0, 0, 0, 0];
//If start is clicked
start.addEventListener('click', () => {
buttonAndTimer();
startDrive();
}); // end of func
function buttonAndTimer() {
start.innerText = 'Stop';
if (!interval) {
interval = setInterval(() => {
run();
}, 10);
} else {
clearInterval(interval)
start.innerText = 'Resume';
interval = null;
};
}
function run() {
milliseconds += 10;
if (milliseconds == 1000) { //note: 1000 milliseconds are 1 seconds
milliseconds = 0;
seconds++;
};
if (seconds == 60) {
seconds = 0;
minutes++;
};
if (minutes == 60) {
minutes == 0
hours++;
};
h = hours < 10 ? '0' + hours : hours;
m = minutes < 10 ? '0' + minutes : minutes;
s = seconds < 10 ? '0' + seconds : seconds;
ms = milliseconds < 100 ? '00' + milliseconds : milliseconds;
//Template Literals
maintime.innerHTML = `${h} : ${m} : ${s} : ${ms} `
};
//calculating price
function startDrive() {
if (start.innerText != 'Resume') {
output.innerHTML = y.toFixed(2) + '€';
timerId = setInterval(() => {
if (y < reversal) {
y += 0.14375;
} else if (y > reversal) {
y += 0.103125;
}
output.innerHTML = y.toFixed(2) + "€";
}, 5000);
}
/*Considered area */
if (start.innerText == 'Resume') {
clearInterval(timerId);
}
} //end of func
// considered area
clear.addEventListener('click', () => {
clearInterval(interval);
interval = null;
maintime.innerHTML = '00:00:00:000';
start.innerText = 'Start'
clearInterval(timerId);
timerId = 0;
output.innerHTML = "";
})
} //end of window.load
#box {
display: flex;
justify-content: center;
align-items:center;
flex-direction: column;
gap: 5px;
}
span, #maintime{
color:#74bde0;
width:15vh;
text-align: center;
max-width:20vh;
}
.button {
border:none;
border-radius: 30px;
cursor: pointer;
color:#74bde0;
box-shadow: 1px 1px 1px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
}
output {
border: 1px solid;
border-color:#74bde0 ;
border-radius: 5px;
height: 10vh;
width: 30vh;
text-align: center;
color:#74bde0;
line-height: 500%;
box-shadow: rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.1) 0px 16px 56px;
}
#card {
background-color: #2f2f2f;
width: 80vh;
height: 10vh;
border:1px solid;
border-color:blueviolet;
border-radius: 30px;
}
<body>
<div id="box">
<button class='button' id='actioner'>Start</button>
<output></output>
<button class='button' id='reseter'>Reset</button>
<div id='mainstopwatch'>
<div id='maintime'>
<span class='span' id="mainhour">00:</span>
<span class='span' id="mainminute">00:</span>
<span class='span' id="mainsecond">00:</span>
<span class='span' id="milliseconds">000</span>
</div>
</div>
</body>
Fixed it.. I hope this is acceptable answer..
window.onload = function () {
//global variables
let interval = null;
let timerId = null;
let y = 3.90;
let reversal = 20
const output = document.querySelector('output');
let maintime = document.getElementById('maintime');
const start = document.getElementById('actioner');
const clear = document.getElementById('reseter');
let [milliseconds, seconds, minutes, hours] = [0, 0, 0, 0];
//If start is clicked
start.addEventListener('click', () => {
console.log("start clicked.. ")
buttonAndTimer();
startDrive();
}); // end of func
function buttonAndTimer() {
start.innerText = 'Stop';
if (!interval) {
interval = setInterval(() => {
run();
}, 10);
} else {
clearInterval(interval)
start.innerText = 'Resume';
interval = null;
};
}
function run() {
milliseconds += 10;
if (milliseconds == 1000) { //note: 1000 milliseconds are 1 seconds
milliseconds = 0;
seconds++;
};
if (seconds == 60) {
seconds = 0;
minutes++;
};
if (minutes == 60) {
minutes == 0
hours++;
};
h = hours < 10 ? '0' + hours : hours;
m = minutes < 10 ? '0' + minutes : minutes;
s = seconds < 10 ? '0' + seconds : seconds;
ms = milliseconds < 100 ? '00' + milliseconds : milliseconds;
//Template Literals
maintime.innerHTML = `${h} : ${m} : ${s} : ${ms} `
};
//calculating price
function startDrive() {
if (start.innerText != 'Resume') {
output.innerHTML = y.toFixed(2) + '€';
timerId = setInterval(() => {
if (y < reversal) {
y += 0.14375;
} else if (y > reversal) {
y += 0.103125;
}
output.innerHTML = y.toFixed(2) + "€";
}, 5000);
}
/*Considered area */
if (start.innerText == 'Resume') {
clearInterval(timerId);
}
} //end of func
// considered area
clear.addEventListener('click', () => {
console.log("clear clicked.. ")
clearInterval(interval);
interval = null;
maintime.innerHTML = '00:00:00:000';
start.innerText = 'Start'
clearInterval(timerId);
timerId = 0;
output.innerHTML = "";
milliseconds = 0
seconds = 0
minutes = 0
hours = 0
})
} //end of
I'm working on a page on my wordpress site where i pull data from the backend. The data has an end_date column that i use to display a countdown timer i.e. from the current date time till the end_date.
This is how i approach it:
This is the html element that will display the timer:
<div class="t1-auction-timer"></div>
This is the javascript that creates the timer:
var countDownDate = new Date("<?=$endDate?>").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);
var timer = document.querySelectorAll(".t1-auction-timer");
for (var i = 0; i < timer.length; i++)
{
timer[i].innerHTML = '<ul class="clock-value"><li class="clock-days">' + padNumber(days) + '<small>days</small> </li><li class="clock-separator">:</li><li class="clock-hours"> ' + padNumber(hours) + ' <small>hrs</small> </li><li class="clock-separator">:</li><li class="clock-minutes"> ' + padNumber(minutes) + ' <small>min</small> </li><li class="clock-separator">:</li><li class="clock-seconds"> ' + padNumber(seconds) + ' <small>sec</small> </li></ul>';
}
if ( distance < 0 )
{
clearInterval(x);
for (var i = 0; i < timer.length; i++)
{
timer[i].innerHTML = "EXPIRED";
}
}
}, 1000);
function padNumber(number)
{
if( number == 0 )
{
number = "0" + number;
}
else if( number > 9 )
{
number;
}
else
{
number = "0" + number;
}
return number;
}
The <?=$endDate?> variable is passed from php. Its being passed correctly.
The number of timers to be displayed will be dynamic depending on the records in the database. The issue I'm facing is: I only get timer created from the first record. Its duplicated across all posts being displayed on the page. I suspect this has to do with my .t1-auction-timer class loop but I haven't figured it out yet.
You can try this approach which uses the data attribute.
var auctionTimer = document.getElementsByClassName('t1-auction-timer');
var interval = setInterval(function() {
if(auctionTimer.length == 0 ){clearFunction()}
for(var i= 0; i < auctionTimer.length; i++){
var endDate = auctionTimer[i].getAttribute('data-end-date')
var int = createTimer(endDate, auctionTimer[i]);
}
},1000)
function clearFunction() {
clearInterval(interval);
}
function createTimer(endDate, element){
var countDownDate = new Date(endDate).getTime();
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);
element.innerHTML = '<ul class="clock-value"><li class="clock-days">' + padNumber(days) + '<small>days</small> </li><li class="clock-separator">:</li><li class="clock-hours"> ' + padNumber(hours) + ' <small>hrs</small> </li><li class="clock-separator">:</li><li class="clock-minutes"> ' + padNumber(minutes) + ' <small>min</small> </li><li class="clock-separator">:</li><li class="clock-seconds"> ' + padNumber(seconds) + ' <small>sec</small> </li></ul>';
if ( distance < 0 )
{
if ( element.classList.contains("t1-auction-timer") ){
element.classList.remove("t1-auction-timer")
element.classList.add("expierd")
expierd()
}
}
}
function padNumber(number)
{
if( number == 0 )
{
number = "0" + number;
}
else if( number > 9 )
{
number;
}
else
{
number = "0" + number;
}
return number;
}
function expierd(){
var expierdDate = document.getElementsByClassName('expierd');
for(var i= 0; i < expierdDate.length; i++){
expierdDate[i].innerHTML = "expierd"
}
}
<div class="t1-auction-timer" data-end-date="2021-01-03 16:15"></div>
<div class="t1-auction-timer" data-end-date="2021-01-01 16:15"></div>
<div class="t1-auction-timer" data-end-date="2021-01-04 16:15"></div>
An approach which directly uses a lot from the OP's code almost unchanged does, within an interval, process a collection of timer elements by (re)rendering each timer again and again.
A timer element's markup base will be the already above (in the comments) mentioned <time/> element where the the OP's endDate will be retrieved from this element's datetime attribute (also again and again) ...
function padNumber(number) {
return (number >= 10) && number || `0${ number }`;
}
function updateTimer(nodeList, timer, timerData) {
// GUARD
if (timer.dataset.isExpired === "true") {
return;
}
const countDownDate = new Date(timer.dateTime).getTime();
const now = new Date().getTime();
const distance = countDownDate - now;
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);
if (distance >= 0) {
timer.innerHTML = `<ul class="clock-value">
<li class="clock-days">${ padNumber(days) } <small>days</small></li>
<li class="clock-hours">${ padNumber(hours) } <small>hrs</small></li>
<li class="clock-minutes">${ padNumber(minutes) } <small>min</small></li>
<li class="clock-seconds">${ padNumber(seconds) } <small>sec</small></li>
</ul>`;
} else {
timer.innerHTML = "EXPIRED";
timer.dataset.isExpired = "true";
// clear the interval only in case each timer has been expired.
if ([
...nodeList
].every(elmNode =>
elmNode.dataset.isExpired === "true"
)) {
clearInterval(timerData.timerId);
}
}
}
function updateAllTimers(nodeList, timerData) {
nodeList.forEach(timer => updateTimer(nodeList, timer, timerData));
}
function initializeAllTimers() {
const nodeList = document.querySelectorAll('.t1-auction-timer');
const data = {
timerId: null
};
updateAllTimers(nodeList, data);
data.timerId = setInterval(updateAllTimers, 1000, nodeList, data);
}
initializeAllTimers();
body {
margin: 0;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
padding: 2px 10px 3px 10px;
}
li .auction-name {
font-family: courier;
}
ul.clock-value,
ul.clock-value > li {
padding: 0;
display: inline-block;
}
ul.clock-value > li {
font-family: ui-monospace;
}
ul.clock-value li:not(:last-child) small:after {
content: ":";
display: inline-block;
width: .7em;
font-weight: bold;
text-align: right;
}
<ul>
<li>
Auction <span class="auction-name">Foo</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-21 22:15">2020-12-21 22:15</time>
</li>
<li>
Auction <span class="auction-name">Bar</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-22 03:15">2020-12-22 03:15</time>
</li>
<li>
Auction <span class="auction-name">Baz</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-22 11:30">2020-12-22 11:30</time>
</li>
<li>
Auction <span class="auction-name">Biz</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-22 14:45">2020-12-22 14:45</time>
</li>
<li>
Auction <span class="auction-name">Buz</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-23 10:20">2020-12-23 10:20</time>
</li>
<li>
Auction <span class="auction-name">Fiz</span> expires at/in ...
<time class="t1-auction-timer" datetime="2020-12-24 10:55">2020-12-24 10:55</time>
</li>
<li>
Auction <span class="auction-name">Faz</span> expires at/in ...
<time class="t1-auction-timer" datetime="2021-01-04 16:15">2021-01-04 16:15</time>
</li>
</ul>
The above approach might be changed towards creating a list of already pre-rendered timer components where each component's update is not anymore based on assigning a huge piece of always newly created HTML markup to a DOM node's innerHTML.
In order to enable a more generic / flexible usage of such components, one now can pass a template-string of custom timer-markup as well as a custom "expired" message to the initializing method. In addition any component now gets identified by its data-countdown-component attribute which makes the creation / initialization process independent from any forced or just layout-related CSS class-names.
function emptyElementNode(elmNode) {
Array
.from(elmNode.childNodes)
.forEach(node => node.remove());
}
function createTemplateFromMarkup(templateMarkup) {
const container = document.createElement('div');
container.innerHTML = String(templateMarkup);
return container.firstElementChild;
}
function getTimeMeasureFromMilliseconds(value) {
let days = (value / 3600000 / 24);
let hours = ((days - Math.floor(days)) * 24);
let minutes = ((hours - Math.floor(hours)) * 60);
let seconds = ((minutes - Math.floor(minutes)) * 60);
days = Math.floor(days);
hours = Math.floor(hours);
minutes = Math.floor(minutes);
seconds = Math.floor(seconds + 0.001);
seconds = ((seconds < 60) && seconds) || 0;
minutes = ((minutes < 60) && minutes) || 0;
hours = ((hours < 24) && hours) || 0;
return { days, hours, minutes, seconds };
}
function formatMeasure(value) {
return ((value >= 10) && value || `0${ value }`);
}
function createTimerComponent(rootNode, template, expiredMessage) {
const expirationDate = new Date(rootNode.dateTime);
const [
elmDays,
elmHours,
elmMinutes,
elmSeconds
] = [...template.querySelectorAll([
'[data-countdown-days]',
'[data-countdown-hours]',
'[data-countdown-minutes]',
'[data-countdown-seconds]',
].join(','))];
const component = {
rootNode,
elmDays,
elmHours,
elmMinutes,
elmSeconds,
isExpired: false,
expiredMessage,
expiresTimestamp: expirationDate.getTime(),
};
emptyElementNode(component.rootNode);
rootNode.dateTime = expirationDate.toUTCString();
rootNode.appendChild(template);
return component;
}
function updateTimer(componentList, component, timerData) {
// GUARD
if (component.isExpired) {
return;
}
const { dateNow } = timerData;
const { expiresTimestamp } = component;
const { elmDays, elmHours, elmMinutes, elmSeconds } = component;
const time = (expiresTimestamp - dateNow);
if (time >= 0) {
const measures = getTimeMeasureFromMilliseconds(time);
elmSeconds.textContent = formatMeasure(measures.seconds);
elmMinutes.textContent = formatMeasure(measures.minutes);
elmHours.textContent = formatMeasure(measures.hours);
elmDays.textContent = formatMeasure(measures.days);
} else {
component.isExpired = true;
emptyElementNode(component.rootNode);
component.rootNode.textContent = component.expiredMessage;
// clear the interval only in case each timer has been expired.
if (componentList.every(item => item.isExpired)) {
clearInterval(timerData.timerId);
}
}
}
function updateAllTimers(componentList, timerData) {
timerData.dateNow = Date.now();
componentList.forEach(component =>
updateTimer(componentList, component, timerData)
);
}
function initializeAllTimers(templateMarkup, expiredMessage = 'Closed') {
const defaultTemplateMarkup = [
'<span>',
'<span data-countdown-days></span> <small>days</small>, ',
'<span data-countdown-hours></span> <small>hours</small>, ',
'<span data-countdown-minutes></span> <small>minutes</small>, ',
'<span data-countdown-seconds></span> <small>seconds</small>',
'</span>',
].join('');
let template = createTemplateFromMarkup(templateMarkup);
if (!template || template.querySelectorAll([
'[data-countdown-days]',
'[data-countdown-hours]',
'[data-countdown-minutes]',
'[data-countdown-seconds]',
].join(',')).length !== 4) {
template = createTemplateFromMarkup(defaultTemplateMarkup);
}
const componentList = [
...document.querySelectorAll('[data-countdown-component]')
].map(elmNode =>
createTimerComponent(elmNode, template.cloneNode(true), expiredMessage)
);
const data = {
timerId: null,
dateNow: null,
};
updateAllTimers(componentList, data);
data.timerId = setInterval(updateAllTimers, 1000, componentList, data);
}
initializeAllTimers(`<ul class="clock-value">
<li class="clock-days">
<span data-countdown-days></span> <small>days</small>
</li>
<li class="clock-hours">
<span data-countdown-hours></span> <small>hours</small>
</li>
<li class="clock-minutes">
<span data-countdown-minutes></span> <small>minutes</small>
</li>
<li class="clock-seconds">
<span data-countdown-seconds></span> <small>seconds</small>
</li>
</ul>`, 'Expired');
body {
margin: 0;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
padding: 2px 10px 3px 10px;
}
li .auction-name {
font-family: courier;
}
ul.clock-value,
ul.clock-value > li {
padding: 0;
display: inline-block;
}
ul.clock-value > li {
font-family: ui-monospace;
}
ul.clock-value li:not(:last-child) small:after {
content: ":";
display: inline-block;
width: .7em;
font-weight: bold;
text-align: right;
}
<ul>
<li>
Auction <span class="auction-name">Foo</span> expires at/in ...
<time data-countdown-component datetime="2020-12-21 22:15">2020-12-21 22:15</time>
</li>
<li>
Auction <span class="auction-name">Bar</span> expires at/in ...
<time data-countdown-component datetime="2020-12-22 03:15">2020-12-22 03:15</time>
</li>
<li>
Auction <span class="auction-name">Baz</span> expires at/in ...
<time data-countdown-component datetime="2020-12-22 11:30">2020-12-22 11:30</time>
</li>
<li>
Auction <span class="auction-name">Biz</span> expires at/in ...
<time data-countdown-component datetime="2020-12-22 14:45">2020-12-22 14:45</time>
</li>
<li>
Auction <span class="auction-name">Buz</span> expires at/in ...
<time data-countdown-component datetime="2020-12-23 10:20">2020-12-23 10:20</time>
</li>
<li>
Auction <span class="auction-name">Fiz</span> expires at/in ...
<time data-countdown-component datetime="2020-12-24 10:55">2020-12-24 10:55</time>
</li>
<li>
Auction <span class="auction-name">Faz</span> expires at/in ...
<time data-countdown-component datetime="2021-01-04 16:15">2021-01-04 16:15</time>
</li>
</ul>
Whenever I refresh my browser its restarting from the start. I uploaded it on server..I'm getting the same result.
Here's my code:
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()) + 33 * 24 * 60 * 60 * 1000);
initializeClock('clockdiv', deadline);
#clockdiv {
font-family: Calibri;
color: #001a00;
display: inline-block;
font-weight: 10;
text-align: center;
font-size: 30px;
}
#clockdiv>div {
padding: 10px;
border-radius: 3px;
display: inline-block;
}
.smalltext {
padding-top: 5px;
font-size: 16px;
}
<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>
Here's the fiddle- code
What am I doing wrong here?
At first I thought it'll be fine if I upload it on server..but still getting the same result.
If there's another code..please help me out or guide me..how to do it!
Thanks!
It is because of this line
var deadline = new Date(Date.parse(new Date()) + 33 * 24 * 60 * 60 * 1000);
You keep setting the date to 33 days in the future, so every time the page loads this is set.
If you change this line to the following and pass in your desired date.
var deadline = new Date(Date.parse('2017-10-30'));
Run code snippet below.
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('2017-10-30'));
initializeClock('clockdiv', deadline);
#clockdiv {
font-family: Calibri;
color: #001a00;
display: inline-block;
font-weight: 10;
text-align: center;
font-size: 30px;
}
#clockdiv>div {
padding: 10px;
border-radius: 3px;
display: inline-block;
}
.smalltext {
padding-top: 5px;
font-size: 16px;
}
<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>
When you set
var deadline = new Date(Date.parse(new Date()) + 33 * 24 * 60 * 60 * 1000);
every time you load the script, it will always be 33 days (and so on) from now. So you'll have to give the script a fixed deadline like so:
var deadline = new Date(Date.parse('2017-10-12'));
My problem is that my upcounter lost 1 day.
if i set the endDateTime to 1 year and 1 day before or after today it show the right time, but if i set it to exactly 1 year before today it shows the wrong day and month. And if i put the code of updateTimer to fiddlejs.net and test it if it shows the right time than is everything right.
sorry for my bad english :)
function updateTimer() {
//change endDateTime to your actual time minus 1 year
var endDateTime = new moment("2016-04-03 4:00:00");
var startDateTime = moment();
var timeLeft = endDateTime + startDateTime;
var timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var years = Math.floor(moment.duration(timeLeft).asYears());
startDateTime = startDateTime.subtract(years, 'years');
timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var months = Math.floor(moment.duration(timeLeft).asMonths());
startDateTime = startDateTime.subtract(months, 'months');
timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var days = Math.floor(moment.duration(timeLeft).asDays());
startDateTime = startDateTime.subtract(days, 'days');
timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var hours = Math.floor(moment.duration(timeLeft).asHours());
startDateTime = startDateTime.subtract(hours, 'hours');
timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var minutes = Math.floor(moment.duration(timeLeft).asMinutes());
startDateTime = startDateTime.subtract(minutes, 'minutes');
timeLeft = startDateTime.diff(endDateTime, 'milliseconds', true);
var seconds = Math.floor(moment.duration(timeLeft).asSeconds());
var total = timeLeft;
if (years < 10) years = "0" + years;
if (months < 10) months = "0" + months;
if (days < 10) days = "0" + days;
if (hours < 10) hours = "0" + hours;
if (minutes < 10) minutes = "0" + minutes;
if (seconds < 10) seconds = "0" + seconds;
return {
'years': years,
'months': months,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds,
'total': total,
}
}
function animateClock(span) {
span.className = "turn";
setTimeout(function() {
span.className = "";
}, 700);
}
function initializeClock(id, endtime) {
var clock = document.getElementById(id);
var yearsSpan = clock.querySelector('.years');
var monthsSpan = clock.querySelector('.months');
var daysSpan = clock.querySelector('.days');
var hoursSpan = clock.querySelector('.hours');
var minutesSpan = clock.querySelector('.minutes');
var secondsSpan = clock.querySelector('.seconds');
function updateClock() {
var t = updateTimer();
yearsSpan.innerHTML = t.years;
monthsSpan.innerHTML = ('0' + t.months).slice(-2);
daysSpan.innerHTML = ('0' + t.days).slice(-2);
hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);
//animation
// var daysMonth = moment(t.years-t.months-t.days).daysInMonth('month');
var spans = clock.getElementsByTagName("span");
animateClock(spans[5]);
if (t.seconds == 0) animateClock(spans[4]);
if (t.minutes == 59 && t.seconds == 59) animateClock(spans[3]);
if (t.hours == 23 && t.minutes == 59 && t.seconds == 59) animateClock(spans[2]);
//if (t.months == daysMonth && t.hours == 23 && t.minutes == 59 && t.seconds == 59) animateClock(spans[1]);
// 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 {
font-family: sans-serif;
color: #2DA2DB;
display: inline-block;
font-weight: 100;
text-align: center;
font-size: 30px;
}
#clockdiv>div {
margin-bottom: 5px;
padding: 6px;
border-radius: 3px;
background: #991b1f;
display: inline-block;
border-style: solid;
border-color: black;
}
#clockdiv>div:nth-child(2) {
background: #aa1e23;
}
#clockdiv>div:nth-child(3) {
background: #bc2025;
}
#clockdiv>div:nth-child(4) {
background: #cc2027;
}
#clockdiv>div:nth-child(5) {
background: #dc1f26;
}
#clockdiv>div:nth-child(6) {
background: #ec1e24;
}
#clockdiv div>span {
font-size: 30px;
letter-spacing: 3px;
font-family: 'pixel', monospace;
color: #white;
text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000;
padding: 6px;
border-radius: 3px;
background: #333;
display: inline-block;
border-style: solid;
border-color: black;
}
<script src="http://momentjs.com/downloads/moment.js"></script>
<div id="clockdiv">
<div>
<span class="years"></span>
<div class="smalltext">Jahre</div>
</div>
<div>
<span class="months"></span>
<div class="smalltext">Monate</div>
</div>
<div>
<span class="days"></span>
<div class="smalltext">Tage</div>
</div>
<div>
<span class="hours"></span>
<div class="smalltext">Stunden</div>
</div>
<div>
<span class="minutes"></span>
<div class="smalltext">Minuten</div>
</div>
<div>
<span class="seconds"></span>
<div class="smalltext">Sekunden</div>
</div>
</div>
I have a time progress bar. I use this code. In this time bar, I get the time in seconds, but I want to show minute, second, hour in the time progress bar.
var timer = 0,
timeTotal = 2500,
timeCount = 20,
timeStart = 0,
cFlag;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text((percentage / 1000).toFixed(2) + "\00a0s");
}
function animateUpdate() {
var perc = new Date().getTime() - timeStart;
if(perc < timeTotal) {
updateProgress(perc);
timer = setTimeout(animateUpdate, timeCount);
} else {
updateProgress(timeTotal);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag == undefined) {
clearTimeout(timer);
cFlag = true;
timeStart = new Date().getTime();
animateUpdate();
}
else if (!cFlag) {
cFlag = true;
animateUpdate();
}
else {
clearTimeout(timer);
cFlag = false;
}
});
});
jsfiddle.net/McNetic/hnfRe/397
You can try this. DEMO LINK HERE
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0 s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
JS...
var timer = 0,
timeTotal = 250000,
timeCount = 20,
timeStart = 0,
cFlag;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
var totalSec= (percentage / 1000);
var min = parseInt(totalSec/60);
var sec = parseInt(totalSec%60);
var hr= parseInt(min/60);
min = parseInt(min % 60);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text(hr+":"+min+":"+sec + "");
}
function animateUpdate() {
var perc = new Date().getTime() - timeStart;
if(perc < timeTotal) {
updateProgress(perc);
timer = setTimeout(animateUpdate, timeCount);
} else {
updateProgress(timeTotal);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag == undefined) {
clearTimeout(timer);
cFlag = true;
timeStart = new Date().getTime();
animateUpdate();
}
else if (!cFlag) {
cFlag = true;
animateUpdate();
}
else {
clearTimeout(timer);
cFlag = false;
}
});
});
CSS...
#pbar_outerdiv { cursor: pointer; }
With percentaje (line 11):
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text(x.toFixed(2) + '%');
}
SEE DEMO
With hours, minutes and seconds:
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress(percentage) {
var x = (percentage/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(percentage/hours) + 'h ' + Math.floor(percentage/minutes) + 'm ' + Math.floor(percentage/seconds) + 's');
}
SEE DEMO.
I think for that you should use requestAnimationFrame:
var timeTotal = 2500,
timeStart = 0,
cFlag = false;
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress() {
var time = new Date().getTime() - timeStart;
var x = (time/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(time/hours) + 'h ' + Math.floor(time/minutes) + 'm ' + Math.floor(time/seconds) + 's');
if(time <= timeTotal && cFlag) {
requestAnimationFrame(updateProgress);
}
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag === false) {
cFlag = true;
timeStart = new Date().getTime();
updateProgress();
}
else {
cFlag = false;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0h 0m 0s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
UPDATED WITH PAUSE ALLOW AND RESUME:
var timeTotal = 5 * minutes,
timePaused = 0,
timePausedStart = 0,
timeStart = 0,
cFlag = false,
stopped = false;
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
function updateProgress() {
if( !timePausedStart ) { // if not paused
var time = new Date().getTime() - timeStart - timePaused;
var x = (time/timeTotal)*100,
y = x.toFixed(3);
$('#pbar_innerdiv').css("width", x + "%");
$('#pbar_innertext').css("left", x + "%").text( Math.floor(time/hours%24) + 'h ' + Math.floor(time/minutes%60) + 'm ' + Math.floor(time/seconds) + 's');
if(time > timeTotal) {
cFlag = false;
}
if( Math.floor(time/seconds) == 3*60+30 && !stopped){ // pause at 3 m 30 s
stopped = true;
pause();
}
}
if( cFlag )
requestAnimationFrame(updateProgress);
}
$(document).ready(function() {
$('#pbar_outerdiv').click(function() {
if (cFlag === false) {
cFlag = true;
timeStart = new Date().getTime();
timePaused = 0;
updateProgress();
} else if( cFlag === true && timePausedStart ){ // reset pause
timePaused += new Date().getTime() - timePausedStart;
timePausedStart = 0;
}
else {
pause();
}
});
});
var pause = function(){
timePausedStart = new Date().getTime();
};
#pbar_outerdiv { cursor: pointer; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pbar_outerdiv" style="width: 300px; height: 20px; border: 1px solid grey; z-index: 1; position: relative; border-radius: 5px; -moz-border-radius: 5px;">
<div id="pbar_innerdiv" style="background-color: lightblue; z-index: 2; height: 100%; width: 0%;"></div>
<div id="pbar_innertext" style="z-index: 3; position: absolute; top: 0; left: 0; height: 100%; color: black; font-weight: bold; text-align: center;">0h 0m 0s</div>
</div>
<p>Click once to start!</p>
<p>Click again to toggle Start/Stop</p>
Instead of printing (percentage / 1000).toFixed(2), you can use percentage to split your time in millisecond to h:m's.ms
You can simply compute the desired values with integer divisions
h = Math.floor(percentage / 3600000);
m = Math.floor((percentage - h * 3600000) / 60000);
s = Math.floor((percentage - h * 3600000 - m * 60000) / 1000);
ms = Math.floor(percentage - h * 3600000 - m * 60000 - s * 1000);
Then, you can just use toString() to convert your int to strings. I concatenated the values with 0 and and used slice() to keep only the two last character. This allow you to print hours, minutes, ... in two digits format
text = ("0" + h.toString() ).slice(-2) + ":" +
("0" + m.toString() ).slice(-2) + "'" +
("0" + s.toString() ).slice(-2) + "\"" +
("0" + ms.toString()).slice(-2);