Reputation: 13
Here is my html:
<div class="slider_container Centered">
<figure id="Slider">
<img src="Images/HBC.jpg" id="1" class="effect Image"/>
<img src="Images/Easter-Pic.jpg" id="2" class="effect Image"/>
</figure>
</div>
and my Javascript:
var Figure_Slider;
var Images;
var Image_Num;
var Current_Element;
var Previous_Element;
function main()
{
Figure_Slider = document.getElementById("Slider");
Images = document.getElementById("Slider").children;
Image_Num = Images.length;
for (var i = 1; i <= Image_Num; i++)
{
var index = i;
Current_Element = document.getElementById(i.toString());
if (index == 1)
{
Current_Element.classList.add("active");
}
else
{
Previous_Element.classList.remove("active");
Current_Element.classList.add("active");
}
window.setTimeout(function(){advance();}, 4000); //This doesn't work
advance();
}
Current_Element.classList.remove("active");
}
function advance()
{
Previous_Element = Current_Element;
}
window.onload = main;
I'm trying to make an image slider. When I use the Chrome debug tools, and step through the javascript manually, it works fine. When I just run it straight, the timer is not executed. What is wrong with the setTimeout
function? I've seen many examples of its output not being given to a variable, so that's not it. I even did the anonymous function fix. The advance();
call underneath the setTimeout
is just temporary so I could view the logic. Without the advance();
line, the script drops an unhandled event where the Previous_Element
has no class named active to remove. Therefore, both parts of the timer statement (delay, and function execution) don't happen. Other than that, the code works fine. Let me know if you need the CSS. I've tried some of the fixes:
function wait(delay)
{
setInterval(advance(), delay);
}
Then calling that function in the loop, but it locks up the browser using 100% or more of my CPU. Is there another way of doing this?
Thanks in advance.
Upvotes: 0
Views: 2029
Reputation: 13
Turns out, the documentation forgot to mention how setTimout
and setInterval
work. When execution gets to this command, it starts the timer, and CONTINUES with the code. Once the timer is finished, THEN the internal function is executed. The program does not pause until the internal function is executed. My logic had be changed so that I used setInterval
, and it was the last line of code for my main function. The documentation for setTimout
and setInterval
should have included this crucial information. Here's what my main now looks like
function main()
{
Figure_Slider = document.getElementById("Slider");
Images = document.getElementById("Slider").children;
Caption = document.getElementById("Caption");
Image_Num = Images.length;
Image_Counter = 1;
Current_Element = document.getElementById(Image_Counter.toString());
Current_Element.classList.add("active");
Caption.innerHTML = Current_Element.alt;
window.setInterval(function (){image_slider();}, 5000);
}
Thanks for your help anyway.
Upvotes: 0
Reputation: 163
It works as expected. Please check my fiddle demo https://jsfiddle.net/jrsucfc4/1
function advance(param) {
advanceCallCount++;
console.log('advanceCallCount = ' + advanceCallCount+ '; advance param: ' + param);
Previous_Element = Current_Element;
}
The other thing is what do you expect to get as result of this execution?
Upvotes: 0
Reputation: 9
Please wrap your setTimeout function in a closure with IIFE.
for (var i = 1; i <= 3; i++)
{
(function(idx)
{
setTimeout(function() { alert(idx); }, i * 500);
})(i);
}
Hope it will help you.
Upvotes: 1
Reputation: 232
Part of the problem is that the setTimeout() functions are called twice, but they are called almost at the exact same time. It takes almost no time at all for the for loop to iterate twice through your list of two images, so setTimeout() is called almost at the exact same time. That makes it look like it's only being called once. Try putting a console.log in the line before the setTimeout and then another console log inside of the setTimeout--it'll help show when everything happens. This SO question/answer also explains it nicely: setTimeout in for-loop does not print consecutive values
Upvotes: 0
Reputation:
Loops/Iterations are blocking in nature while setTimeout is asynchronous/unblocking in nature. SetTimeout would not work when placed in a for loop, this would work fine!
function wait(fn) {
window.setTimeout(function() { fn(); }, 1000);
}
for (var i = 1; i <=5; ++i){
/* ... */
wait(advance);
/* ... */
}
If you wanted to use setTimeout to wait for some time and then execute, you could use this (if yes, you should have mentioned it in the question)
function blockUntil(fn,delay){
var until = new Date().getTime() + delay;
while(new Date().getTime() < until) {};
fn();
}
for (var i = 0; i < 5; i++) {
blockUntil(advance,1000);
};
Upvotes: 0