Inefficient javascript countdown timer - javascript

I have created a very simple countdown timer in js which every element of time is calculated out. It works, the only issue with it is there exists lag most likely caused from the calculations being made every second. Any thoughts as to how to make this more efficient?
js:
var count = 55010; //needs to be in seconds
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
function timer(){
count = count-1;
if (count <= -1){
clearInterval(counter);
return;
}
document.getElementById("hour10").innerHTML=Math.floor(((count/86400)%1)*2.4);
document.getElementById("hour1").innerHTML=Math.floor(((count/86400)%1)*24)-(Math.floor(((count/86400)%1)*2.4))*10;
document.getElementById("min10").innerHTML=Math.floor(((count/3600)%1)*6);
document.getElementById("min1").innerHTML = Math.floor(((count/3600)%1)*60)-(Math.floor(((count/3600)%1)*6))*10;
document.getElementById("sec10").innerHTML = Math.floor(((count/60)%1)*6);
document.getElementById("sec1").innerHTML = Math.floor(((count/60)%1)*60)-(Math.floor(((count/60)%1)*6))*10;
}
HTML:
<span id="hour10">0</span>
<span id="hour1">0</span> :
<span id="min10">0</span>
<span id="min1">0</span> :
<span id="sec10">0</span>
<span id="sec1">0</span>
The reason I have created the timer in this fashion is because I want to put each element into a div container like so:
Thanks in advance!

A way to make this more efficient is to keep a reference to the elements by only searching the Dom once, and also use innerText if you are not using any markup
var count = 55010; //needs to be in seconds
var counter = setInterval(timer, 1000); //1000 will run it every 1 second
var elHour10 = document.getElementById("hour10");
var elHour1 = document.getElementById("hour1");
var elMin1 = document.getElementById("min10");
var elSec10 = document.getElementById("sec10");
var elSec1 = document.getElementById("sec1");
function timer(){
count = count-1;
if (count <= -1){
clearInterval(counter);
return;
}
elHour10.innerText=Math.floor(((count/86400)%1)*2.4);
elHour1.innerText=Math.floor(((count/86400)%1)*24)-(Math.floor(((count/86400)%1)*2.4))*10;
elMin10.innerText=Math.floor(((count/3600)%1)*6);
elMin1.innerText = Math.floor(((count/3600)%1)*60)-(Math.floor(((count/3600)%1)*6))*10;
elSec10.innerText = Math.floor(((count/60)%1)*6);
elSec1.innerText = Math.floor(((count/60)%1)*60)-(Math.floor(((count/60)%1)*6))*10;
}

Related

How to setup Multiple countdown timers on products?

