setInterval and clearInterval not working as expected - javascript

I have this function which acts as a loading box using setInterval to change the background images which creates a flashing effect.
function loading() {
clearInterval(start);
var i = 0;
function boxes() {
in_loading = ".in_loading:eq(" + i + ")";
$(".in_loading").css("background", "url(images/load_bar_green.png) no-repeat");
$(in_loading).css("background", "url(images/load_bar_blue.png) no-repeat");
if(i == 3) {
i = 0;
} else {
i++;
}
}
var start = setInterval(function() {
boxes();
}, 350);
}
But even with clearInterval if I click on it more than once the flashing goes out of order. I tried removing the boxes, hiding them but I can't seem to get the 'buffer' cleared? Any ideas?

The reason why it keeps flashing is because every time loading gets called it creates a new variable start, so clearInterval is actually doing nothing. You also shouldn't have the boxes function within loading because it is doing the same thing, creating a new boxes function every time loading is called. This will add a lot of lag the longer the script executes.
var i = 0;
var start;
function loading() {
clearInterval(start);
start = setInterval(function() {
boxes();
}, 350);
}
function boxes() {
var in_loading = ".in_loading:eq(" + i + ")";
$(".in_loading").css("background", "url(images/load_bar_green.png) no-repeat");
$(in_loading).css("background", "url(images/load_bar_blue.png) no-repeat");
if(i == 3) {
i = 0;
} else {
i++;
}
}

Function declarations get "hoisted" to the top of their scope, this is what is messing the execution order. Check this: http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

The reason is every time you call loading it creates a new Interval or new var start. So if you click it twice, then you have two things manipulating the same data. So you need to have the var start outside of the function and the clearInterval inside. So every time you call loading it clears the interval and creates a new one.
var i = 0;
var start;
function loading() {
clearInterval(start);
start = setInterval(boxes, 350);
}
function boxes() {
in_loading = ".in_loading:eq(" + i + ")";
$(".in_loading").css("background", "url(images/load_bar_green.png) no-repeat");
$(in_loading).css("background", "url(images/load_bar_blue.png) no-repeat");
if(i == 3) {
i = 0;
} else {
i++;
}
}

maybe you should take a look at this Jquery Plugin , it seems to manage intervals very well .
Jquery Timers Plugin

Related

Clearing setInterval() Issue

I have a setInterval on a function X that runs every 500ms. In this function X, I call another function Y that essentially binds an event on some divs. However, I would like to unbind these events the next time the function X is called (to start "fresh"). My code doesn't seem to work:
setInterval(this.board.updateBoard, 500); //called from another constructor
This then initiates the functions below:
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
for(var i = 0; i < divs.length; i++) {
$(divs[i]).unbind(); //Apparently this doesn't work?
}
//...some code here...
//find appropriate $div's (multiple of them), and then calls this.beginWalking() below on each of those
//loop here
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
return setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
};
Basically, updateBoard is called every 500ms. Each time it's called, beginWalking is called to set another interval on a div. The purpose of this other interval, which functions correctly, is to add and remove a class every 80ms. I just can't seem to unbind everything before the next updateBoard is called.
Any suggestions appreciated!
use clearInterval()
edit: $(selector).toggleClass(dir0) might also be helpful
// In other file, use a global (no var) if you need to read it from another file:
updaterGlobal = setInterval(this.board.updateBoard, 500);
// store interval references for clearing:
var updaterLocals = [];
Board.prototype.updateBoard = function() {
//I attempt to unbind ALL my divs
var divs = this.$el.find("div");
// Stop existing div timers:
while(updaterLocals.length > 0){
clearInterval(updaterLocals[0]);
updaterLocals.shift(); // remove the first timer
}
//...some code here...
//loop here to call the below on several $div's
this.beginWalking($div, direction + "0", direction + "1");
//end of loop
}
//alternate between classes to give appearance of walking
Board.prototype.beginWalking = function ($div, dir0, dir1) {
var interval = setInterval(function () {
if ($div.hasClass(dir0)) {
$div.removeClass(dir0);
$div.addClass(dir1);
} else {
$div.removeClass(dir1);
$div.addClass(dir0);
}
}.bind(this), 80);
// Save the timer:
updaterLocals.push(interval);
return;
};

jQuery. Why it shows extra elements?

