slideshow looping randomly and sometimes skips very fast [duplicate] - javascript

I am doing a very simple timer with two buttons: stop and set.
Here is the code:
<h1>0</h1>
<button onclick = 'set()'>Set</button>
<button onclick = 'stop()'>Stop</button>
var click = false;
let interval
function set(){
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
},1000)
}
function stop(){
window.clearInterval(interval)
}
I found that if I keep pressing the set button which will set new interval, the speed of adding 1 to h1 will become faster and faster (which is much faster than 1000 ms).
I know I could gather the two buttons to one button, or make the set button become display: none or use other ways to prevent this situation.
But I just wonder why does this happens.
Could someone explain me a little bit about why this happens?
Thanks for any responds?

That's because you are not clearing the previous interval (simply reassigning it) on your set function, so if you click on set three times, you are running three intervals.
The proper code should be:
function set(){
clearInterval(interval);
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
}, 1000)
}

an other way, more user friendly ?
const h1_element = document.querySelector('h1')
, btSet = document.querySelector('#bt-set')
, btStop = document.querySelector('#bt-stop')
;
var interval = 0
, counter = 0
;
btSet.onclick =()=>
{
btSet.disabled = true
btStop.disabled = false
interval = setInterval( ()=> { h1_element.textContent = ++counter }, 1000 )
}
btStop.onclick =()=>
{
clearInterval(interval)
btSet.disabled = false
btStop.disabled = true
}
<h1>0</h1>
<button id="bt-set">Set</button>
<button id="bt-stop" disabled>Stop</button>

