views:

316

answers:

1

I've written an image slideshow in jQuery that speeds up/down based on where the mouse is hovering over the images.

I'd like to have the images 'repeat' as the slideshow ends. So the user scrolls through the slideshow, it reaches the end of the image LI's and then seamlessly repeats from the start.

Here's the current code:

jQuery

$(document).ready(function()
{
   $('#products ul').css('width', ($('#products ul li').length * 185));

   var $products = $('#products div');
   var posLeft   = 0;

   // Add 5 DIV overlays to use as 'hover buttons' for the slideshow speed
   for (i = 0; i <= 4; i++)
   {
      $('#products').append('<div class="hover-' + i + '" style="background: transparent; width: 100px; height: 167px; position: absolute; left: ' + posLeft + 'px; top: 15px;"></div>');
      posLeft += 100;
   }  

   // Function animate the scrolling DIV in the appropriate direction with the set speed
   function plz2scroll(direction, scrollSpeed)
   {
      var scrollDir    = (direction == 'left')  ? '-='  : '+=';
      var scrollOffset = (direction == 'right') ? '-10' : '+' + $products.css('width').substring(0, -2) + 10; // Fix the '+100px10' issue - Seems substring don't support negative offsets 

      $products.animate({scrollLeft: scrollDir + $products.css('width')}, scrollSpeed, 'linear', function()
      {
         $products.scrollLeft(scrollOffset);
         plz2scroll(direction, scrollSpeed);
      });
   }

   // Create the 'hover buttons'
   $('div.hover-0').hover(function() { $products.stop(); plz2scroll('right', 2000); });
   $('div.hover-1').hover(function() { $products.stop(); plz2scroll('right', 3500); });
   $('div.hover-2').hover(function() { $products.stop(); });
   $('div.hover-3').hover(function() { $products.stop(); plz2scroll('left',  3500); });
   $('div.hover-4').hover(function() { $products.stop(); plz2scroll('left',  2000); });
});

HTML

<div id="products">
   <div>
      <ul>
         <li><img src="images/1.jpg" /></li>
         <li><img src="images/2.jpg" /></li>
         <li><img src="images/3.jpg" /></li>
         <li><img src="images/4.jpg" /></li>
         <li><img src="images/5.jpg" /></li>
      </ul>
   </div>
</div>

The scroller works and the speed/direction works nicely with the overlayed DIV buttons. My animate() callback to repeat is slow, buggy and just bad :/

My overuse of .stop() also looks like a potential problem >.<

Any ideas?

A: 

Hi Frank, just thought of something: You could try to position the inner div (the one obtained by $('#products div') with position: relative; and the lis with position: absolute. Moreover, the inner div must have overflow: hidden (probably already the case). The positions of the list items are now relative to the surrounding div, which makes calculations easier.

Then, instead of moving the div as a whole, move the images individually. You can check if an item is visible by something like this, for instance:

function isItemVisible(li) {
    var w = li.outerWidth()
    var pos = li.position();
    return pos.left + w > 0 && pos.left < $products.innerWidth();
}

You still have to figure out when to rearrange individual items, but maybe this helps you get started. Maybe you will have to maintain a separate data structure where you can reorder the items when necessary, or at least maintain a leftmost and rightmost pointer to the (currently) leftmost and rightmost item.

Tom Bartel
That seems fairly doable... I'll have a go and see what happens. Thanks for the idea.
frank