How to make clearInterval() work in JavaScript - javascript

I want to make an element (id=runner) move across the page by n pixels after a mouseover event, then stop at a certain position (left = 2000px), using setInterval() to repeatedly call move_left(), then clearInterval() when left == 200px. I can make the element move, but when I look in developer tools it never stops - left continues to increase. I am pretty new to JavaScript/HTML/CSS. How do I make it stop?
Relevant code:
<script>
function runner_go()
{
var load_time = performance.now();
const go = setInterval(move_left,20);
}
function move_left()
{
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position,10) + 17 + "px";
if (parseInt(runner_position,10) > 2000)
{
clearInterval(go);
}
}
</script>
</head>
<body style="background-color:gray;" onmouseover = "runner_go();">
<div>
<h1>Running!</h1>
</div>
<img src="images/runner_l.png" alt ="running man" style="position:relative; visibility:hidden;" id = "runner"/>
</body>

You need to create the var 'go' outside the method cause of the scope, also if you let on the 'body' the 'onmouseover' it will set the interval everytime.
Try this code to test:
<head>
<script>
let go = null;
function runner_go()
{
var load_time = performance.now();
go = setInterval(move_left,20);
}
function move_left()
{
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position,10) + 17 + "px";
if (parseInt(runner_position,10) > 2000)
{
clearInterval(go);
}
}
</script>
</head>
<body style="background-color:gray;" onclick = "runner_go();">
<div>
<h1>Running!</h1>
</div>
<img src="images/runner_l.png" alt ="running man" style="position:relative; visibility:hidden;" id = "runner"/> </body>

Problem -
You declared the interval variable as a constant within another function which is not accessible by the move_left function
So just move your interval variable to global scope (outside the function) and it should work
let go;
function runner_go() {
var load_time = performance.now();
go = setInterval(move_left, 20);
}
function move_left() {
document.getElementById('runner').style.visibility = "visible";
var runner_position = getComputedStyle(document.getElementById('runner')).getPropertyValue('left');
document.getElementById('runner').style.left = parseInt(runner_position, 10) + 17 + "px";
if (parseInt(runner_position, 10) > 2000) {
clearInterval(go);
}
}
sample on how intervals and clearIntervals work
let interval, i = 1;
function start() {
interval = setInterval(log, 1000);
}
function log() {
if (i >= 5) clearInterval(interval);
console.log(`Test ${i}`);
i++
}
start();

Related

Is these a way to add 1 and then after one second than add 2 and than 3 etc