Setting up a sales page and I can't get the product inventory countdown timer to work on other products on the page.
I got it working for the first product but it doesn't wanna work on the second product. Same Page.
// Random Countdown Timer Script, by http://ctrtard.com
var timer;
function startCount() {
timer = setInterval(count, 200); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count() {
var rand_no = Math.ceil(9 * 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 > 0) {
el.innerHTML = newNumber;
} else {
el.innerHTML = "Sold Out"; // This message is displayed when the counter reaches zero.
}
}
<body onLoad="startCount();">
<span class="timer">Buy it now!!!!!! only <span id="counter">15555</span> left</span>
</body>
I just end up with one timer or the other working, not both firing off
All you need to do is have 2 unique ids for your counters (let's say counter1 and counter2) and then, update those in your count method like that:
<span class="timer">Buy it now!!!!!! only <span id="counter1">15555</span> left</span>
...
<span class="timer">Buy it now!!!!!! only <span id="counter2">12345</span> left</span>
var timer;
var nbCounters = 2;
function startCount() {
timer = setInterval(count, 200); // 200 = 200ms delay between counter changes. Lower num = faster, Bigger = slower.
}
function count() {
// Update all counters
for(i=1; i<=nbCounters; i++) {
var rand_no = Math.ceil(9 * Math.random()); // 9 = random decrement amount. Counter will decrease anywhere from 1 - 9.
var el = document.getElementById('counter' + i);
var currentNumber = parseFloat(el.innerHTML);
var newNumber = currentNumber - rand_no;
if (newNumber > 0) {
el.innerHTML = newNumber;
} else {
el.innerHTML = "Sold Out"; // This message is displayed when the counter reaches zero.
}
}
}
I'd really advise you to have a look at jQuery for DOM manipulation: https://api.jquery.com/
Lucas

How do I loop this function?

I am using Odometer to show an animated counter:
setTimeout(function (){
$('.odometer').html(8567);
}, 1000);
</script>
<script>
window.odometerOptions = {
duration: 3000
};
I would like the counter to start over at the value I've defined in my html (which is 1000) and then count back up to 8567 and repeat indefinitely. I've tried:
$(document).ready(function () {
function loop(){
setTimeout(function (){
$('.odometer').html(8567);},1000,loop);
loop();
});
But it breaks the counter. I'm assuming I can't mix the setTimeout while defining the loop, but don't know what else to try. The 1000 in the setTimeout function is just a coincidence and is the delay to start the function after page load.
If you want to repeatedly call a function over time like this you should use setInterval not setTimeout.
You need to keep track of the current value of the loop, yours right now is setting the counter to 8567 every time.
const start = 1000;
const max = 1010;
var c = start;
var el = document.getElementById('counter');
function counter() {
if (c > max) {
c = start;
}
el.innerHTML = c + "";
c++;
}
counter(); // Optional, can exclude if you want to delay starting the timer
setInterval(counter , 1000)
<div id="counter"></div>

For loop with a timeout doesn't seem to work and gives weird numbers

I want to make a countdown in javascript, with simple variables, for loop, set timeout.
I get stuck when trying to make a for loop update realtime (every second) right now I get -1 in webpage.
//HTML PART
<p id=timer>0</p>
//JS PART
var timer = 10;
var text = "";
function f() {
for (timer; timer > 0; timer--) {
text += timer + "<br>";
}
timer--;
if( timer > 0 ){
setTimeout( f, 1000 );
}
}
f();
document.getElementById("timer").innerHTML = timer;
Please explain the error and if I'm doing any stupid mistakes
Looks like you want to show timer value from 10 to 0 by changing the value every second. If so, you can do like this:
1. You need to correct your html by putting quotes around timer like this <p id="timer">0</p>
2. You need to remove for loop as I have commented.
3. Move document.getElementById("timer").innerHTML = timer; inside function f().
var timer = 10;
//var text = "";
function f() {
//for (timer; timer > 0; timer--) {
// text += timer + "<br>";
//}
document.getElementById("timer").innerHTML = timer;
timer--;
if (timer >=0) {
setTimeout(f, 1000);
}
}
f();
<p id="timer">0</p>
You can do it like so, I provided comments in code for explanation:
var count = 10;
function timer(targetValue) {
// display first number on screen
document.getElementById("timer").textContent = count;
// decrease count by 1
count--;
// check if timer is still grater than target value
if (count >= targetValue) {
// call timer() function every second to update
setTimeout(timer, 1000, targetValue);
}
}
timer(0);
Counts down from 10 to 0.
Want to count down from 10 to 5? Simply use timer(5)

setInterval for stopwatch

I'm trying to make a stopwatch. Here's the code:
var min = 0, sec = 0, censec = 0
$("#startBtn").on("click", function() { // when start button is clicked
$(this).hide(); // start is hidden
$("#stopBtn").show(); // stop is shown
setInterval(add, 10); // the censec will be increased every 10 millisecond.
$("#censec").text(censec);
})
function add() {
censec++;
if (censec == 100) {
censec = 0;
sec++;
if (sec == 60) {
sec = 0;
min++;
}
}
}
The problem is that setInterval() happens only at once. The censec only changes from 00 to 1. That's it.
P.S. I'm new to coding, so if there are other mistakes, please don't hesitate to tell me.
The setInterval calls to add will definitely repeat. But your code is only ever showing the value of censec once, when you start the timer.
If you want to update the display every hundredth of a second, put the code showing the value in add.
Separately, the code as it is in the question won't run at all, because it has a ReferenceError on the first line. Those ; should be ,.
Example (this also stores the timer's handle and clears the timer when you click the stop button):
var min = 0, sec = 0, censec = 0;
// Note ---^--------^
function add() {
censec++;
if (censec == 100) {
censec = 0;
sec++;
if (sec == 60) {
sec = 0;
min++;
}
}
$("#censec").text(censec);
}
var timer = 0;
$("#startBtn").on("click", function() { //when start button is clicked
$(this).hide(); //start is hidden
$("#stopBtn").show(); //stop is shown
timer = setInterval(add,10); //the censec will be increased every 10 millisecond.
});
$("#stopBtn").on("click", function() {
clearInterval(timer);
timer = 0;
$(this).hide();
$("#startBtn").show();
});
<input type="button" id="startBtn" value="Start">
<input type="button" id="stopBtn" value="Stop" style="display: none">
<div id="censec"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Note that although it may be mostly fine to use setInterval for displaying, using it to track the elapsed time is a bad idea; it frequently doesn't fire precisely.
Instead, record when you started
var start = Date.now();
...and then when the timer fires, figure out how long it's been since you started
var elapsed = Date.now() - start;
Then use the value (milliseconds) in elapsed to figure out your display.
Your variable declarations have ; instead of , .
Also checking numbers on equality should be done by using === but that is not the problem here.
Your also not updating the view in your timer. So updating of your html should also be in your function that is called by the timer.
If the goal is to use real seconds and milliseconds, I also suggest using the Date type because your timer will be late and not real-time. So still use the timer with the interval you like but in the add function you call the date object. You can replace the 3 vars for one datetime of type Date which will give you the granularity that you like.
var dateTimeStart = null, censecElement = null, timer = null;
$("#startBtn").on("click", function() {//when start button is clicked
$(this).hide(); // start is hidden
$("#stopBtn").show(); // stop is shown
if(timer === null) {
// timer was not started
dateTimeStart = new Date();
timer = setInterval(updateCensec, 10); //the censec will be increased every 10 millisecond.
console.log("Started timer");
}
});
$("#stopBtn").on("click", function() {//when stop button is clicked
$(this).hide(); // stop is hidden
$("#startBtn").show(); // start is shown
if(timer) {
// timer is started/running
clearInterval(timer);
console.log("Stopped timer");
}
timer = null;
});
function updateCensec() {
var sensec = 0, sec = 0, dateTimeNow = new Date(), diffMilliseconds = 0;
diffMilliseconds = dateTimeNow - dateTimeStart;
censec = parseInt((diffMilliseconds % 600 ) / 10); // convert milliseconds to centi seconds
sec = parseInt(diffMilliseconds / 600);
if(censecElement === null) {
censecElement = $("#censec");
}
censecElement.text(sec + ":" + censec);
}
I would like to suggest that you do not update your view every 10 milliseconds even if you want your stopwatch to show time in centiseconds.

How to run a javascript function X seconds?

I am using setInterval to run a Javascript function that generates a new, random integer in a div. the timer starts when I click on the div. I am having problems with stopping it form generating new numbers after five seconds.
Using setTimeout, I hide the div after 5 seconds; that stops random numbers, but I lose the div.
How can I efficiently stop the generating of numbers in the div, and not hide it?
HTML:
<div id="div" onmousedown='F();'>Click here</div>
JS:
function F(){
var div = document.getElementById("div");
setInterval(function(){
var number = Math.floor(Math.random()*28) ;
div.innerHTML = number;
}, 1000);
setTimeout(function(){
div.style.display = 'none';
},5000);
};
Just use a counter to keep track of the number of times the interval has ticked and then use clearInterval to stop it:
var count = 0;
var intervalID = setInterval(function() {
// generate your random number
count++;
if (count === 5) {
clearInterval(intervalID);
}
}, 1000);
Something hastily written, but what you want to do is keep track of your interval handle and then clear it. You can do this with a setTimeout
var forXsecs = function(period, func) {
var handle = setInterval(func, 1000);
setTimeout(function() { clearInterval(handle); }, period * 1000);
}
The timing is not perfect. Matt's answer would also work.
Another option is a slight change on Matt's answer that removes setInterval and just uses timeouts.
var count = 0;
var forXsecs = function(period, func) {
if(count < period) {
func();
count++;
setTimeout(function() {forXsecs(period, func);}, 1000);
} else {
count = 0; //need to reset the count for possible future calls
}
}
If you just want to simply let it run once each second and that 5 times you can do it like this:
HTML:
<div id="5seconds"></div>
JS:
var count= 0;
setInterval(function(){
if(count < 5){
document.getElementById('5seconds').innerHTML = Math.random();
count++
}
},1000);
This will generate a random number each second. until 5 seconds have passed
you should use clearInterval to stop the timer.
To do so, you pass in the id(or handle) of a timer returned from the setInterval function (which creates it).
I recommend clearing the interval timer (using clearInterval) from within the function being executed.
var elm = document.querySelector("div.container");
var cnt = 0;
var timerID;
function generateNumber()
{
cnt += 1;
elm.innerText = cnt;
if (cnt >= 5) {
window.clearInterval(timerID);
}
}
timerID = window.setInterval(generateNumber, 1000);
.container {display:block; min-width:5em;line-height:5em;min-height:5em;background-color:whitesmoke;border:0.1em outset whitesmoke;}
<label>1s Interval over 5s</label>
<div class="container"></div>

Categories