Restarting setInterval in javaScript - javascript

var myImage = document.getElementById("mainImage");
var imageArray = ["_images/overlook.jpg","_images/winery_sign.jpg","_images/lunch.jpg",
"_images/bigSur.jpg","_images/flag_photo.jpg","_images/mission_look.jpg"];
var imageIndex = 0;
function changeImage() {
myImage.setAttribute("src",imageArray[imageIndex]);
imageIndex++;
if (imageIndex >= imageArray.length) {
imageIndex = 0;
}
}
I tried to refactor this question restarting a setInterval, but couldn't get it right. Any help would be appreciated!
***Added context****
Basically I have a bunch of images that cycle through and stop upon clicking them. I'd like to restart the cycling upon clicking again...
var intervalHandle = setInterval(changeImage,5000);
//Basically I want a clearInterval on a click and then restart this changing image function it.
myImage.onclick = function(){
clearInterval(intervalHandle);
intervalHandle = setInterval(changeImage,5000);
};

I expect the problem is that setInterval doesn't fire immediately, and you're expecting it to call changeImage as soon as you click myImage. The first call to changeImage will be 5 seconds after clicking the image. You could do something like this to call changeImage immediately:
myImage.onclick = function () {
clearInterval(intervalHandle);
intervalHandle = setInterval(changeImage, 5000);
changeImage();
};
Another choice is to do away with intervals entirely (as with this answer) — intervals can queue up when the window isn't focused in some browsers, so you could have changeImage set its own timeouts:
var timeoutHandle = setTimeout(changeImage, 5000);
function changeImage() {
// ...
timeoutHandle = setTimeout(changeImage, 5000);
}
myImage.onclick = function () {
clearTimeout(timeoutHandle);
changeImage();
};

Basically I have a bunch of images that cycle through and stop upon clicking them. I'd like to restart the cycling upon clicking again...
Well why didn't you say so? ;)
So you want to start the interval if its not started, and stop it if it is started.
var intervalHandle = setInterval(changeImage, 5000); // start the interval by default
var running = true; // true if the interval is running, false if its not.
myImage.onclick = function(){
if (running) {
clearInterval(intervalHandle); // stop interval
running = false; // mark interval as stopped
} else {
intervalHandle = setInterval(changeImage, 5000); // start interval
running = true; // mark interval as started
changeImage(); // also change the image right now
}
};

the only reason why i think this would not work is if you define intervalHandle in a "dom ready" event or some other function so try putting it in global scope rather than defining it.
EDIT: sorry for the first reply it was indeed false beacause i didnt had full information of what you wanted to do so home this will help you
var intervalHandle = setInterval(changeImage,5000);
myImage.onclick = function(){
if (intervalHandle > -1) {
clearInterval(intervalHandle);
intervalHandle = -1;
} else {
intervalHandle = setInterval(changeImage,5000);
}
};

Related

Chrome Extensions: Javascript not not running clearInterval();

I'm trying the make a chrome extension in javascript. So far, my popup.js looks like this:
let bg;
let clock;
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('button1').addEventListener('click', butClicked);
bg = chrome.extension.getBackgroundPage();
//clock = document.getElementById("label1");
});
let timeStamp;
let isClockRunning = false;
function butClicked() {
let test = bg.getURL();
document.getElementById('test').innerHTML = test;
timeStamp = new Date();
isClockRunning = !isClockRunning;
runCheckTimer();
}
function runCheckTimer() {
var handle;
if(isClockRunning == true) {
handle = setInterval(updateClock, 1000);
}
else if(isClockRunning == false) {
clearInterval(handle);
handle = 0;
}
}
function updateClock() {
let seconds = bg.returnTimeSince(timeStamp);
document.getElementById("label1").innerHTML = "Seconds: " + seconds;
}
The program works just fine when I click the button once; it starts the timer. But when I click the button the second time, timeStamp gets set to 0, but the updateClock keeps running at the same interval; the interval doesn't get cleared even though I'm toggling the isClockRunning boolean. It's almost as if javascript is forgetting to run the else if part in runCheckTimer(). How can I fix this?
EDIT: On a sidenote, am I doing the timer thing the right way? Or is there a better way to do it? I basically want a timer to keep ticking every second since you've pressed the button, and then when you click it again it'll stop and reset to 0.
You have scoped handle to runCheckTimer. When runCheckTimer starts, it will create a new handle every time.
Move handle outside of the function.
var handle;
function runCheckTimer() {
if(isClockRunning == true) {
handle = setInterval(updateClock, 1000);
}
else if(isClockRunning == false) {
clearInterval(handle);
handle = 0;
}
}

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);
};

Clear interval and variables: clearinterval fails