What I am looking for would essentially be a "++" to a "++" command using native java script. The program simply runs an animation for a given number in which the idea of the animatio is that it adds 1 after one second, two after two seconds and keeps going in the same fashion until the animation is stopped.
var counter = 10;
var animationOn = false;
var counterAnimation;
var plusOne;
function updateCounter() {
//update the counter value
var plusOne = counter++;
for (var i = 1; i = < 100000000;) {
}
//show the counter
var counterSpan = document.getElementById("counterHolder");
counterSpan.innerHTML = plusOne;
}
function startCounterAnimation() {
if (animationOn == false) {
animationOn == true;
counterAnimation = setInterval(updateCounter, 1000);
}
}
function stopCounterAnimation() {
if (animationOn == true) {
animationOn == false;
}
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick="startCounterAnimation();">
Start counter animation
</button>
<button onclick="stopCounterAnimation();">
Stop counter animation
</button>
<span id="counterHolder">6931418</span>
</body>
</html>
You don't need the for loop.
You should assign to the global plusOne variable, not declare a local variable in the function.
You should add counter++ to it, not assign that directly.
Initialize plusOne from the number already in the output span.
Since your time intervals change between each update, you can't use setInterval(). Use setTimeout() to make a different timeout each time.
Use =, not ==, to assign to the animationOn variable.
var counter;
var animationOn = false;
var counterAnimation;
var plusOne = parseInt(document.getElementById("counterHolder").innerHTML);
function updateCounter() {
//update the counter value
plusOne += counter++;
//show the counter
var counterSpan = document.getElementById("counterHolder");
counterSpan.innerHTML = plusOne;
counterAnimation = setTimeout(updateCounter, counter * 1000);
}
function startCounterAnimation() {
if (!animationOn) {
animationOn = true;
counter = 1;
counterAnimation = setTimeout(updateCounter, 1000 * counter);
}
}
function stopCounterAnimation() {
if (animationOn) {
animationOn = false;
clearTimeout(counterAnimation);
}
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick="startCounterAnimation();">
Start counter animation
</button>
<button onclick="stopCounterAnimation();">
Stop counter animation
</button>
<span id="counterHolder">6931418</span>
</body>
</html>
You canĀ“t define var onePlus in two places, instead define it once and assign a value, var is wide scoped
Also add whatever logic you need in the for loop and put the onePlus ++ and counter as parts of the for loop
As it is now you are expecting to use the counter both outside the for loop and as the for loop middle part, which seems reduntant
Try something like(leaving the variable names as are):
var counter = 1000
for (var plusOne = 1; plusOne < counter; plusOne++) {
//Your logic in here
await sleep(1000);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

How so I make the background of the page red, after the counter reaches zero?

This is my code and it runs, but I have to change the background color to red when the counter reaches zero.
<script>
window.onload = function () {
const tag = document.getElementById("tag1");
var time = 100;
const getTime = ()=>{
time = time - 1;
tag.innerHTML = "Goodbye Aliens: ship leaves in " + time + " secs ";
}
setInterval(getTime, 500);
}
</script>
<body>
<div>
<h1 id="tag1">Hello Earthling</h1>
</div>
</body>
<script>
const tag = document.getElementById("tag1");
tag.innerHTML = "Goodbye Aliens";
</script>
</html>
I thought of something like this in order to do it:
function changeColor() {
if (time == 0) {
document.change.bgColor = "red";
}
}
but it does not work and I do not understand where to put the code in the first place.
Please explain if someone has time. Thanks
My approach would be to check the time variable inside the GetTime method and calling changeColor when its 0.
Then you need to clear the interval using clearInterval to stop the loop.
function changeColor() {
document.querySelector("body").style.backgroundColor = "red";
}
window.onload = function () {
const tag = document.getElementById("tag1");
var time = 10;
const getTime = () =>{
time = time - 1;
tag.innerHTML = "Goodbye Aliens: ship leaves in " + time + " secs ";
if(time === 0){
changeColor();
window.clearInterval(interval);
}
}
var interval = setInterval(getTime, 500);
}
const tag = document.getElementById("tag1");
tag.innerHTML = "Goodbye Aliens";
<div>
<h1 id="tag1">Hello Earthling</h1>
</div>
I tend to favour setTimeout over setInterval. It seems more managable.
Note: I've used a class here instead of directly setting the style on the element.
const tag = document.getElementById('tag1');
// `getTime` accepts a time argument which
// we initialise as 100
function getTime(time = 100) {
// Print the message using `textContent` rather than `innerHTML`
tag.textContent = `Goodbye Aliens: ship leaves in ${time} secs`;
// If time reaches 0 set the background to red using a class
if (time === 0) {
tag.classList.add('red');
// Otherwise call `getTime` again passing in a decremented
// `time` value as the argument
} else {
setTimeout(getTime, 50, --time);
}
}
// Call `getTime` after showing the initial message
setTimeout(getTime, 2000);
.red { background-color: red; }
<div>
<h3 id="tag1">Hello Earthling</h3>
</div>

Executing two functions in the same onclick event but running one only once

I'm trying to get an image to run two javascript functions at the same time, the problem is that I want the changeImg() function to run continually with each click but only execute the clock() function once. (So that it starts the timer).
<img id="emotion" src="Target.jfif" width="50" onclick="changeImg();clock(); this.onclick=null;"/>
This is my changeImg() script:
{
var x = Math.floor(Math.random()*900);
var y = Math.floor(Math.random()*900);
var obj = document.getElementById("emotion");
obj.style.top = x + "px";
obj.style.left = y + "px";
}
And this is my clock() script:
function clock() {
myTimer = setInterval(myClock, 1000);
var c = 30;
function myClock() {
document.getElementById("demo").innerHTML = --c;
if (c == 0) {
clearInterval(myTimer);
alert("Reached zero");
}
}
}
Have clock() check if the timer is already set, and return.
function clock() {
if (myTimer) { // clock already started
return;
}
myTimer = setInterval(myClock, 1000);
var c = 30;
function myClock() {
document.getElementById("demo").innerHTML = --c;
if (c == 0) {
clearInterval(myTimer);
alert("Reached zero");
}
}
}
instead of passing null to onclick pass the function changeImg
onclick="changeImg();clock();this.onclick=changeImg;"
I don't know about good practices but it works without changing your code too much

error on trying to change image in sequence from list JavaScript

I have a list:
var images = ["image1.png", "image2.png", "image3.png", "image4.png"];
I made a code which attempts at displaying image1 when the page loads but for ever 3 seconds the image changes to the next image in the list. However when the code was ran it was stuck on image1 and did not change in the next 3 seconds.
This is my JavaScript code so far:
<html>
<body>
<body onload = "myFunction()">
<img src ="image1.png" id = "target" >
<script language="javascript">
var counter = 0;
var images = ["image1.png", "image2.png", "image3.png", "image4.png"];
function myFunction() {
counter++;
if (counter > 4) {
counter = 0
}
target = document.getElementById ("target").src = images[counter];
setTimeout("myFunction", 3000)
}
window.onLoad = function(){
myFunction();
}
</script>
</body>
</html>
I have seen similar codes but the answers answered did not meet my specification.
You can use setInterval (passing a function rather than a string) instead of recursively calling setTimeout. Also note that your counter logic can be greatly simplified with the use of the modulo (%) operator:
<html>
<body>
<img src="image1.png" alt="image1.png" id="target">
<script language="javascript">
var counter = 0;
var images = ["image1.png", "image2.png", "image3.png", "image4.png"];
var target = document.getElementById("target")
setInterval(function myFunction() {
counter = (counter + 1) % images.length
target.src = target.alt = images[counter]
}, 3000)
</script>
</body>
</html>
In setInterval, you need to pass the function myFunction as parameter, not the function name "myFunction":
Change it to this:
setTimeout(myFunction, 3000);
setTimeout - will work only one time
setInterval - will continue always
<html>
<body>
<img src ="logo.png" id = "target" >
<script language="javascript">
var counter = 0;
var images = ["logo.png", "222.jpg"];
function myFunction() {
counter++;
if (counter > 1) {
counter = 0
}
target = document.getElementById("target").src = images[counter];
}
function my2(){
setInterval("myFunction()", 1000);
}
window.onload = function(){
my2();
}
</script>
</body>
</html>
Expanding on what others have mentioned already.
It's window.onload - not window.onLoad - Casing is important
Update to
setTimeout(myFunction, 3000);
Place that in your window.onload
JS:
var counter = 0;
var images = ["image1.png", "image2.png", "image3.png", "image4.png"];
function myFunction() {
counter++;
if (counter > 4) {
counter = 0
}
target = document.getElementById ("target").src = images[counter];
}
window.onload = function(){
setTimeout(myFunction, 3000)
}
You can use setInterval instead of setTimeout
var counter = 0;
var images = ["image1.png", "image2.png", "image3.png", "image4.png"];
function myFunction() {
counter++;
if (counter > 3) {
counter = 0
}
target = document.getElementById("target").src = images[counter];
}
setInterval(myFunction, 3000);
JSFiddle

Onclick reset setInterval

<!DOCTYPE html>
<html>
<head>
<script>
function timer(x) {
if (x == 1) {
//reset timer
}
var i = 0;
var timer = setInterval(function() {
var x = document.getElementById("demo").innerHTML = i;
i = i + 1;
}, 500);
}
</script>
</head>
<body>
<p id="demo">hello</p>
<button type="button" onclick="timer(0)">change</button>
<button type="button" onclick="timer(1)">reset</button>
</body>
</html>
I want to reset timer onclick . e.g. if setIntervaltime is set to 5 sec and 3 seconds are elapsed ,after that if some on click on reset button it should start gain from 5 seconds.How to do this.
Keep the return value of setTimeout somewhere that you can get it again (currently you are storing it in a local variable, so it goes away when the function ends)
Call clearTimeout(timer);
Call setTimeout with whatever arguments you want again.
As already Quentin mentioned, use clearInterval to solve your problem.
Wrap it within an if.else.. statement like
if(x == 1) {
clearTimeout(timeout);
}
else {
timeout = setInterval..... // otherwise even after resetting
// it will continue to increment the value
}
Complete Code:
var timeout; // has to be a global variable
function timer(x) {
var i = 0;
if (x == 1) {
clearTimeout(timeout);
document.getElementById("demo").innerHTML = i;
} else {
timeout = setInterval(function () {
var x = document.getElementById("demo").innerHTML = i;
i = i + 1;
}, 1000);
}
}
JSFiddle

Categories