Using setTimeout in a for loop - javascript

Why does setTimeout not work inside a for loop? I'm trying to have a class added to each frame one at a time and every three seconds I need to remove it from the current one and add it to the next. When It gets to frame-6 I need it to wait ten seconds before removing the class. Then I need it all to repeat. But its just adding the class to them all straight away and then not removing them.
for(i = 1; i < 6; i++){
jQuery('.frame-'+i).addClass('color');
if(i < 6){
setTimeout(function(){
jQuery('.frame-'+i).removeClass('color');
}, 3000);
}else if(i = 6){
setTimeout(function(){
jQuery('.frame-'+i).removeClass('color');
i = 1;
}, 10000);
}
}
.color{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="frame-1">one</div>
<div class="frame-2">two</div>
<div class="frame-3">three</div>
<div class="frame-4">four</div>
<div class="frame-5">five</div>
<div class="frame-6">six</div>

There are 2 issues with your code. Firstly, you're expecting the timeouts to execute before the next one is created, which is wrong. You're creating them all at the same time. Secondly, you're reusing the i variable inside the timeouts, so when they fire it's 6, for all of them.
However, you can make a recursive function to handle all of this, like this...
function timeoutHandler(i) {
// if no value is passed, set i = 1
if (!i) i = 1;
// if i < 6 then create a setTimeout for 3 seconds
// when we remove the class and call the function again with i + 1
if (i < 6) {
setTimeout(function() {
$(".frame-" + i).removeClass("color");
timeoutHandler(++i);
}, 3000);
}
// else (i == 6) setTimeout for 10 seconds
// when we remove the class and stop
else {
setTimeout(function() {
$(".frame-" + i).removeClass("color");
}, 10000);
}
}
// add class to initialise - should really do this in html
for(i = 1; i < 7; i++) {
$(".frame-" + i).addClass("color");
}
// start
timeoutHandler();
.color{
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="frame-1">one</div>
<div class="frame-2">two</div>
<div class="frame-3">three</div>
<div class="frame-4">four</div>
<div class="frame-5">five</div>
<div class="frame-6">six</div>

Related

Delaying While Loop in JavaScript

<html>
<body>
Click Here
<body>
</html>
I am using the following code to check the href attribute of the anchor tag and if it is blank I want to show alert for now. But when I write the code of javaScript in web browser console my complete system ends up unresponsive for quite some time. I might be doing something wrong. Can someone explain me what?
var a = document.getElementById("content2").getAttribute("href");
let i = 0;
while(a.trim().length < 1)
{
task(i);
}
function task(i) {
setTimeout(function() {
alert(i);
}, 1000 * 10);
}
Your timeout call seems to be within a while loop which gets called a ton of times. It should be
var a = document.getElementById("content2").getAttribute("href");
let i = 0;
if (a.trim().length < 1) {
task(i);
}
function task(i) {
setTimeout(function() {
alert(i);
if (a.trim().length < 1) {
task(++i);
}
}, 1000 * 10);
}
<html>
<body>
Click Here
</body>
</html>
This runs your loop after each attempt where a.trim().length < 1
You need change while loop to if condition, the while loop have never ended.
var a = document.getElementById("content2").getAttribute("href");
let i = 0;
if(a.trim().length < 1)
{
task(i);
}
function task(i) {
setTimeout(function() {
alert(i);
}, 1000 * 10);
}
<html>
<body>
Click Here
<body>
</html>

How to show and hide previous and new item by time interval Jquery

I work with big quantity of data, and all data are not fering in screen, was decided to change data depends of time interval. When my page is load in array i received 18 items, which i put in to div's.
So i need show in page first 8 items, after 10 second, another 8 items, and in the end show 2 items (because i have only 18 items.).
So i create script which show one by one div's, but i need show 8 in 10 second
var current = 0;
setInterval(function () {
var divs = $(".cards").hide();
divs.eq(current).fadeIn("normal");
console.log(divs.eq(current))
if (current < divs.length - 1)
current++;
else
current = 0;
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cards">1</div>
<div class="cards">2</div>
<div class="cards">3</div>
<div class="cards">4</div>
<div class="cards">5</div>
<div class="cards">6</div>
<div class="cards">7</div>
<div class="cards">8</div>
<div class="cards">9</div>
<div class="cards">10</div>
<div class="cards">11</div>
<div class="cards">12</div>
<div class="cards">13</div>
<div class="cards">14</div>
<div class="cards">15</div>
<div class="cards">16</div>
<div class="cards">17</div>
<div class="cards">18</div>
So how it's must works:
First 10 sec show div's from 1-8
After 10 sec show items from 9-16
And in the end show rest 2 div's
But for this exmple i have 18, but this data will be dynamicaly, and i dont know how many div's i will have
A solution:
var current = 0;
$(".cards").hide();
setInterval(function () {
var divs = $(".cards").hide();
var i = 0;
while (i < 8) {
divs.eq(current).fadeIn("normal");
console.log(divs.eq(current))
if (current < divs.length) {
i++;
current = current + 1;
} else {
i = 0;
current = 0;
}
}
}, 10000);
Solution was found:
script:
$(document).ready(function () {
var elements = $(".cards");
var index = 0;
var showNext = function (index) {
if (index >= elements.length) {
index = 0;
}
console.log(index);
elements.hide().slice(index, index + 8).show();
setTimeout(function () {
showNext(index + 8)
}, 10000);
}
showNext(0);
});

I am trying to show a random div with setinterval()

I am getting - Uncaught TypeError: Cannot read property 'style' of null
when I try to run the following:
<script type="text/javascript">
function startRotation() {
setInterval(resetAllDivs(), 20000);
}
function resetAllDivs(){
var i;
for(i=1; i<=15; i++) {
document.getElementById("img"+i).style.display = "none";
}
displayRandom();
}
function displayRandom(){
var n=Math.round(Math.random()*3)
document.getElementById("img"+n).style.display = "block";
document.getElementById("img"+n).style.width = "64%";
}
</script>
I am calling startRotation() above my closing using:
document.addEventListener('DOMContentLoaded',function(){startRotation()});
The error points to the line:
document.getElementById("img"+i).style.display = "none";
Any ideas?
A few things to note, some of them have be pointed out in the comments already, but I'll reiterate.
setInterval expects a function reference as its first parameter, you're passing in the return result of a call to resetAllDivs(), which is undefined. Really you've got
setInterval(undefined, 20000);
which won't work. You want
setInterval(resetAllDivs, 20000);
Next, this line will get you a random number between 0 - 3, which I don't think is what you were after. It's why you sometimes you'll try document.getElementById('img0'), which returns null.
Math.round(Math.random()*3)
Instead, this will get you a number between 1 - 15:
Math.floor((Math.random() * 15) + 1);
Here is a working example. Timing reduced to half a second instead of 20.
DEMO
function startRotation() {
resetAllDivs();
setInterval(resetAllDivs, 500);
}
function resetAllDivs(){
for (var i = 1; i <= 15; i++) {
document.getElementById("img" + i).style.display = "none";
}
displayRandom();
}
function displayRandom(){
var n = Math.floor((Math.random() * 15) + 1);
document.getElementById("img" + n).style.display = "block";
document.getElementById("img" + n).style.width = "64%";
}
startRotation();
div {
width: 50px;
height: 50px;
background-color: red;
}
div:nth-child(even) {
background-color: blue;
}
<div id="img1"></div>
<div id="img2"></div>
<div id="img3"></div>
<div id="img4"></div>
<div id="img5"></div>
<div id="img6"></div>
<div id="img7"></div>
<div id="img8"></div>
<div id="img9"></div>
<div id="img10"></div>
<div id="img11"></div>
<div id="img12"></div>
<div id="img13"></div>
<div id="img14"></div>
<div id="img15"></div>
This code could definitely be refactored into something smarter. I'd also advise using setTimeout over setInterval, as you gain more control.
One of your document.getElementById("img"+i) is returning a null value, wich means that the element doesn't exist or wasn't created before your resetAllDvis() functions runs.
You should use:
Math.floor((Math.random() * 15) + 1);
to return a random number between 1 and 15.
Make sure you have images with id's from id="img1" to id="img15".

setInterval doesnt tigger inner script on first time run

Maybe I'm not properly understanding setInterval but I have made a kind of slideshow script, as below:
var i = 0;
setInterval(function() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
if(i == 5){
i = 0;
}
}, 4000);
This works, except for the first run - no slides will display for the first 4 seconds.
See Fiddle here: http://jsfiddle.net/vpa89snf/6/
Is there anyway I can trigger whats inside the setInterval function when it runs the first time round?
Use setTimeOut instead of setInterval for better performance, inspect the sample below:
Here is working jsFiddle.
var i = -1;
var totalSlide = $('.slide').length-1;
var slideTimer = 0;
function nextFrame() {
i == totalSlide ? i = -1 : i;
i++;
$('.slide').fadeOut(200);
$('.slide').eq(i).fadeIn(200);
slideTimer = setTimeout(nextFrame,4000);
}
$('#holder').addClass('isAni');
nextFrame();
// play / pause animation
$('#holder').click(function() {
if ( $(this).hasClass('isAni') ) {
$(this).removeClass('isAni');
clearTimeout(slideTimer);
}else{
$(this).addClass('isAni');
nextFrame();
}
});
You need to run the function and not wait for the 4 first seconds:
var i = 0;
function doSomething() {
$('.slide').fadeOut('slow').delay(200);
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i = (i + 1) % 5;
}
$document.ready(function () {
setInterval(doSomething, 4000);
doSomething(); // run it!
});
JSFIDDLE.
This is how setInterval is executed. It runs your function after x milliseconds set as 2nd parameter.
What you have to do in order to show the first slide is to have the 1rst slide fadein like below:
var i = 0;
$('.slide:eq(' + i + ')').fadeIn('slow').delay(2000);
i++;
setInterval(function() {
...
}, 4000);

how to replace a value in a division for every 5 seconds in jquery?

I want to replace a value in a div with id show_num_val with new value for every 5 seconds. For that I have written the following.
<div id="show_num_val"> 0 </div>
In the script:
<script>
$(document).ready(function() {
for(i=0;i<20;i++){
showThis(i);
}
});
function showThis(x) {
setTimeout(function() {
$('#show_num_val').html(x);
}, 5000);
}
</script>
But I am getting the last value i.e 20 only in the show_num_val div.
can anybody help?
You can use setInterval() if you want repetitive execution.
Live Demo
$(document).ready(function() {  
x = 1;
inverval = setInterval(function() {
$('#show_num_val').html(x++);
if(x == 21)
clearInterval(inverval);
}, 2000);​
});
var x = 0;
T = setInterval(function() {
if (x == 20) clearInterval(T);
$('#show_num_val').html(x);
x++;
}, 5000);
See it working http://jsbin.com/ajekeq/2/watch
<script>
$(document).ready(function() {
for(i=1; i<20; i++){
showThis(i, 5000 * i));
}
});
function showThis(x, y) {
setTimeout(function() {
$('#show_num_val').html(x);
}, y);
}
</script>
The reason why your code was not working because all the timers were getting over at the same time. I would have liked to use setInterval though as we are starting 20 timers at the same time. Another model is to start next timer in the setTimeout call till you are done.

Categories