Fixing looping of a function in jQuery

289
November 21, 2016, at 8:37 PM

So, I tried to create an image slider using jQuery. I was able to slide the first image but it looks like my for loop is not working as expected and all the other images inside that parent div are not sliding in. Here is fiddle Fiddle and my jQuery here

$(document).ready(function() {
    setInterval(function() {
        for(var i=0;i<4;i++){
            moveRight();    
        }
    }, 1000);
});
function moveRight() {
    $(".images img").animate({
        right: '100%' //could be
    }, 1000);
}

Where am I going wrong? The for loop seems to look good, is it moveRight() function that needs work? How can I make it work? Also, tips on making the first image slide in after the last image slides out will be really appreciated.

Answer 1

I have a much simpler implementation that cycles the images through continuosly

$(document).ready(function(){
    setInterval(moveRight, 1000);
});
function moveRight(){
    $(".images img:first").animate(
        {"margin-left": -1 * $(".images img:first").width()},
        1000,
        function(){
            //move the image to the end of the children and reset it's margin-left property
            $(".images").append($(this).detach().css({'margin-left': 0}));
        }
    );
}

JSFiddle

Answer 2

Instead of using a for loop you actually need to integrate your counter variable with your setInterval function. Also you need to move the images by an increased percentage each time.

Here is a working live demo:

$(document).ready(function(){ 
    var i = 0; 
    var interval = setInterval(function(){ 
            moveRight(i); 
            i++; 
            if (i === 3) clearInterval(interval); 
    }, 3000); 
    
}); 
 
function moveRight(i){ 
	$(".images img").animate({ 
	    right: (100 * (i + 1)) + '%' //could be 
	}, 1000); 
}
body, html{ 
	margin: 0; 
	padding: 0; 
	height: 100%; 
} 
 
#slider-wrapper{ 
	width: 80%; 
	height: auto; 
	overflow: hidden; 
	border: 1px solid black; 
    white-space:nowrap; 
    position: relative; 
} 
 
#slider-wrapper .images img{ 
	position: relative; 
	width: 100%; 
	height: auto; 
	overflow: hidden; 
    display:inline-block; 
    line-height: 0; 
    margin: 0; 
    padding: 0; 
    white-space:nowrap; 
} 
#slider-wrapper .bubbles{ 
	position: absolute; 
	bottom: 0; 
	padding: 20px 0; 
	background-color: green; 
	border-top: red; 
	width: 100%; 
	height: 20px; 
	text-align: right; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<div id="slider-wrapper"> 
		<div class="images"> 
			<img src="http://morfys.com/projects/vcards/lib/files/images/image1.jpg"><img src="http://morfys.com/projects/vcards/lib/files/images/image2.jpg"><img src="http://morfys.com/projects/vcards/lib/files/images/image3.jpg"><img src="http://morfys.com/projects/vcards/lib/files/images/image4.jpg"> 
		</div> 
		<div class="bubbles"> 
			Bubbles here 
		</div> 
	</div>

JSFiddle Version: http://jsfiddle.net/Lmpjxv9d/3/

Answer 3

jsBin demo of the Infinite Slide Gallery

Basically you're doing it wrong... You're not supposed to slide every single image into place, instead slide a container that holds your images.

Infinite slider

Also you might want to create an infinite slider. To do that there's a quite nice trick

  • Set an overflow:hidden main (static) Container.
  • Add a movable element inside of it, and set it twice it's width width:200%
  • Accommodate inside that #movable your .item elements (DIVs, images whatever (floated left) set at width:50% (since the movable parent is their 100% reference)
  • On "NEXT" animation do:

function next() {
  $movable.animate({left: -galleryWidth}, 800, function(){
    $(this).append( $('.item:first') ).css({left: 0});
  });
}
  • on "PREV" animation do as:

function prev() {
  $movable.prepend( $('.item:last') ).css({left: -galleryWidth});
  $movable.animate({left:0}, 800);
}

To make your slider automatically animate you need to create an interval variable

var galleryInterval = null;

create functions that will stop and auto-run it:

function stop(){
  clearInterval( galleryInterval );
}
function auto(){
   galleryInterval = setInterval( moveNext, 4500);
}
auto(); // Start the animation!!!

(where moveNext is a function that holds the code to move NEXT (see above)).
Now logically you'd like the user to pause the gallery when he hovers it with the mouse:

$gallery.hover(stop, auto);

That's it. You have a fully functional infinite slide gallery.
You can additionally create PREV and NEXT buttons and call your already written functions like:

