Update: Creating a news carousel with jQuery, now with time based switching
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 <= 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) && (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 > 0)? '-=': '+=';
var move = 0;
var bottom = Math.min(current_index, new_index);
var top = Math.max(current_index, new_index);
while (bottom < 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 < 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;
}
});
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).
@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.
hi, what is the format for the widths array for the images, i can’t seem to customize the images width to show them.
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 imageLet me know if this clears your doubt.
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.
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
Hi @Peter. I haven’t experienced that, do you have a public server where I can see it?
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!
@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
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?
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