why progressbar works separately from countdown - javascript

I want to create progress bar countdown.
But the problem is that decimals don't change like 10 9 8 7 .. simultaniously.
this is html :
<progress id="prg" value ="0" max="10"></progress>
<p id="counting">10</p>
This is my js script :
var reverse_count = 10;
var downloadTimer = setInterval(function(){
document.getElementById('prg').value = 10 - --reverse_count;
if(reverse_count <= 0) {
clearInterval (downloadTimer);
document.getElementById('counting').innerHTML = reverse_count;
}
}, 1000);

You need to take document.getElementById('counting').innerHTML = reverse_count; out of the if statement, like so:
var reverse_count = 10;
var downloadTimer = setInterval(function() {
document.getElementById('prg').value = 10 - --reverse_count;
if (reverse_count <= 0) {
clearInterval(downloadTimer);
}
document.getElementById('counting').innerHTML = reverse_count;
}, 1000);
<progress id="prg" value="0" max="10"></progress>
<p id="counting">10</p>

You just added the right statement in the wrong place. The update of the countdown label should also be done each time the interval callback is executed, as you do with the update of the <progress> value, not only once just before calling clearInterval:
const progressBar = document.getElementById('progressBar');
const countdownLabel = document.getElementById('countdownLabel');
let countdown = 10;
const downloadTimer = setInterval(() => {
// This is executed multiple times until the interval is cleared:
countdownLabel.innerHTML = --countdown;
progressBar.value = 10 - countdown;
if (countdown <= 0) {
// This is only executed once when the countdown gets to 0:
clearInterval(downloadTimer);
}
}, 1000);
<progress id="progressBar" value ="0" max="10"></progress>
<p id="countdownLabel">10</p>

In your code the countdown updates iff reverse_count <= 0.
var reverse_count = 10;
var downloadTimer = setInterval(function(){
document.getElementById('prg').value = 10 - --reverse_count;
document.getElementById('counting').innerHTML = reverse_count;
if(reverse_count <= 0) {
clearInterval (downloadTimer);
}
}, 1000);
<progress id="prg" value ="0" max="10"></progress>
<p id="counting">10</p>

Related

JavaScript Local Storage Second Counter

my question is the following: Is it possible to create a second counter using local storage? I mean you load the page, the counter starts counting from 1 one by one. You reload the page at 5seconds, and the counter won't resets but continues the counting from 5. Is it possible?
I have a code with a simple sec counter, but I don't know how to make it workable with Local Storage
var seconds = 0;
var el = document.getElementById('seconds-counter');
function incrementSeconds() {
seconds += 1;
el.innerText = seconds;
}
var cancel = setInterval(incrementSeconds, 1000);
<div id='seconds-counter'> </div>
this way ?
<div id="seconds-counter">_</div>
<!-- button id="bt-stop-counter"> stop counter </button -->
const
counterLimit = 5 // <-- your counter limit value....
, div_s_counter = document.querySelector('#seconds-counter')
, btStopCounter = document.querySelector('#bt-stop-counter')
, timeRef_ls = localStorage.getItem('counterVal') || 0
, timeRef = (new Date()) - (timeRef_ls * 1000)
, CounterIntv = setInterval(() =>
{
let seconds = Math.floor(((new Date()) - timeRef) / 1000)
if (seconds >= counterLimit ) // stopCounter()
{
div_s_counter.textContent = seconds = counterLimit
clearInterval( CounterIntv )
}
div_s_counter.textContent = seconds
localStorage.setItem('counterVal', seconds.toString(10))
}
, 500)
;
div_s_counter.textContent = timeRef_ls
/* disable counter reset ------------------------------------
{
clearInterval( CounterIntv ) // to stop the counter
localStorage.removeItem('counterVal') // remove the counter
}
btStopCounter.onclick = stopCounter
------------------------------------------------------------*/
var el = document.getElementById('seconds-counter');
function incrementSeconds() {
var counter = window.localStorage.getItem("counter") ?? 0;
window.localStorage.setItem("counter", ++counter);
el.innerText = counter;
}
var cancel = setInterval(incrementSeconds, 1000);

How can I fix the stop-start process within this Javascript stopwatch-clock?

