setInterval is not working with innerHTML? - javascript

I am trying to create a small place on my website to show the seconds running. but my javascript function is not running. At the same time, it does not show any error. This is my javascript code:
function stoptime() {
let count = 0;
count = count+1;
stop = document.getElementById("time");
stop.iinnerHTML = count.value;
setInterval(stoptime, 1000);
I can use this code with document.write function, but it did not give the count ++ value, instead of that it showed many single value of count. so I tried to use it with innerHtml, but it not running.
please tell, what is the reason and the correct code?

HTML
<span id="time"></span>
JS
let count = 0;
function stoptime() {
count++
stop = document.getElementById("time");
stop.innerHTML = count;
}
setInterval(stoptime, 1000);

The count variable is initialized in the same function every time. Its value gets reset to 1 each time the function is called. Moving the count declaration outside the function should fix your issue.
Also you don't need count.value
let count = 0;
function stoptime() {
count = count+1;
stop = document.getElementById("time");
stop.innerHTML = count;
}
setInterval(stoptime, 1000);
<div id="time"></div>

Related

Browser freezes when I execute this simple code to increment number

I am trying to create a div where the number starts from 1 and automatically increments by one - like a stopwatch. But when I run the code, it crashes or does not work.
<html>
<body>
<div></div>
<script>
var div = document.querySelector('div');
var i = 1;
while(i>0){
div.innerText=i;
i++;
}
</script>
</body>
</html>
You never let the JavaScript engine rest. As soon as it has incremented the variable, the loop starts over, and it never exits. This blocks everything else.
You need to pause between loops to let the browser do other things.
You can use the requestAnimationFrame function to do this.
const div = document.querySelector('div');
let i = 1;
const incrementCounter = () => {
div.innerText = i;
i++;
requestAnimationFrame(incrementCounter);
}
incrementCounter();
<div></div>
Since you mentioned the term "stopwatch" maybe you prefer something like this:
This increments i by 1 every second using setInterval()
The first parameter is our function, that gets executed on that interval.
The second parameter 1000 is the interval. In this case 1000 ms.
You can adjust it as needed.
You can stop the timer with:
clearInterval(incrementCounter);
const div = document.querySelector('div');
let i = 1;
const incrementCounter = setInterval(() => {
div.innerText = i;
i++;
},1000);
<div></div>
You can find more information here:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

Javascript : setInterval and ClearInterval on one click?

I'm trying to have the numbers 1-6 quickly flash on the screen when a button is clicked, then stop and display the random generated number. If I put clearInterval into the function it just displays the random Number and doesn't display the flashes up numbers before hand.
HTML
<div id='dice'>
<div id='number'>0</div>
</div>
<div id='button'>
<button onclick='roll()'>Roll Dice</button>
</div>
JAVASCRIPT
let rollButton = document.querySelector('button');
let diceNumber = document.getElementById ('number');
function roll(){
diceSides = [1,2,3,4,5,6];
var i = 0;
let shuffleDice = setTimeout(function(){
diceNumber.innerHTML = diceSides[i++];
if(diceNumber == diceSides.length){
i = 0;
}
}, 500);
let random = Math.floor(Math.random() * 6);
diceNumber.innerHTML = random;
}
Maybe this works for you
hint: you can use i as a counter variable OR use your approach (define an array with numbers and use index to find them and put them in number tag)
HTML:
<div id='dice'>
<div id='number'>0</div>
</div>
<div id='button'>
<button onclick='roll()'>Roll Dice</button>
</div>
JS:
let rollButton = document.querySelector('button');
let diceNumber = document.getElementById ('number');
function roll(){
diceSides = [1,2,3,4,5,6];
var i = 6;
let shuffleDice = setInterval(function(){
diceNumber.innerHTML = i;
if(i == 0){
clearInterval(shuffleDice);
let random = Math.floor(Math.random() * 6);
diceNumber.innerHTML = random;
}
i--;
}, 1000);
}
CodePen
clearInterval
setInterval
setTimeout
SetTimeout only executes once. Also your variable is changed by the interval!
After its over, you have to clear the interval with clearInterval.
let rollButton = document.querySelector('button');
let diceNumber = document.getElementById ('number');
function roll(){
diceSides = [1,2,3,4,5,6];
var i = 0;
var shuffleDice = setInterval(function(){
diceNumber.innerHTML = diceSides[i++];
//use i
if(i == diceSides.length){
i = 0;
//clear
clearInterval(shuffleDice);
// moved because the interval will change it
let random = Math.floor(Math.random() * 6);
diceNumber.innerHTML = String(random);
}
}, 500);
}
<div id = 'dice'>
<div id = 'number'>0</div>
</div>
<div id = 'button'>
<button onclick = 'roll()'>Roll Dice</button>
</div>
I suggest something like this:
var diceNumber = document.getElementById ('number');
const diceSides = [1,2,3,4,5,6];
function roll(){
let arr = [...diceSides,diceSides[Math.floor(Math.random() * diceSides.length)]];
cycle(diceNumber,arr,200);
}
function cycle(element,arr,delay) {
element.innerText=arr.shift();
if (arr.length > 0)
setTimeout(cycle,delay,element,arr,delay);
}
Given that you know precisely the list you want to iterate through, and thus the fixed number of iterations you want to execute, this seems cleaner and more concise than setInterval, which you would have to explicitly stop when you reach the end of the list. I like setInterval for things that will run an indeterminate period of time (for instance, until stopped by a user action).
What this says is: "Take this list of numbers (the last one being the random one). Show the first one and remove it from the list. Then wait a while and do it again, until you're out of numbers."
A couple other fine points here:
innerText rather than innerHTML, since you're just setting string content.
You want to use your random number as a key against your array of die faces, not directly - used directly, you get [0-5], not [1-6].
Use the length of your array, rather than hard-coding '6' - always avoid magic numbers when you can. By referring everything back to your constant array, changing the values on the faces of the die (or the number of them) becomes trivial; just change the array and everything else will still work.
Normally, there are stack-size concerns with recursive code. In this case, that wouldn't be a problem because of the small size of the array. But beyond that, the fact that the recursion is going through setTimeout means that each one is a seprate entry on the queue, and the prior isn't waiting for the next to complete before it can exit.

Javascript for() not working

I am trying to make a progress bar with Javascript. I am using a for loop to run the code:
var prog = document.getElementById("progressbar").max;
var progg = document.getElementById("progressbar");
function runAnimation(){
for(var i=0; i < prog; i++){
var hit = progg.value;
hit++;
}
};
This should make the value of the progressbar increment each time the function runs, but it doesn't work. I am not getting any errors in the console. How can I make the progressbar's value rise incrementally?
For an "animated" effect, you can recursively call a setTimeout, based on the current value and max value of your progress bar. Something like:
var progg = document.getElementById("progressbar");
function runAnimation(){
setTimeout(function() {
if (progg.value <= progg.max) {
progg.value++;
runAnimation();
}
}, 10);
};
runAnimation();
Changing your timeout value (10 in the above example) will increase/decrease the progress bar.
Here's a fiddle: http://jsfiddle.net/cL7nygsr/
For a more interesting use of setTimeout (since the above is just basically setInterval), call it after an operation has completed before calling your next iteration. Here's an updated fiddle which includes a random update of the progress bar.
http://jsfiddle.net/cL7nygsr/2/
var b = document.getElementById('progress').max;
window.setInterval(a,1000);
function a() {
document.getElementById('progress').value++;
if (document.getElementById('progress').value >= b) {
window.clearInterval(a);
}
}
Here is code to increment progress bar value every 1 second, you can change to 2 second by replacing 1000 with 2000.
You're not doing anything with your hit variable once you increment it. You want to do this instead:
for (var i = 0; i < prog; i++) {
progg.value++;
}

Problems using setInterval and clearInterval more than once

I'm getting confused with what's happening here. The quiz works fine the first time. After the first play, though, I get all sorts of problems. I want to click the same button,"#start2", to start and also restart the quiz, ie clear the timer, put all variables back to 0 etc, and display the first question. As if the page had been refreshed, basically.
Instead, I'm getting faster ticking, the timer is incrementing on correct guess and so on. Horrible.
I've used modulo to measure how many times the "#start2" div is clicked. On first click, start timer. On second click - I want to reset the timer. Third click - start timer, and so on.
Any help is massively appreciated.
var n = 0;
var x = 0;
var p = 0;
var incTime;
function a(n) {
var x,y,z;
x = Math.floor((Math.random() * 3))
if(x == 0){y = 1; z = 2}else if(x == 1){y = 0; z = 2}else{y = 0; z = 1}
$("#question_holder2").text(questions[n].q);
$(".answer_holder2").eq(x).text(questions[n].a).data('answer', 'a');
$(".answer_holder2").eq(y).text(questions[n].b).data('answer', 'b');
$(".answer_holder2").eq(z).text(questions[n].c).data('answer', 'c');
}
$(document).ready(function() {
//timing element
function startTimer(x){
$("#start2").text(x);
}
$("#start2").click(function(){
var setTimer;
p++;
//if it's been clicked before
if(p%2 === 0){
clearInterval(setTimer);
$("#start2").text("Start");
n = 0;
x = 0;
a(n);
alert("okay");
}else if(p%2 !== 0){
//never been clicked before
a(n);
setTimer = setInterval(function(){startTimer(x=x+1)}, 1000);
$('.answer_holder2').click(function() {
//correct answer given
if ($(this).data('answer') === 'a') {
n++;
if (n < questions.length) {
a(n);
} else {
alert("End of quiz!");
clearInterval(setTimer);
$("#start2").text("You took " + x + " seconds, you answered " + n + " questions correctly, with - incorrect answers given.");
x = 0;
n = 0;
a(n);
}
}else{
//incorrect answer given
$(this).fadeTo(1000,0.4);
var timeString = $("#start2").text();
var incTime = (timeString * 1) + 5;
$("#start2").text(incTime);
startTimer(incTime);
x = incTime;
};
});
};
});
});
You have this:
$("#start2").click(function(){
var setTimer;
p++;
//if it's been clicked before
if(p%2 === 0){
clearInterval(setTimer);
//....
In this case, when you set to the clearInterval line, setTimer will always be 0, and not the id of a running timer. So this is not actually stopping any timer. If you don't stop the timer it will continue to run. So the function here:
setTimer = setInterval(function(){startTimer(x=x+1)}, 1000);
Will continue to run. So the next time you create a timer, you now have two timers updating x and it'll look like it's running faster.
Try this:
$(document).ready(function() {
var setTimer;
$("#start2").click(function(){
// the rest of your click handler code...
});
//timing element
function startTimer(x){
$("#start2").text(x);
}
}
Your setTimer variable needs to exist in a scope outside of your click handler. As you had it you were declaring a new variable every time so when you try and clear the timer, you are not actually clearing the timer.
Also: freakish's point about how you are reattaching the click handler is also a problem. You need to fix that too.
The answer is that bad things happen because of this:
$("#start2").click(function(){
// some code...
$('.answer_holder2').click(function() {
// some code...
});
});
When you click on #start2 new handler is attached to .answer_holder2. So after for example 3 clicks, .answer_holder2 has 3 handlers attached to it and when you click on it all 3 fire.
You're code is a bit complicated and I'm not going to give you a solution how to fix that. But I can give you a hint. Put inner .click outside of outer .click. You will have to change some code probably, but that has to be done.
EDIT What you could try ( as a fast fix, but not necessarly good ) is adding this:
$('.answer_holder2').off( "click" ).click(function() {
Additonally have a look at Matt's answer.

storing the value of setInterval

if I had a code like this
count=0
count2=setInterval('count++',1000)
the count2 variable would always set as 2 not the actual value of count as it increases every second
my question is: can you even store the value of the seInterval() method
The return value of setInterval() is an ID number that can be passed to clearInterval() to stop the periodically executed function from running another time. Here's an example of that:
var id = setInterval(function() {
// Periodically check to see if the element is there
if(document.getElementById('foo')) {
clearInterval(id);
weAreReady();
}
}, 100);
In your example, if you want count2 to have the same value as count, you could use:
var count = 0, count2 = 0;
setInterval(function() {
// I wrote this on two lines for clarity.
++count;
count2 = count;
}, 1000);
setInterval returns an ID which you can later use to clearInterval(), that is to stop the scheduled action from being performed. It will not be related to the count values in any way.
var count=0;
function incrementCount(){
count++;
}
setTimeout("incrementCount()", 1000);

Categories