Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Help with auto-rotating infinite jquery carousel. Can not get carousel to loop infinitely instead of 'rewind'

I'm building an auto-rotating image-carousel with jquery and I'm trying to get the images to rotate infinitely rather than when it reaches the last image, it 'rewinds' back to the first image and starts again. Unfortunately, I'm rather new at the jquery game, so I'm having some trouble getting this to work. I've tried piecing together code I've found in tutorials online and modifying it to fit my code, but no luck. I think I might have to clone the existing images to appear after they cycle through, but I'm not sure what direction to go in. Any assistance is greatly appreciated. Here's the code I'm working with below:

HTML:

<div class="main_view">
    <div style="width:165px; height:98px; margin:0; padding:0; border:0;">
        <img src="/content/template_images/wanalogo-blackBG-165x98.png" />
    </div>
    <div class="window">
        <ul class="image_reel">
        <li><a href="/MLB/Philadelphia-Phillies-Tickets" title="Phillies"><img src="/content/template_images/Banners/SideBanner/imgscroll1.jpg" alt="Phillies" /></a></li>
        <li><a href="/NFL/Philadelphia-Eagles-Tickets" title="Eagles"><img src="/content/template_images/Banners/SideBanner/imgscroll2.jpg" alt="Eagles" /></a></li>
        <li><a href="/NHL/Philadelphia-Flyers-Tickets" title="Flyers"><img src="/content/template_images/Banners/SideBanner/imgscroll3.jpg" alt="Flyers" /></a></li>
        <li><a href="/NBA/Philadelphia-76ers-Tickets" title="76ers"><img src="/content/template_images/Banners/SideBanner/imgscroll4.jpg" alt="76ers" /></a></li>
        <li><a href="/NCAA-Basketball" title="NCAA Basketball"><img src="/content/template_images/Banners/SideBanner/imgscroll8.jpg" alt="NCAA Basketball" /></a></li>
        <li><a href="/Concerts-Tickets" title="Concerts"><img src="/content/template_images/Banners/SideBanner/imgscroll5.jpg" alt="Concerts" /></a></li>
        <li><a href="/Theatre-Tickets" title="Theatre"><img src="/content/template_images/Banners/SideBanner/imgscroll6.jpg" alt="Theatre" /></a></li>
        <li><a href="/Other-Events-Tickets" title="Family Events"><img src="/content/template_images/Banners/SideBanner/imgscroll7.jpg" alt="Family Events" /></a></li>
        </ul>
    </div>
    <div style="width:170px; height:290px; border:0; padding:0; margin: -290px 0px 0px 0px;">
        <img src="/content/template_images/black-fade-border-170x290.png" />
    </div>
    <div class="botTextBox">
        <center>
        <div class="botText">
        <a href="/MLB/Philadelphia-Phillies-Tickets" title="Phillies">Phillies</p></a>
        <a href="/NFL/Philadelphia-Eagles-Tickets" title="Eagles"><p>Eagles</p></a>
        <a href="/NHL/Philadelphia-Flyers-Tickets" title="Flyers"><p>Flyers</p></a>
        <a href="/NBA/Philadelphia-76ers-Tickets" title="76ers"><p>76ers</p></a>
        <a href="/NCAA-Basketball" title="NCAA Basketball"><p>NCAA Basketball</p></a>
        <a href="/Concerts-Tickets" title="Concerts"><p>Concert</p></a>
        <a href="/Theatre-Tickets" title="Theatre"><p>Theatre</p></a>
        <a href="/Other-Events-Tickets" title="Family Events"><p>Family Event</p></a>
        </div>
        </center>
    </div>
        <div class="paging">
        <a href="#" rel="1">1</a>
        <a href="#" rel="2">2</a>
        <a href="#" rel="3">3</a>
        <a href="#" rel="4">4</a>
        <a href="#" rel="5">5</a>
        <a href="#" rel="6">6</a>
        <a href="#" rel="7">7</a>
        <a href="#" rel="8">8</a>
        </div>
</div>

Javascript