I have a JavaScript stopwatch here, I require the start-stop button to keep the same time when continuing.
Currently, if I stop and continue the clock diff is something ridiculous such as '-19330839:-3:-53'
Can anyone explain how this is fixed?
I have various method stopwatches made; however I would rather use real date time instead of a counter, this is because (I have tested after being made aware of this) that counters are very inaccurate over a period of time.
Any help is much appreciated.
html:
Please ignore the reset button for now. I will configure this later.
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
JS:
const outputElement = document.getElementById("outputt");
var startTime = 0;
var running = false;
var splitcounter = 0;
function startstop() {
if (running == false) {
running = true;
startTime = new Date(sessionStorage.getItem("time"))
if (isNaN(startTime)) startTime = Date.now();
startstopbutton.value = 'Stop';
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
updateTimer();
} else {
running = false;
logTime();
startstopbutton.value = 'Start';
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
function updateTimer() {
if (running == true) {
let differenceInMillis = Date.now() - startTime;
sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
requestAnimationFrame(updateTimer);
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
I just need the timer to continue on from where it was stopped at.
Issue with your code:
You start with initial value for sessionStorage as Date.now but then save difference on update.
You interact a lot with session storage. Any communication with external API is expensive. Instead use local variables and find an event to initialise values.
Time difference logic is a bit off.
Date.now - startTime does not considers the difference between stop action and start action.
You can use this logic: If startTime is defined, calculate difference and add it to start time. If not, initialise it to Date.now()
Suggestions:
Instead of adding styles, use classes. That will help you in reset functionality
Define small features and based on it, define small functions. That would make reusability easy
Try to make functions independent by passing arguments and only rely on them. That way you'll reduce side-effect
Note: as SO does not allow access to Session Storage, I have removed all the related code.
const outputElement = document.getElementById("outputt");
var running = false;
var splitcounter = 0;
var lastTime = 0;
var startTime = 0;
function logTime() {
console.log('Time: ', lastTime)
}
function resetclock() {
running = false;
startTime = 0;
printTime(Date.now())
applyStyles(true)
}
function applyStyles(isReset) {
startstopbutton.value = running ? 'Stop' : 'Start';
document.getElementById("outputt").classList.remove('red', 'green')
if (!isReset) {
document.getElementById("outputt").classList.add(running ? 'red' : 'green')
}
}
function startstop() {
running = !running;
applyStyles();
if (running) {
if (startTime) {
const diff = Date.now() - lastTime;
startTime = startTime + diff;
} else {
startTime = Date.now()
}
updateTimer(startTime);
} else {
lastTime = Date.now()
logTime();
}
}
function printTime(startTime) {
let differenceInMillis = Date.now() - startTime;
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
}
function updateTimer(startTime) {
if (running == true) {
printTime(startTime)
requestAnimationFrame(() => updateTimer(startTime));
}
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
.red {
background-color: #2DB37B
}
.green {
background-color: #B3321B
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();" />
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
simple stopwatch example
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<input class="startstop" style="width: 120px;" type="button" value="Start" onclick="startstop();">
<input class="reset" style="width: 120px;" type="button" value="Reset" onclick="reset();"/>
<div class="timerClock" value="00:00:00">00:00:00</div>
<script type="text/javascript">
var second = 0
var minute = 0
var hour = 0
var interval
var status = false
var element = document.querySelector('.startstop')
var clock = document.querySelector('.timerClock')
var string = ''
function startstop()
{
if(status == 'false')
{
element.value = 'Stop'
clock.style.backgroundColor = "#2DB37B";
status = true
interval = setInterval(function()
{
string = ''
second += 1
if(second >= 60)
{
minute += 1
second = 0
}
if(minute >= 60)
{
hour += 1
minute = 0
}
if(hour < 10)
string += `0${hour}:`
else
string += `${hour}:`
if(minute < 10)
string += `0${minute}:`
else
string += `${minute}:`
if(second < 10)
string += `0${second}`
else
string += `${second}`
clock.innerHTML = string
},1000)
}
else
{
clock.style.backgroundColor = "#B3321B";
element.value = 'Start'
status = false
clearInterval(interval)
}
}
function reset()
{
second = 0
minute = 0
hour = 0
status = false
element.value = 'Start'
clearInterval(interval)
clock.innerHTML = `00:00:00`
clock.style.backgroundColor = "transparent";
}
</script>
</body>
</html>
One thing to know about requestAnimationFrame is that it returns an integer that is a reference to the next animation. You can use this to cancel the next waiting animation with cancelAnimationFrame.
As mentioned by #Rajesh, you shouldn't store the time each update, as it will stop the current process for a (very) short while. Better in that case to fire an event, preferably each second, that will wait until it can run. I haven't updated the code to take that into account, I only commented it away for now.
It's also better to use classes than updating element styles. I wrote sloppy code that overwrites all classes on the #outputt element (it's spelled "output"). That's bad programming, because it makes it impossible to add other classes, but it serves the purpose for now. #Rajesh code is better written for this purpose.
I added two variables - diffTime and animationId. The first one corrects startTime if the user pauses. The second one keeps track if there is an ongoing timer animation.
I refactored your style updates into a method of its own. You should check it out, because it defines standard values and then changes them with an if statement. It's less code than having to type document.getElementById("outputt").style... on different rows.
I also added a resetclock method.
const outputElement = document.getElementById("outputt");
var startTime = 0;
var diffTime = 0;
var animationId = 0;
function startstop() {
const PAUSED = 0;
let paused = animationId == PAUSED;
//diffTime = new Date(sessionStorage.getItem("time")) || 0;
startTime = Date.now() - diffTime;
if (paused) {
updateTimer();
} else {
cancelAnimationFrame(animationId);
animationId = PAUSED;
}
updateTimerClass(paused);
}
function updateTimerClass(paused) {
var outputClass = 'red';
var buttonText = 'Start';
if (paused) {
outputClass = 'green';
buttonText = 'Stop';
}
startstopbutton.value = buttonText;
outputElement.classList = outputClass;
}
function updateTimer() {
let differenceInMillis = Date.now() - startTime;
//sessionStorage.setItem("time", differenceInMillis)
let {
hours,
minutes,
seconds
} = calculateTime(differenceInMillis);
let timeStr = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
outputElement.innerText = timeStr;
diffTime = differenceInMillis;
animationId = requestAnimationFrame(updateTimer);
}
function calculateTime(milliS) {
const SECONDS = 1000; // should be 1000 - only 10 to speed up the timer
const MINUTES = 60;
const HOURS = 60;
const RESET = 60;
let hours = Math.floor(milliS / SECONDS / MINUTES / HOURS);
let minutes = Math.floor(milliS / SECONDS / MINUTES) % RESET;
let seconds = Math.floor(milliS / SECONDS) % RESET;
return {
hours,
minutes,
seconds
};
}
function pad(time) {
return time.toString().padStart(2, '0');
}
function resetclock() {
let paused = animationId == 0;
startTime = Date.now();
diffTime = 0;
if (paused) {
const REMOVE_ALL_CLASSES = '';
outputElement.className = REMOVE_ALL_CLASSES;
outputElement.innerText = '00:00:00';
}
}
#outputt.green {
background-color: #2DB37B;
}
#outputt.red {
background-color: #B3321B;
}
<input id="startstopbutton" class="buttonZ" style="width: 120px;" type="button" name="btn" value="Start" onclick="startstop();">
<input id="resetbutton" class="buttonZ" style="width: 120px;" type="button" name="btnRst1" id='btnRst1' value="Reset" onclick="resetclock();"/>
<div id="outputt" class="timerClock" value="00:00:00">00:00:00</div>
class Stopwatch {
constructor(display, results) {
this.running = false;
this.display = display;
this.results = results;
this.laps = [];
this.reset();
this.print(this.times);
}
reset() {
this.times = [ 0, 0, 0 ];
}
click(){
var x=document.getElementById('ctrl');
if(x.value=="start"){
this.start();
x.value="stop";
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
}
else{
x.value="start";
this.stop();
document.getElementById("outputt").style.backgroundColor = "#B3321B";
}
}
start() {
if (!this.time) this.time = performance.now();
if (!this.running) {
this.running = true;
requestAnimationFrame(this.step.bind(this));
}
}
stop() {
this.running = false;
this.time = null;
}
resets() {
document.getElementById("outputt").style.backgroundColor = "#2DB37B";
if (!this.time) this.time = performance.now();
if (!this.running) {
this.running = true;
requestAnimationFrame(this.step.bind(this));
}
this.reset();
}
step(timestamp) {
if (!this.running) return;
this.calculate(timestamp);
this.time = timestamp;
this.print();
requestAnimationFrame(this.step.bind(this));
}
calculate(timestamp) {
var diff = timestamp - this.time;
// Hundredths of a second are 100 ms
this.times[2] += diff / 1000;
// Seconds are 100 hundredths of a second
if (this.times[2] >= 100) {
this.times[1] += 1;
this.times[2] -= 100;
}
// Minutes are 60 seconds
if (this.times[1] >= 60) {
this.times[0] += 1;
this.times[1] -= 60;
}
}
print() {
this.display.innerText = this.format(this.times);
}
format(times) {
return `\
${pad0(times[0], 2)}:\
${pad0(times[1], 2)}:\
${pad0(Math.floor(times[2]), 2)}`;
}
}
function pad0(value, count) {
var result = value.toString();
for (; result.length < count; --count)
result = '0' + result;
return result;
}
function clearChildren(node) {
while (node.lastChild)
node.removeChild(node.lastChild);
}
let stopwatch = new Stopwatch(
document.querySelector('.stopwatch'),
document.querySelector('.results'));
<input type="button" id="ctrl" value="start" onClick="stopwatch.click();">
<input type="button" value="Reset" onClick="stopwatch.resets();">
<div id="outputt" class="stopwatch"></div>

Enable button when counter reaches zero

I have a button its disabled and i want to put a counter inside it, what i want to do is when the counter reaches zero it get enabled, how can i do that? in the code below the counter doesn't appear inside the button and i don't want the reset button i just want the button to be enabled when it reaches zero, here is what i have tried so far:
function Countdown()
{
this.start_time = "00:30";
this.target_id = "#timer";
this.name = "timer";
this.reset_btn = "#reset";
}
Countdown.prototype.init = function()
{
this.reset();
setInterval(this.name + '.tick()',1000)
}
Countdown.prototype.reset = function()
{
$(this.reset_btn).hide();
time = this.start_time.split(":");
//this.minutes = parseInt(time[0]);
this.seconds = parseInt(time[1]);
this.update_target();
}
Countdown.prototype.tick = function()
{
if(this.seconds > 0) //|| this.minutes > 0)
{
if(this.seconds == 0)
{
// this.minutes = this.minutes - 1;
this.seconds = 59
} else {
this.seconds = this.seconds - 1;
}
}
this.update_target()
}
Countdown.prototype.update_target = function()
{
seconds = this.seconds;
if (seconds == 0) $(this.reset_btn).show();
else if(seconds < 10) seconds = "0" + seconds;
$(this.target_id).val(this.seconds)
}
timer = new Countdown();
timer.init();
$(document).ready(function(){
$("#reset").click(function(){
//timer = new Countdown();
timer.reset();
});
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button type="text" id="timer" disabled>Counter should be inside me, and enable me when it reaches 0</button>
<button id="reset">Reset</button>
This is much simpler than what you've got. Just use window.setTimeout().
Keep in mind that tracking time to a high precision is not super reliable in a browser. You may want to look at moment.js or use performance.now() for an easier API to handle that.
// Get refreence to span and button
var spn = document.getElementById("count");
var btn = document.getElementById("btnCounter");
var count = 5; // Set count
var timer = null; // For referencing the timer
(function countDown(){
// Display counter and start counting down
spn.textContent = count;
// Run the function again every second if the count is not zero
if(count !== 0){
timer = setTimeout(countDown, 1000);
count--; // decrease the timer
} else {
// Enable the button
btn.removeAttribute("disabled");
}
}());
<button id="btnCounter" disabled>Time left: <span id="count"></span></button>

setInterval and clearInterval through button click events

Here is my code:
window.onload = runThis;
function runThis() {
const txtMin = document.getElementsByClassName("min");
const txtSec = document.getElementsByClassName("sec");
function go() {
setInterval(countDown, 1000);
}
function countDown() {
timeNow = timeNow - 1;
timeSec = timeNow % 60; //remainder as seconds
timeMin = Math.round((timeNow/60) - (timeSec/60)); //minutes
txtMin[0].innerText =
(timeMin > 0 ?
(timeMin >= 10 ? `${timeMin}:` : `0${timeMin}:`)
: "00:");
txtSec[0].innerText =
(timeSec > 0 ?
(timeSec >= 10 ? timeSec : `0${timeSec}`)
: "00");
}
function stopIt() {
let x = setInterval(countDown, 1000);
clearInterval(x);
}
const btnStart = document.getElementsByClassName("start");
btnStart[0].addEventListener("click", go);
const btnStop = document.getElementsByClassName("stop");
btnStop[0].addEventListener("click", stopIt);
}
I am having trouble trying to set up setInterval and clearInterval.
2 buttons: start and stop. I want the function go to run when I click start to start the timer. That is all good. My problem is trying to stop the timer.
If I put let x = setInterval(countDown, 1000); outside the stopIt() function, it will automatically start the timer on windows.onload regardless of whether or not I click the start button but, in doing so, I can stop the timer.
If I put let x = setInterval(countDown, 1000); inside the stopIt() function like what I have here, I can start the timer whenever I want by clicking the start button, but now I can't stop the timer using clearInterval().
Any help is greatly appreciated. Thanks in advance!
Try to set the ID of the interval in the "go" function in a variable outside to be canceled inside the "stopIt" function, like this:
window.onload = runThis;
function runThis() {
var intervalID = null;
const txtMin = document.getElementsByClassName("min");
const txtSec = document.getElementsByClassName("sec");
function go() {
intervalID = setInterval(countDown, 1000);
}
function countDown() {
timeNow = timeNow - 1;
timeSec = timeNow % 60; //remainder as seconds
timeMin = Math.round((timeNow/60) - (timeSec/60)); //minutes
txtMin[0].innerText =
(timeMin > 0 ?
(timeMin >= 10 ? `${timeMin}:` : `0${timeMin}:`)
: "00:");
txtSec[0].innerText =
(timeSec > 0 ?
(timeSec >= 10 ? timeSec : `0${timeSec}`)
: "00");
}
function stopIt() {
clearInterval(intervalID);
}
const btnStart = document.getElementsByClassName("start");
btnStart[0].addEventListener("click", go);
const btnStop = document.getElementsByClassName("stop");
btnStop[0].addEventListener("click", stopIt);
}

Javascript random countdown - how to repeat same time multiple times on same page

I have a random countdown script, as per below:
Here is the Javascript:
<script>
var timer;
function startCount()
{
timer = setInterval(count, 1000); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count()
{
var do_wait = Math.ceil(4*Math.random());
if (do_wait == 4) {
var rand_no = Math.ceil(4*Math.random()); // 9 = random decrement amount. Counter will decrease anywhere from 1 - 9.
var el = document.getElementById('counter');
var currentNumber = parseFloat(el.innerHTML);
var newNumber = currentNumber - rand_no;
if (newNumber > 3) {
el.innerHTML = newNumber;
} else {
el.innerHTML = '<font color="white">3</font>'; // This message is displayed when the counter reaches zero.
}
}
}
startCount();
</script>
Here is how I am calling it in HTML
<span style="color:white;" id="counter">50</span>
I want to be able to display the ID "counter" multiple times on the page with the same countdown number. The problem is each time I display ID "counter" it has a different countdown number.
I'd change 'id' for 'name' so I do not have the same id multiple times in my document. I've made a few changes in your code:
<html>
<head>
<script>
var timer;
function startCount()
{
timer = setInterval(count, 1000); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count()
{
var do_wait = Math.ceil(4*Math.random());
if (do_wait == 4) {
var rand_no = Math.ceil(4*Math.random()); // 9 = random decrement amount. Counter will decrease anywhere from 1 - 9.
var els = document.getElementsByName('counter');
for(var i = 0 ; i < els.length ; i++) {
var currentNumber = parseFloat(els[i].innerHTML);
var newNumber = currentNumber - rand_no;
if (newNumber > 3) {
els[i].innerHTML = newNumber;
} else {
els[i].innerHTML = '<font color="white">3</font>'; // This message is displayed when the counter reaches zero.
}
}
}
}
startCount();
</script>
</head>
<body>
<span style="color:white;" name="counter">50</span>
<span style="color:white;" name="counter">50</span>
<span style="color:white;" name="counter">50</span>
<span style="color:white;" name="counter">50</span>
</body>
I'm now using counter as values for name attributes and document.getElementsByName() to read those array of names.
BTW, I tested in Chrome.

Categories