read div and check for a click condition - javascript

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.

Related

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>

JavaScript ClearInterval button doesn't stop

I've reviewed the other clearInterval posts here for a clue as to why my code isn't functioning as intended. Despite my best efforts, I still can't get clearInterval to stop my count.
I'm trying to do something simple: have a count, increase by one until the stop button is pushed.
I have tried different, and incorrect variables, but I cannot find a working solution.
<p>Count Up:</p>
<p id="count">1</p>
<button onclick="clearInterval(current)">Stop</button>
<script>
var current = 1;
function animateValue(id) {
var obj = document.getElementById(id);
var current = parseInt(obj.innerHTML);
setInterval(function () {
current++;
obj.innerHTML = current;
}, 1000);
}
animateValue("count");
</script>
Store the value returned by setInterval in a variable and pass that as the parameter to clearInterval instead of counter:
<p>Count Up:</p>
<p id="count">1</p>
<button onclick="clearInterval(interval)">Stop</button>
<script>
var interval;
var current = 1;
function animateValue(id) {
var obj = document.getElementById(id);
var current = parseInt(obj.innerHTML);
interval = setInterval(function () {
current++;
obj.innerHTML = current;
}, 1000);
}
animateValue("count");
</script>

Change background images using setTimeout

I have 31 images and I want to display them one after another as the background of a div. I only want it to change when the user hovers over the div. My problem right now is that it just flips through all the images really fast. I am attempting to use setTimeout, but it isn't working. How can I make the delay work?
The name of the div is About_Me_Block and the images are called frame1.gif,frame2.gif ...etc
Here is my code:
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
var counter = 0;
while (hoverAnimate[0]) {
console.log(counter);
setTimeout(changeImg(counter), 1000);
counter++;
if (counter === 32)
hoverAnimate[0] = false;
}
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
setTimeout doesn't wait for the function to end, it works lile threading in other languages.
To achieve a what you want, you need to call setTimeout from the changeImg function.
var counter = 0;
$(document).ready(function() {
var hoverAnimate = []
"use strict";
$('#About_Me_Block').mouseenter(function() {
hoverAnimate[0] = true;
counter = 0;
changeImg();
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate[0] = false;
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
function changeImg() {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
counter++;
if (counter < 32 && hoverAnimate[0]) {
setTimeout(changeImg, 1000);
} else {
hoverAnimate[0] = false;
}
}
the reason they happen all at once is because while statement doesn't have delay, so all setTimeout will be set up at the same time, thus, calling changeImg all at once.
To solve this problem, you can replace setTimeout with setInterval. Instead of using while, you can just call setInterval like
var counter = 0;
var myTimer = setInterval(changeImg, 1000);
and update counter inside changeImg every time it gets called. After looping, don't forget to
clearInterval(myTimer)
It seems you need to read up on how setTimeout works. It essentially places a reminder to run a function after a given amount of milliseconds have passed. So, when you do setTimeout(changImg(counter), 1000) you are calling changImg(counter) which returns undefined. Therein producing this setTimeout(undefined, 1000) which is why it flips really fast.
So, you can use bind to allow the function to be called later with that parameter built in. Also, make sure you remove the reminders once done with clearTimeout.
function changeImg(counter) {
$('#About_Me_Block').attr("style", "background-image: url(playGif/frame" + counter + ".gif);");
}
$(document).ready(function() {
var hoverAnimate = false, id;
function loop(counter) {
if(hoverAnimate || counter < 32) {
changeImg(counter);
id = setTimeout(loop.bind(this, counter++), 1000);
}
}
$('#About_Me_Block').mouseenter(function() {
hoverAnimate = true;
id = setTimeout(loop.bind(this, 0), 1000);
});
$('#About_Me_Block').mouseleave(function() {
hoverAnimate = false;
// Don't want a reminder for a random counter to wake up.
clearTimeout(id);
$(this).attr("style", "background-image: url(play.jpeg);");
});
});
Two methods for timers - setTimeout and SetInterval (single / repeating)
// setInterval is also in milliseconds
var intervalHandle = setInterval(<yourFuncToChangeImage>,5000);
//this handle loop and make example loop stop
yourelement.yourEvent = function() {
clearInterval(intervalHandle);
};

How do make a count down inside the button?

I want to make a 5-second countdown inside my button so you can see how much time is left before I submit some content after I click the button. I get the value he has to count down from "data-delay" inside my HTML tag
});
Demo of what I assume you want: http://jsfiddle.net/Lp99cw3q/2/
Firstly,
var b = $(button);
is invalid, I assume you're wanting to access the button attributes, so use:
var b = $('#first');
This then allows you to use b to access everything you need, eg:
var text = b.attr('value');
if you want the timer function to be called on click:
$('#first').click(function() {
timer();
});
which I would then set up as so:
function timer(){
setTimeout(function(){
b.val(text + ' ' + counter); // update the text with the counter
b.attr('data-delay', counter); // update the attribute holding the value
if (counter == 0) {next();} // if finished, call next function
else {counter--; timer();} // decrease the counter and call the timer again after 1s
},1000);
}
function next() {
b.val('Done!');
//whatever happens afterwards
}
Here is the updated/working code.
<input type="button" value="Submit and wait!" id="first" data-delay="5"></input>
var button = $('#first');
var counter = button.attr('data-delay');
var text = button.attr('value');
function timer() {
button.val(text+' '+counter);
if (counter == 0) {
clearInterval(countdownTimer);
button.val("TimeOut");
} else {
counter--;
}
}
var countdownTimer = setInterval('timer()', 1000);

Categories