an other way ? More RELIABLE , More elegant
Leveraging OOP: where you guarantee a unique interval is running per instance
class IntervalManager {
constructor(fn, delay){ this.fn= fn; this.delay= delay;}
start() {this.stop(); this.id= setInterval(this.fn, this.delay);}
stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now
const counter = new IntervalManager(function(){
let ui = document.querySelector('h1')
ui.textContent = parseFloat(ui.textContent)+1
},1000);
<h1>0</h1>
<button onclick = 'counter.start()'>Set</button>
<button onclick = 'counter.stop()'>Stop</button>
Other examples below show the benefit of using this manager:
class IntervalManager {
constructor(fn, i){ this.fn= fn; this.i= i;}
start() {this.stop(); this.id= setInterval(this.fn, this.i);}
stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now
//-- example 1
const timer = new IntervalManager(() => {
document.querySelector('#timer h4').textContent = new Date()
}, 1000)
//-- example 2
counterIncrem= 0
const counter = new IntervalManager(() => {
counterIncrem++;
document.querySelector('#counter h4').textContent = counterIncrem
}, 1000)
<section id="timer">
<h1>Timer</h1>
<h4>_</h4>
<button onclick = 'timer.start()'>Start</button>
<button onclick = 'timer.stop()'>Stop</button>
</section>
<section id="counter">
<h1>counter</h1>
<h4>_</h4>
<button onclick = 'counter.start()'>Start</button>
<button onclick = 'counter.stop()'>Stop</button>
</section>

Related

read div and check for a click condition

let timer = document.querySelector("#timer");
var counter = 3;
function myFn() {
counter--
if (counter === -1) {
counter = 3
}
timer.innerText = counter
}
btn.onclick = function() {
text.innerHTML += 'clicked' + '<br>'
}
var myTimer = setInterval(myFn, 1000);
<div id="timer"></div>
<button id="btn">Button</button>
<div id="text"></div>
I'm trying with this small code to read the div#timer every second and check for a click condition in console.log() F12. It gives me different error in every way I try to do it.
let timer = document.querySelector("#timer");
let btn = document.querySelector("#btn");
setInterval(() => {
console.log(timer.textContent)
if (timer.textContent === '0') {
btn.click()
}
}, 1000);
Consider the following jQuery example.
$(function() {
var timer = 0;
var counter = 3;
var timeObj = $("#timer");
var btnObj = $("#btn");
var txtObj = $("#text");
var interval;
function myFn() {
if (--counter >= 0) {
txtObj.append("Clicked<br />");
} else {
clearInterval(interval);
}
}
interval = setInterval(function() {
timeObj.html(++timer);
}, 1000);
btnObj.click(myFn);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="timer">0</div>
<button id="btn">Button</button>
<div id="text"></div>
You will want to use setInterval() and not setTimeout().
The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.
This method returns an interval ID which uniquely identifies the interval, so you can remove it later by calling clearInterval().
See more: https://developer.mozilla.org/en-US/docs/Web/API/setInterval
Using the -- and ++ before the variable will also apply the change before it is used.
The decrement operator (--) decrements (subtracts one from) its operand and returns the value before or after the decrement, depending on where the operator is placed.
Adjusting the logic here can also ensure that the button click does allow the user to keep performing actions.

Counter speed increases when the start button is clicked again

When the start button is clicked once, everything works perfectly fine. However, when the start button is clicked multiple times (by accident for example), the speed of the counter increases and the stop button doesn't seem to work any more!
Why is this happening? And what can I do to prevent the start button (if clicked accidentally) from increasing the speed of the timer when it is already running?
<button id="startBtn" onclick="startTimer()">Start</button>
<button id="stopBtn" onclick="stopTimer()">Stop</button>
<h2 id="timer"></h2>
<script>
let myCounter
function startTimer() {
myCounter = setInterval(counter, 200);
}
function stopTimer() {
clearInterval(myCounter);
}
let i = 0;
function counter() {
document.getElementById("timer").innerHTML = i++;
}
</script>
Welcome to StackOverflow.
Within your question, it's unclear if you want the timer to reset if the user clicks the start button again, however with my answer, I came to the conclusion that you didn't.
Here's a modified version of startTimer() which utilizes a guard clause to check if an interval already exists (and if so, don't start again)
function startTimer() {
// Guard clause! If the counter exists, exit the function!
if(myCounter) {
return
}
myCounter = setInterval(counter, 200);
}
A tiny update of the stop function is also needed to set myCounter to null after the counter is stopped:
function stopTimer() {
clearInterval(myCounter);
// Set the counter to Null, because it is still declared even though it has no value! (try removing this line and see what happens when you hit start again)
myCounter = null;
}
Hope this helped :)
I added a variable that can helps you detect if the counter is already clicked or not, with the condition of that variable, you can have what you want, I edited your code.
<button id="startBtn" onclick="startTimer()">Start</button>
<button id="stopBtn" onclick="stopTimer()">Stop</button>
<h2 id="timer"></h2>
<script>
let myCounter
let clicked = false;
function startTimer() {
if(!clicked){
myCounter = setInterval(counter, 200);
}
clicked = true;
}
function stopTimer() {
if(clicked){
clearInterval(myCounter);
}
clicked = false;
}
let i = 0;
function counter() {
document.getElementById("timer").innerHTML = i++;
}
</script>
You could simply disable the start button once clicked, and re-enable it when the stop button is clicked.
let i = 0;
let myCounter;
let startBtn = document.getElementById('startBtn');
let stopBtn = document.getElementById('stopBtn');
let timer = document.getElementById('timer');
function startTimer() {
startBtn.disabled = true;
stopBtn.disabled = false;
myCounter = setInterval(counter, 200);
}
function stopTimer() {
startBtn.disabled = false;
stopBtn.disabled = true;
clearInterval(myCounter);
}
function counter() {
i++; timer.value = i;
}
startBtn.addEventListener('click', startTimer);
stopBtn.addEventListener('click', stopTimer);
<button id="startBtn">Start</button>
<button id="stopBtn" disabled>Stop</button>
<h2><output id="timer">0</output></h2>
As an added measure, you can even hide the disabled button so only the active one is shown.
button:disabled {
display: none;
}

Why the interval will become faster and faster if I keep setting new interval

I am doing a very simple timer with two buttons: stop and set.
Here is the code:
<h1>0</h1>
<button onclick = 'set()'>Set</button>
<button onclick = 'stop()'>Stop</button>
var click = false;
let interval
function set(){
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
},1000)
}
function stop(){
window.clearInterval(interval)
}
I found that if I keep pressing the set button which will set new interval, the speed of adding 1 to h1 will become faster and faster (which is much faster than 1000 ms).
I know I could gather the two buttons to one button, or make the set button become display: none or use other ways to prevent this situation.
But I just wonder why does this happens.
Could someone explain me a little bit about why this happens?
Thanks for any responds?
That's because you are not clearing the previous interval (simply reassigning it) on your set function, so if you click on set three times, you are running three intervals.
The proper code should be:
function set(){
clearInterval(interval);
interval = setInterval(function(){
document.querySelector('h1').textContent = parseFloat(document.querySelector('h1').textContent)+1
}, 1000)
}
an other way, more user friendly ?
const h1_element = document.querySelector('h1')
, btSet = document.querySelector('#bt-set')
, btStop = document.querySelector('#bt-stop')
;
var interval = 0
, counter = 0
;
btSet.onclick =()=>
{
btSet.disabled = true
btStop.disabled = false
interval = setInterval( ()=> { h1_element.textContent = ++counter }, 1000 )
}
btStop.onclick =()=>
{
clearInterval(interval)
btSet.disabled = false
btStop.disabled = true
}
<h1>0</h1>
<button id="bt-set">Set</button>
<button id="bt-stop" disabled>Stop</button>
an other way ? More RELIABLE , More elegant
Leveraging OOP: where you guarantee a unique interval is running per instance
class IntervalManager {
constructor(fn, delay){ this.fn= fn; this.delay= delay;}
start() {this.stop(); this.id= setInterval(this.fn, this.delay);}
stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now
const counter = new IntervalManager(function(){
let ui = document.querySelector('h1')
ui.textContent = parseFloat(ui.textContent)+1
},1000);
<h1>0</h1>
<button onclick = 'counter.start()'>Set</button>
<button onclick = 'counter.stop()'>Stop</button>
Other examples below show the benefit of using this manager:
class IntervalManager {
constructor(fn, i){ this.fn= fn; this.i= i;}
start() {this.stop(); this.id= setInterval(this.fn, this.i);}
stop() {if (this.id) clearInterval(this.id);}
}
//--- use it now
//-- example 1
const timer = new IntervalManager(() => {
document.querySelector('#timer h4').textContent = new Date()
}, 1000)
//-- example 2
counterIncrem= 0
const counter = new IntervalManager(() => {
counterIncrem++;
document.querySelector('#counter h4').textContent = counterIncrem
}, 1000)
<section id="timer">
<h1>Timer</h1>
<h4>_</h4>
<button onclick = 'timer.start()'>Start</button>
<button onclick = 'timer.stop()'>Stop</button>
</section>
<section id="counter">
<h1>counter</h1>
<h4>_</h4>
<button onclick = 'counter.start()'>Start</button>
<button onclick = 'counter.stop()'>Stop</button>
</section>

set Interval function giving output for previous parameter [duplicate]

So, I got an infinite loop to work in this function using setInterval attached to an onClick. Problem is, I can't stop it using clearInterval in an onClick. I think this is because when I attach a clearInterval to an onClick, it kills a specific interval and not the function altogether. Is there anything I can do to kill all intervals through an onClick?
Here's my .js file and the calls I'm making are
input type="button" value="generate" onClick="generation();
input type="button" value="Infinite Loop!" onclick="setInterval('generation()',1000);"
input type="button" value="Reset" onclick="clearInterval(generation(),80;" // This one here is giving me trouble.
setInterval returns a handle, you need that handle so you can clear it
easiest, create a var for the handle in your html head, then in your onclick use the var
// in the head
var intervalHandle = null;
// in the onclick to set
intervalHandle = setInterval(....
// in the onclick to clear
clearInterval(intervalHandle);
http://www.w3schools.com/jsref/met_win_clearinterval.asp
clearInterval is applied on the return value of setInterval, like this:
var interval = null;
theSecondButton.onclick = function() {
if (interval === null) {
interval = setInterval(generation, 1000);
}
}
theThirdButton.onclick = function () {
if (interval !== null) {
clearInterval(interval);
interval = null;
}
}
Have generation(); call setTimeout to itself instead of setInterval. That was you can use a bit if logic in the function to prevent it from running setTimeout quite easily.
var genTimer
var stopGen = 0
function generation() {
clearTimeout(genTimer) ///stop additional clicks from initiating more timers
. . .
if(!stopGen) {
genTimer = setTimeout(function(){generation()},1000)
}
}
}
Live demo
This is all you need!
<script type="text/javascript">
var foo = setInterval(timer, 1000);
function timer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
$(document).on("click", "#stop_clock", function() {
clearInterval(foo);
$("#stop_clock").empty().append("Done!");
});
</script>

Is there any way to kill a setInterval loop through an Onclick button

So, I got an infinite loop to work in this function using setInterval attached to an onClick. Problem is, I can't stop it using clearInterval in an onClick. I think this is because when I attach a clearInterval to an onClick, it kills a specific interval and not the function altogether. Is there anything I can do to kill all intervals through an onClick?
Here's my .js file and the calls I'm making are
input type="button" value="generate" onClick="generation();
input type="button" value="Infinite Loop!" onclick="setInterval('generation()',1000);"
input type="button" value="Reset" onclick="clearInterval(generation(),80;" // This one here is giving me trouble.
setInterval returns a handle, you need that handle so you can clear it
easiest, create a var for the handle in your html head, then in your onclick use the var
// in the head
var intervalHandle = null;
// in the onclick to set
intervalHandle = setInterval(....
// in the onclick to clear
clearInterval(intervalHandle);
http://www.w3schools.com/jsref/met_win_clearinterval.asp
clearInterval is applied on the return value of setInterval, like this:
var interval = null;
theSecondButton.onclick = function() {
if (interval === null) {
interval = setInterval(generation, 1000);
}
}
theThirdButton.onclick = function () {
if (interval !== null) {
clearInterval(interval);
interval = null;
}
}
Have generation(); call setTimeout to itself instead of setInterval. That was you can use a bit if logic in the function to prevent it from running setTimeout quite easily.
var genTimer
var stopGen = 0
function generation() {
clearTimeout(genTimer) ///stop additional clicks from initiating more timers
. . .
if(!stopGen) {
genTimer = setTimeout(function(){generation()},1000)
}
}
}
Live demo
This is all you need!
<script type="text/javascript">
var foo = setInterval(timer, 1000);
function timer() {
var d = new Date();
var t = d.toLocaleTimeString();
document.getElementById("demo").innerHTML = t;
}
$(document).on("click", "#stop_clock", function() {
clearInterval(foo);
$("#stop_clock").empty().append("Done!");
});
</script>

Categories