decodeURI

Update: Creating a news carousel with jQuery, now with time based switching

Posted in Uncategorized by lucianopanaro on January 11, 2009

This is just a simple and quick update on the Creating a news carousel with jQuery post.

After reading this comment, and going through the code, I decided to implement the time-based switching functionality and also clean up the code a little bit (check it out here).

The additions made (along with some code cleaning) were:

  • Append a simple div that will shrink while the picture is shown and reinitialized when the picture is switched.
  • Add a setInterval call that will do the picture switching (and the new div’s animation).

Update 01/12: I added some fixes to the code

  • Use the image’s load event to calculate each individual width. When all images are loaded, then the carousel is initiated.
  • The animate_timer function now stops all animations on the timer div before reinitializing the animation

Update 01/27: Even more fixes :)

  • Work with cases were images are already in cache and load event is fired before we attach to it.
  • Fixed the way the news animation was calculated.
  • Added 2 more news to help test it better.

So here’s the new javascript that will do this:

$(function() {
    var carousel   = $('#news_carousel');
    var news       = carousel.find('ul.news');
    var controls   = null; // Will hold the ul with the controls
    var timer      = null; // Will hold the timer div
    var wait       = 5000; // Milliseconds to wait for auto-switching
    var widths     = [];   // Will hold the widths of each image
    var items_size = news.find('li').length;
    var initialized = false;

    if (!items_size) { return; }

    // Controls html to append
    var controls_str = '<ul class="controls">';
    for ( var i = 1; i &lt;= items_size; i++) {
       controls_str += '<li><a href="#">' + i + '</a></li>';
    }
    controls_str += '</ul>';

    // Cache the controls list
    controls = carousel.append(controls_str).find('ul.controls');

    // Make the first button in controls active
    controls.find('li:first a').addClass('active');

    // Hook to the controls' click events
    controls.find('li a').click(function(event) {
      move_news( $(this) );
      return false;
    });

    // Append the timer and cache it
    timer = carousel.append('<div class="timer"></div>').find('div.timer');

    // Store each item's width and calculate the total width
    news.find('li img')
        .each(function(i, e) {
            widths[i] = $(e).width();
            if ( all_images_loaded() ) { init_carousel(); }
        })
        .load(function(e) {
            var i = news.find('li img').index(this);
            widths[i] = $(this).width();
            if ( all_images_loaded() ) { init_carousel(); }
        });

    function all_images_loaded() {
      return (items_size == widths.length) &amp;&amp; (jQuery.inArray(0, widths)  1 ) {
        return false;
      }

      var current_active = controls.find('li a.active');

      if (new_active == 'next') {
        var next = current_active.parent().next().find('a');

        if ( !next.length ) { next = controls.find('li:first a'); }

        new_active = next;
      }

      var current_index = parseInt(current_active.text(), 10) - 1;
      var new_index     = parseInt(new_active.text(), 10) - 1;
      var move_to       = new_index - current_index;

      if (!move_to) { return false; }

      var direction = (move_to &gt; 0)? '-=': '+=';

      var move   = 0;
      var bottom = Math.min(current_index, new_index);
      var top    = Math.max(current_index, new_index);

      while (bottom &lt; top) {
        move += widths[bottom];
        bottom++;
      }

      news.animate({marginLeft: direction + move }, 500);
      new_active.addClass('active');
      current_active.removeClass('active');
    }

    function animate_timer() {
      timer.stop().css({width: '100px'}).animate({width: '1px'}, wait);
    }

    // Initializer, called when all images are loaded
    function init_carousel() {
      if (initialized) { return false; }

      // Set the news ul total width
      var width = 0;
      for( var i = 0; i &lt; widths.length; i++) { width += widths[i]; }
      news.width(width);

      // Make the news change every X seconds
      setInterval(function() { move_news('next'); animate_timer(); }, wait);
      animate_timer();

      initialized = true;
    }
});

Tagged with: , ,

11 Responses

Subscribe to comments with RSS.

  1. Miguel said, on January 22, 2009 at 5:47 pm

    Hello is a great script!! but if you press the last number and after press the first number (total numbers: 5) this show the 4th element… (the element previous to the last element).

    • luciano.panaro said, on January 27, 2009 at 2:36 pm

      @Miguel: thanks for your comments. As you noted, there were a few more bugs left in the code since I last updated. Everything should be working now. I will be probably explaining in more detail the code in a future post and do some more cleaning.

  2. israel vasquez said, on January 27, 2009 at 11:11 pm

    hi, what is the format for the widths array for the images, i can’t seem to customize the images width to show them.

    • luciano.panaro said, on January 28, 2009 at 6:21 am

      The box’s size is set in the css:

      #news_carousel { width: 444px; height: 333px; }

      The images however can have any width (though only the box’s size will be shown). To achieve this the script stores every image’s width in widths

      var widths = []; // Will hold the widths of each image

      Let me know if this clears your doubt.

  3. Fabio said, on January 29, 2009 at 8:42 pm

    Precisaly what i was looking for, a well functional and light jquery gallery to implement in my website.

    The only problme is that i want something more like http://www.msn.com.br main headlines style, instead of a button over the picture i would like it in the left side, working like a navigator with thumbnails.

    I will try to work out on it however, see if i can do it with this script.

  4. Peter said, on June 1, 2009 at 3:40 am

    Hi guys.

    I am currently implementing this carousel and it works fine under IE7/8.
    We have problems however under FF. For some bizarre reason it will not load up random number of pictures from the script. No regularity in this action.

    Does it happen to you as well ?

    Cheers,
    Peter

    • luciano.panaro said, on June 1, 2009 at 7:17 am

      Hi @Peter. I haven’t experienced that, do you have a public server where I can see it?

  5. dan said, on July 4, 2009 at 2:45 pm

    Hi,

    Great script, I was wondering is there anyway to reset the timer when someone clicks on a link in the corner? I’m having a problem when I select another news item it only seems to show for the remainder of the timer before it jumps to the next news.

    I guess it just needs a line adding in to stop this but my javascript/jquery isn’t up to much!

  6. luciano.panaro said, on July 4, 2009 at 8:32 pm

    @dan: You can use the clearInteval function (https://developer.mozilla.org/en/window.clearInterval). To use this, you will have to get the intervalId that is returned by the setInterval function, so that you can then use it to clear the interval.

    Here’s an example of how to use the clearInterval function: https://developer.mozilla.org/en/DOM/window.setInterval#Example

    Let me know if that helps :)

  7. Josh said, on February 18, 2010 at 7:34 pm

    I’m implementing this on a site my company is creating. Generally speaking, it works great – however, it doesn’t scale to different zoom-levels in Chrome. Anyone have any idea why this would be, or a fix to stop it?

  8. Jesus said, on March 4, 2010 at 5:10 pm

    Hi,

    Great script, however I’m getting a behaviour similar to the one mentioned above for FF, but in my case with IE7, for some reason very often it won’t load the second and third images of a total of three, It always loads the first one without problem. I’ve I forze the reload of the page, usually all images come through. In Chrome works fine all the time with all images. Any idea why this may be happening?

    Thanks

    Jesús


Leave a Reply