$(document).ready(function() {
    $(".paging").show();
    $(".paging a:first").addClass("active");

    var imageWidth = $(".window").width();
    var imageSum = $(".image_reel img").size();
    var imageReelWidth = imageWidth * imageSum;

    $(".image_reel").css({'width' : imageReelWidth});

    rotate = function(){
    var triggerID = $active.attr("rel") - 1; //Get number of times to slide
    var image_reelPosition = triggerID * imageWidth; //Determines the distance the image reel needs to slide

    $(".paging a").removeClass('active'); //Remove all active class
    $active.addClass('active'); //Add active class (the $active is declared in the rotateSwitch function)

    //Slider Animation
    $(".image_reel").animate({
        left: -image_reelPosition
    }, 750 );
    $(".botText").animate({
    left: -image_reelPosition
    }, 750 );
    }; 

    //Rotation  and Timing Event
    rotateSwitch = function(){
    play = setInterval(function(){ //Set timer - this will repeat itself every X seconds
    $active = $('.paging a.active').next(); //Move to the next paging
    if ( $active.length === 0) { //If paging reaches the end...
    $active = $('.paging a:first'); //go back to first
    }
    rotate(); //Trigger the paging and slider function
    }, 1500); //Timer speed in milliseconds (7 seconds)
    };

    rotateSwitch(); //Run function on launch

    //On Hover
    $(".image_reel a").hover(function() {
        clearInterval(play); //Stop the rotation
    }, function() {
        rotateSwitch(); //Resume rotation timer
    }); 

    //On Click
    $(".paging a").click(function() {
        $active = $(this); //Activate the clicked paging
        //Reset Timer
        clearInterval(play); //Stop the rotation
        rotate(); //Trigger rotation immediately
        rotateSwitch(); // Resume rotation timer
        return false; //Prevent browser jump to link anchor
    });
});

Edit- CSS:

.main_view {
    float: left;
    overflow:hidden;
    position: relative;
    width:170px; 
    height:475px; 
    background-color:black; 
    border:0; 
    margin:2px; 
    padding:2px 0px 2px 0px; 
    text-align:center;
}
.window {
    height:290px;   width:170px;
    overflow: hidden;
    position: relative;
    background-color:black; 
    border:0; 
    padding:0px; 
    margin:0px;
}
.image_reel {
    position: absolute;
    top: 0; left: 0;
    margin-left:-40px;
}
.image_reel img {float: left;}

.botTextBox {
    height:87px; width:1360px;
    overflow:hidden;
    position:relative;
    background:url(/content/template_images/black-side-bottom-170x87.png) no-repeat; 
    margin:0px; 
    padding:0px;
}
.botText {
    position:relative;
    top:0; left:0;
    margin:32px 0px 0px 0px; 
    padding:0; 
    text-align:center;
}
.botText p {width:170px; float: left;}

.paging {
    position: absolute;
    bottom: 40px; right: -7000px;
    width: 178px; height:47px;
    z-index: 100; 
    text-align: center;
    line-height: 40px;
    display: none; 
}
.paging a {
    padding: 5px;
    text-decoration: none;
    color: #fff;
}
.paging a.active {
    font-weight: bold;
    background: #920000;
    border: 1px solid #610000;
    -moz-border-radius: 3px;
    -khtml-border-radius: 3px;
    -webkit-border-radius: 3px;
}
.paging a:hover {font-weight: bold;}

...actually you can see the flash banner on the right that i'm trying to replace with a jquery one...

Once again, I really appreciate any help with this. Like I said, I'm kinda new at working with jQuery and I've been stumbling over this all day. Thanks a million.

like image 508
garr1s0n Avatar asked Sep 17 '10 20:09

garr1s0n


2 Answers

The problem with your carousel is that the block of images remains one giant block, so when you get to the end, you must slide all the way back to the first image to loop, and this is what causes that "rewind" look.

What I would do instead is:

  1. Load each image into an array
  2. Remove all but the first image from the gallery.
  3. Add the next image (in an array next with looping is number % length)
  4. Animate slider to show next image
  5. Reset CSS and remove the now invisible first image
  6. Rinse and repeat.

Below is an example implementation with a recursive function.

I create a slider function that makes use of jQuery's .animate(). In the call back of .animate() I call the slider function again after a brief pause casued by setTimeout().

The example below is quite simple, you can adjust it easily to for example show the slivers of the previous and next image and other things.... This is just to illustrate a simple implementation of an infinite slide with a limited number of images.

I added in a simple implementation of how to show a changing caption under the gallery. The information for the caption is taken from the images HTML codes. This caption could also be placed under each image and slid along with the image.

jsFiddle example