I have this code: It's very simple. I create an interval, and that works fine, but when I clear it, that statement is the only thing that fails.
clearinterval(interval);
This line fails, dragging don the whole function with it. If I comment out this one line, discomodeoff() works perfectly, besides that my interval is still running.
var interval;
function discomodeon() {
interval = setInterval( 'flashtext()', 50 );
document.body.style.background = "#000000";
discoball.style.visibility="visible";
on.style.display="none";
off.style.display="block";
music.innerHTML = "<embed src='discomusic.mp3' autostart='true' loop='true' hidden='true'></embed>";
}
function discomodeoff() {
clearinterval(interval);
document.body.style.background = "#FFFFFF";
discoball.style.visibility="hidden";
on.style.display="block";
off.style.display="none";
music.innerHTML = "";
}
I'm not sure why it fails, but it causes discomodeoff() to fail.
It's clearInterval, not clearinterval.
function discomodeoff() {
clearInterval(interval);
document.body.style.background = "#FFFFFF";
discoball.style.visibility="hidden";
on.style.display="block";
off.style.display="none";
music.innerHTML = "";
}

onmouseover stop slideshow help

This is a function for a slideshow,onmouseover i want it to stop. Instead of stopping the slideshow onmouseover, it speeds up?? How can i correct this to stop onmouseover?
<body onload="nextslide();">
function nextslide() {
// Hide current slide
var object = document.getElementById('slide' + current); //e.g. slide1
object.style.display = 'none';
// Show next slide, if last, loop back to front
if (current == last) {
current = 1;
} else {
current++;
}
object = document.getElementById('slide' + current);
object.style.display = 'block';
var timeout = setTimeout(nextslide, 2500);
object.onmouseover = function(){
clearTimeout( timeout );
}
object.onmouseout = nextslide;
}
I tried your code and the only problem I can see is on "onmouseout" there is an immediate transition to next slide. I would change that line like this:
object.onmouseout = function() {
timeout = setTimeout(nextslide, 2500);
}
I disagree with Jared, "timeout" is defined there because you are using nested functions and inner functions have access to outer functions scope. You should never omit var when defining variables.

Implement a timer into js function

I have already this function I'm trying to add a timer like this: when value >= 1 and user doesn't move mouse for 1 minute or 60 seconds timer starts and redirect user to a new page but if user moves mouse before 60 seconds end the timer resets again.
function pagar(){
var textarea = document.getElementById ("textarea");
/*if (event.propertyName.toLowerCase () == "value") {
alert ("NUEVO VALOR EN EL CAMPO TOTAL: " + event.srcElement.value);
}*/
if (event.srcElement.value>=1)
{
var bottomMenu = $("#main_footer").bottomMenu([
{name:"backward","class":"red", text:getStr("menu_backward")},
{name:"menu","class":"green", text:getStr("menu_menu"), func:function(){parent.location = "./index.html";}, enabled:false},
{name:"forward","class":"green", text:getStr("menu_pay"), func:forward, enabled:true}
]);
}
else
{
var bottomMenu = $("#main_footer").bottomMenu([
{name:"backward","class":"red", text:getStr("menu_backward")},
{name:"menu","class":"green", text:getStr("menu_menu"), func:function() {parent.location = "./index.html";}, enabled:true},
{name:"forward","class":"green", text:getStr("menu_pay"), func:forward, enabled:false}
]);
}
}
I want to add a timer after this:
if (event.srcElement.value>=1)
{
You'll want to attach a mousemove event listener to the window which clears and resets a timer upon movement.
function MouseMoveTimeout() {
// Whatever you want the timeout to do
}
var TimerID;
function InstallMouseMoveTimeout(Install) {
var Timeout = 60000;
var MouseMoveDetector = function(e) {
clearTimeout(TimerID);
TimerID = setTimeout(MouseMoveTimeout, Timeout);
}
if(Install && TimerID == undefined) {
TimerID = setTimeout(MouseMoveTimeout, Timeout);
window.addEventListener('mousemove', MouseMoveDetector, true);
} else {
clearTimeout(TimerID);
window.removeEventListener('mousemove', MouseMoveDetector, true);
TimerID = undefined;
}
}
To use this in your code you would:
if (event.srcElement.value>=1) {
InstallMouseMoveTimeout(true); // Install mouse move timeout
...
} else {
InstallMouseMoveTimeout(false); // Cancel mouse move timeout
...
}
var idleTimer = null; // do this in the global scope
// do the following at the location where you want to reset the timer:
if(idleTimer) window.clearTimeout(idleTimer);
idleTimer = window.setTimeout(function() {
location.href = 'other-site';
}, 60000);
So whenever the second block of code is called the old timer is reset and a new one is started. However, since mousemove events trigger very often, this might screw up performance. In this case create an interval (setInterval()) which triggers e.g. every 10 seconds and only set the current date in your mousemove handler. Then you can simply check in your timer callback if enough time since the last mousemove has exceeded and in this case execute an action.
Sounds like a crazy UI idea! But if you want to do that, you need to declare this somewhere:
var timer;
When you want to start the timer running, do this:
timer = setTimeout(function() { timer = -1; doStuff(); }, seconds * 1000);
That will call doStuff after seconds has elapsed.
If you want to cancel the timer:
if (timer != -1) {
clearTimeout(timer);
timer = -1;
}
By combining these appropriately, you can solve your problem.

Categories