$("#prev, #next").click(function(){
   if(!$movable.is(":animated")) return; // ignore clicks if gallery is animating
   return this.id === "next" ? next() : prev();
});

Full gallery code & example:

var $gallery = $("#gallery"); 
var galleryWidth = $gallery.outerWidth(); 
var $movable = $("#movable"); 
var galleryInterval = null; 
 
// update the gallery width on window resize 
$(window).on("load resize", function(){ 
  galleryWidth = $gallery.outerWidth(); 
}); 
 
 
function next() { 
  $movable.animate({left: -galleryWidth}, 800, function(){ 
    $(this).append( $('.item:first') ).css({left: 0}); 
  }); 
} 
 
function prev() { 
  $movable.prepend( $('.item:last') ).css({left: -galleryWidth}); 
  $movable.animate({left:0}, 800); 
} 
 
function stop(){ 
  clearInterval( galleryInterval ); 
} 
 
function auto(){ 
  galleryInterval = setInterval( next, 4500); 
} 
 
 
$gallery.hover(stop, auto); // Pause on hover/ restart 
 
$("#prev, #next").click(function(){ 
  if($movable.is(":animated")) return; // Is animated? ignore clicks. 
  return this.id === "next" ? next() : prev(); 
}); 
 
auto(); // Start the animation!!!
body, html{ 
  margin: 0; 
  padding: 0; 
  height: 100%; 
} 
#gallery{ 
  position:relative; 
  margin:0 auto; /* Horiz. center */ 
  width:80%; /* no need to use height! */ 
} 
#slider-wrapper{ 
  /* the overflow element */ 
  width: 100%;  /* same as #gallery */ 
  height: 80vh; /* set as desired!(try with "80vh" also!) */ 
  position: relative; 
  overflow: hidden; /* comment this line and see how the .item are 2by2 */ 
} 
 
#movable{ 
  /* we'll animate this one with jQuery */ 
  position:relative; 
  left:0; 
  width:200%;  /* see? */ 
  height:100%; /* needed fix flor the .item to be 100% too */ 
} 
 
.item{ 
  /* we'll append prepend items to create an infinite slider */ 
  float:left; 
  height: 100%; /* same as movable height */ 
  width: 50%;   /* 50% of the 100% parent */ 
  /* now the responsive bg-images trick */ 
  background: 50% / cover; 
} 
 
#bubbles{ 
  text-align:center; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="gallery"> 
  <!-- #gallery to contain the slider and the buttons so that we can apply the hover to pause if both buttons or slider are hovered --> 
 
  <div id="slider-wrapper"> 
 
    <div id="movable"> 
      <div class="item" style="background-image: url(http://morfys.com/projects/vcards/lib/files/images/image1.jpg)"></div> 
      <div class="item" style="background-image: url(http://morfys.com/projects/vcards/lib/files/images/image2.jpg)"></div> 
      <div class="item" style="background-image: url(http://morfys.com/projects/vcards/lib/files/images/image3.jpg)"></div> 
      <div class="item" style="background-image: url(http://morfys.com/projects/vcards/lib/files/images/image4.jpg)"></div> 
    </div> 
 
  </div> 
 
  <div id="bubbles"> 
    <button id="prev">PREV</button> 
    <button id="next">NEXT</button> 
  </div> 
 
</div>

Answer 4

Originally, you just had each image move to the right once with the right: 100%;, but if the third and fourth images were originally two and three whole frames to the right of the first image, you will need to move them two and three whole frames to the left to be able to view them. This is done by just increasing the percentage by one whole frame (100%) on each iteration.

The 1100 interval is also just to make the transition more noticeable since slides would just immediately move when set at the same time as the animation time.

$(document).ready(function(){
    var i = 0;
    setInterval(function(){
        moveRight(++i); 
    }, 1100);
});
function moveRight(i){
    $(".images img").animate({
        right: i*100 + '%' //could be
    }, 1000);
}
READ ALSO
jQuery dropdown not working when appended

jQuery dropdown not working when appended

Im appending a form & it contains select - Im using jQuery select plugin Chosen. .

274
JQuery code is not executed when bootstrap-table columns selected to be shown changes

JQuery code is not executed when bootstrap-table columns selected to be shown changes

I have a bootstrap-table which have a not visible column at start: data-visible="false". The columns caption contains a button to display a modal help dialog:.

275
Have all label in Chartjs be at fixed positions

Have all label in Chartjs be at fixed positions

Been searching for for this question for a little while to no avail. I want a way to modify the positions of specific labels.

453