$(function() {          
    var showing = 0;    // which image is showing
    var imgs = [];      // array to hold images HTML
      // Put image elements into an array
    imgs = $("#gallery img").toArray();
    var numberOf = imgs.length;    
      // Remove all but first image from DOM
    $("#slider").html("");
    $("#slider").html(imgs[0]);    
      // Add title text div
    $("#gallery").after('<a id="title"/>');
      // The recursive slider function
    var nextImage = function() {
          // Add next image (only use increment once!)
        $("#slider").append(imgs[++showing % numberOf]);
          // Show image title
        $("#title").html($(imgs[showing % numberOf]).attr("title"));
          // Link to original
        $("#title").attr("href", $(imgs[showing % numberOf]).attr("src"));
          // Animate the slider
        $("#slider").animate({
            left: '-=200'
        }, 2000, function() {            
              // Remove image to the left
            $("#slider img:first").remove();            
              // Reset CSS
            $("#slider").css("left", "0px");            
              // Call animationg function again
            setTimeout(function() {nextImage(); }, 1000);
        });  
    }        
    nextImage();  // Call next image for the first time         
});

The static HTML would consist of:

<div id="gallery">
    <div id="slider">
        ... the images here ...
    </div>
</div>

PS: to see the conveyor belt effect at work look at this.


jQuery and JS methods and properties used:

  • .animate()
  • .append()
  • .css()
  • :first selector
  • .html()
  • .length
  • .remove()
  • setTimeout()
  • .toArray()
like image 82
Peter Ajtai Avatar answered Sep 27 '22 18:09

Peter Ajtai


Peter Ajtai has a nice summary of one method, but I have another one which only requires adding a few lines to your script.

Basically it clones the first image, text and pager link and adds it to the end. When the animation ends on the last image (which is now actually the first), the left positioning of the window is reset to zero and the animation resumes. I tried to add comments with [NEW] so you can more easily find the changes. And, I made a demo so hopefully it will be clear.

$(document).ready(function() {
 $(".paging").show();
 $(".paging a:first").addClass("active");

 var imageWidth = $(".window").width();
 // [NEW] add one, since we are adding the first image to the end
 var imageSum = $(".image_reel img").size() + 1; 
 var imageReelWidth = imageWidth * imageSum;

 // [NEW] included modifying width of botTextBox 
 $(".image_reel, .botTextBox").css({'width' : imageReelWidth });

 // [NEW] clone first image & text and add it to the end, include dummy paging
 $(".image_reel li:first").clone().appendTo( $(".image_reel") );
 $(".botText a:first").clone().appendTo( $(".botText") );
 $(".paging").append('<a href="#" rel="' + imageSum + '"></a>'); // don't include the number in the link

 rotate = function(){
  var triggerID = $active.attr("rel") - 1; //Get number of times to slide
  var image_reelPosition = triggerID * imageWidth; //Determines the distance the image reel needs to slide

  $(".paging a").removeClass('active'); //Remove all active class
  $active.addClass('active'); //Add active class (the $active is declared in the rotateSwitch function)

  // [NEW] Slider Animation
  $(".image_reel, .botText").animate({
   left: -image_reelPosition
  }, 750, function(){
   // [NEW] callback function (called when animation is done)
   if (triggerID == imageSum - 1) {
    // if we're back to the first image, reset the window position
    $(".image_reel, .botText").css('left',0);
   }
  });
 };

 //Rotation  and Timing Event
 rotateSwitch = function(){
  play = setInterval(function(){ //Set timer - this will repeat itself every X seconds
   $active = $('.paging a.active').next(); //Move to the next paging
   if ( $active.length === 0) { // If paging reaches the end...
    // [NEW] go back to second image (the first is now the last)        
    $active = $('.paging a:eq(1)');
   }
   rotate(); //Trigger the paging and slider function
  }, 1500); //Timer speed in milliseconds (7 seconds)
 };

 rotateSwitch(); //Run function on launch

 //On Hover
 $(".image_reel a").hover(function(){
  clearInterval(play); //Stop the rotation
 }, function(){
  rotateSwitch(); //Resume rotation timer
 }); 

 //On Click
 $(".paging a").click(function() {
  $active = $(this); //Activate the clicked paging
  //Reset Timer
  clearInterval(play); //Stop the rotation
  rotate(); //Trigger rotation immediately
  rotateSwitch(); // Resume rotation timer
  return false; //Prevent browser jump to link anchor
 });

});

Oh and one last thing... I added the missing <p> in front of the Phillies botText

like image 34
Mottie Avatar answered Sep 27 '22 20:09

Mottie