0

I have a setTimeout inside the a for loop, but it not behaving as i anticipated.

I have a bunch of banners in a page that are loading all at once. I am removing their parent's div html and storing it in an array. Then I would like for each parent to receive its corresponding html every 5 seconds. This only needs to happen once on ready state.

Here's my code...

function oneBanner() {

   var divs = $('.banner-slide'),
       imgs = [];

   for ( var j = 0; j < divs.length; j++ ) {
      imgs.push( $('.banner-slide:nth-child(' + (j+1) + ')') );
   }

   for ( var k = 0; k < imgs.length; k++ ) {
      var url = $(imgs[k]).html();
      $(imgs[k]).html('');

      setTimeout(function(y) {
         console.log(k * 5000);
         $(imgs[k]).html(url);
      }, k * 5000, k);
      
   }
}
oneBanner();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="banner-slide">
  <img src="http://www.placecage.com/150/150" >
</div>

<div class="banner-slide">
  <a href="#"> <img src="http://fillmurray.com/150/150" > </a>
</div>

<div class="banner-slide">
  <img src="http://stevensegallery.com/150/150" >
</div>

As you can see the images do not get printed on the screen one at a time every 5 seconds - which I thought I was doing.

Thank you for any help.

Serge

3 Answers 3

1

It will be better to simplify your code while you don't need any of variables/arrays outside this function .. you can just use jquery .each()

try This

function oneBanner() {
   var divs = $('.banner-slide');
   divs.each(function(i){  // loop through .banner-slide divs
      var ThisIt = $(this);  // define this outside setTimout function
      setTimeout(function(){
         divs.hide();    // hide all .banner-slide divs
         ThisIt.show();  // show just this one
      } , 5000 * i);     // time * the i -- i is the index of the div
   }); 
}

see the code in action

function oneBanner() {
   var divs = $('.banner-slide');
   divs.each(function(i){
      var ThisIt = $(this);
      setTimeout(function(){
         divs.hide();
         ThisIt.show();
      } , 5000 * i);
   }); 
}

oneBanner();
.banner-slide:not(:first){
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="banner-slide">
  <img src="http://www.placecage.com/150/150" >
</div>

<div class="banner-slide">
  <a href="#"> <img src="http://fillmurray.com/150/150" > </a>
</div>

<div class="banner-slide">
  <img src="http://stevensegallery.com/150/150" >
</div>

Note: by using setTimeout() you'll show each image for 5 seconds and the code will stop looping

Update up to the OP comment

function oneBanner() {
   var divs = $('.banner-slide'),
       htmlArray = [];
   divs.each(function(i){
      var ThisIt = $(this);            // get this outside the setTimout
      htmlArray.push(ThisIt.html());   // push the inner html to the array
      ThisIt.html('');                 // emty this div
      setTimeout(function(){
         $(ThisIt).html(htmlArray[i]); // add html again with setTimeout every 5 second to its parent div
      } , 5000 * i);
   });
}

oneBanner();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="banner-slide">
  <img src="http://www.placecage.com/150/150" >
</div>

<div class="banner-slide">
  <a href="#"> <img src="http://fillmurray.com/150/150" > </a>
</div>

<div class="banner-slide">
  <img src="http://stevensegallery.com/150/150" >
</div>

Sign up to request clarification or add additional context in comments.

3 Comments

I don't need to "show" each every 5 seconds. Once the page loads I need to remove each parent's html and store it in an array. THEN every 5 seconds re-insert them back into their original place. And it has to be the entire inner html - either just the img tag or the img and anchor. I hope this makes sense lol.
@Sergio I updated my answer with comment on code .. please read it .. Have a great day :-)
Great. Thanks Again. You as well, have a great day!
1

one word: closure

function oneBanner() {

   var divs = $('.banner-slide'),
       imgs = [];

   for ( var j = 0; j < divs.length; j++ ) {
      imgs.push( $('.banner-slide:nth-child(' + (j+1) + ')') );
   }
   
   imgs.forEach(($img,k)=>{
	var url = $img.html();
	  $img.html('');

	  setTimeout(function(y) {
		 $img.html(url);
	  }, k * 5000, k);
	})
	
}
oneBanner();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="banner-slide">
  <img src="http://www.placecage.com/150/150" >
</div>

<div class="banner-slide">
  <a href="#"> <img src="http://fillmurray.com/150/150" > </a>
</div>

<div class="banner-slide">
  <img src="http://stevensegallery.com/150/150" >
</div>

1 Comment

can you explain. Your code sort of works in my real application, but do you mean by "closure".
0

You are referencing the wrong variable inside of your setTimeout. Replace 'y' with 'k'

  function oneBanner() {

     var divs = $('.banner-slide'),
         imgs = [];

     for ( var j = 0; j < divs.length; j++ ) {
        imgs.push( $('.banner-slide:nth-child(' + (j+1) + ')') );
     }

     for ( var k = 0; k < imgs.length; k++ ) {
        var url = $(imgs[k]).html();
        $(imgs[k]).html('');
        setTimeout(function(k) {
           console.log(k * 5000);
           $(imgs[k]).html(url);
        }, k * 5000, k);

     }
  }
  oneBanner();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
    <div class="banner-slide">
      <img src="http://www.placecage.com/150/150" >
    </div>

    <div class="banner-slide">
      <a href="#"> <img src="http://fillmurray.com/150/150" > </a>
    </div>

    <div class="banner-slide">
      <img src="http://stevensegallery.com/150/150" >
    </div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.