This code creates elements when the video reaches a specified time(I'm using YouTube iFrame API). And it gets information from array of json objects that came from server. But when almost all objects passed during the time with showing and hiding elements it starts to add to normal element new elements in order from beginning. I don't know why these elements are added.
// when the player is ready, start checking the current time every 1000 ms.
function onPlayerReady() {
function updateTime() {
var oldTime = videotime;
if(player && player.getCurrentTime) {
videotime = +player.getCurrentTime().toFixed();
}
if(videotime !== oldTime) {
onProgress(videotime);
}
}
timeupdater = setInterval(updateTime, 1000);
}
// when the time changes, this will be called.
function onProgress(currentTime) {
var ci = array_of_json.length;
console.log(currentTime);
for(i = 0; i < ci; i++){
if(currentTime === array_of_json[i].time) {
$(document).ready(function(){
$( '#pos_wrapper' ).prepend( "<div class='emotion " + array_of_json[i].emotion
+ "' style='display: none'></div>" );
(function(){
var selector = 'div.'+array_of_json[i].emotion;
$(selector).show(1000);
$(selector).fadeOut(10000);
})();
});
}
}
}
i think that you need to add clearInterval(timeupdater); in this condition
if(videotime !== oldTime) {
onProgress(videotime);
}
or the loop will never stop calling your function onProgress so it you should try this
if(videotime !== oldTime) {
clearInterval(timeupdater);
onProgress(videotime);
}
I've already solved the problem. I added in fadeOut callback function that removes current element.

JQuery transition animation

This program randomly selects two employees from a json-object Employees array, winnerPos is already defined.
For better user experience I programmed these functions to change pictures one by one. The animation stops when the randomly selected person is shown on the screen.
The slideThrough function will be triggered when the start button is pressed.
function slideThrough() {
counter = 0;
start = true;
clearInterval(picInterval);
picInterval = setInterval(function () {
changePicture();
}, 500);
}
function changePicture() {
if (start) {
if (counter > winnerPos) {
setWinner();
start = false;
killInterval();
} else {
var employee = Employees[counter];
winnerPic.fadeOut(200, function () {
this.src = 'img/' + employee.image;
winnerName.html(employee.name);
$(this).fadeIn(300);
});
counter++;
}
}
}
The problem is the animation doesn't work smoothly. At first it works, but not perfect. The second time the transition happens in an irregular way, i.e. different speed and fadeIn/fadeOut differs from picture to picture.
Could anyone help me to fine-tune the transition?
I would avoid using setInterval() and add a function to the call to .fadeIn() that starts the animation of the next picture.
It would look like this:
function changePicture(pos) {
pos = pos || 0;
if (pos <= winnerPos) {
var employee = Employees[pos];
winnerPic.fadeOut(200, function() {
this.src = 'img/' + employee.image;
winnerName.html(employee.name);
$(this).fadeIn(300, function() {
changePicture(pos + 1);
});
});
} else {
setWinner();
}
}
To start the animation, you call changePicture() without any arguments, like this.
changePicture();
jsfiddle

window.settimeout in javascript loading too fast

I have this js code that has to make the height of a panel bigger on load of my page. But it seems to be loading it way too fast.
var TimerID;
function LoadDoc() {
for(i=0;i<=100;i++){
TimerID=window.setTimeout(MoveRolldownDown(i),5000);
}
}
function MoveRolldownDown(i){
document.getElementById('Rolldown').style.height=i + '%';
window.clearTimeout(TimerID);
}
This loads in the page nearly instantly, so how can i make this load slower. At the top of my HTML page i have this code
document.onreadystatechange = function () {
if(document.readyState === "complete"){
LoadDoc();
}
}
1st thing -- your functions are executing immediately so you need to put them inside of another function.
One more thing -- all of your timeouts end at basically the same time!
Try something like this:
function LoadDoc() {
for (i = 0; i <= 100; i++) {
var down = i;
setTimeout((function (down) {
return function(){ //return function for timeout
MoveRolldownDown(down);
};
})(i), 10 * i);
}
}
function MoveRolldownDown(i) {
document.getElementById('Rolldown').style.height = i + '%';
}
Demo: http://jsfiddle.net/maniator/RTaZh/
Yes, it because you are calling the function within the parameters,
You probably want something like
window.setTimeout(MoveRolldownDown,5000, [i]);
https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout

JS clearInterval() will not clear

Just moments ago I asked a question about why my setInterval() function would only run once,
JS setInterval() only runs once when animating opacity
I had that answered, but then I wanted to check and make sure the loop stopped, so I added an alert() to the loop and found out clearInterval is not clearing even though I initially ran the setInterval function connected to a global variable...
the opacity change works fine, but now the alert box goes on infinitely after you click OK... eventually I won't need the alert function I just wanted to see if the interval actually cleared which it doesn't...
var run;
var runOpt;
document.getElementById('menu-1-A').style.opacity=0;
document.getElementById('menu-1-B').style.opacity=0;
function openSubMenu1(item) {
runOpt=item;
run = setInterval(runSubMenu1,35);
}
function runSubMenu1() {
var i=document.getElementById('menu-1-'+runOpt);
if (parseInt(i.style.opacity) == 1) {
clearInterval(run);
alert('done');
} else {
i.style.opacity = parseFloat(i.style.opacity) + .1;
}
}
Thank you plalx -- openSubMenu1() was run from onmouseover which was repeatedly calling openSubMenu1(), I created a variable to test if the menu is open, if it is openSubMenu1() returns false before calling setInterval()..
now it only runs once. Thanks.
What may be happening is that you are starting multiple instances before the first setInterval has finished, so the clearTimeout has the wrong reference when called.
The following uses closures instead of globals so each call has its own timeout reference:
<div id="d0">jere</div>
<script>
var makeOpaque = (function() {
var timeout, el;
return function(id) {
if (!el) {
el = document.getElementById(id);
timeout = setInterval(makeOpaque, 50)
} else if (el && el.style.opacity < 1) {
el.style.opacity = +el.style.opacity + 0.1;
// debug
console.log(el.id + ' : ' + el.style.opacity);
} else {
timeout && clearInterval(timeout);
alert('done');
}
}
}());
makeOpaque('d0');

Categories

Resources