Create a Simple Slideshow Using MooTools, Part IV: Thumbnails and Captions
My "Create a Simple Slideshow Using MooTools" series has been hugely successful. The first step was laying the groundwork for the slideshow, the second step was adding controls and events to the slideshow, and the third step was recoding the slideshow into a sexy class. This fourth slideshow tutorial will add thumbnail previews and captions to the slideshow.
No Class? WTF!?
I've chosen to revert back to the "inline" code from the second tutorial. Why? I'm going a little bit off of the reservation with this one. I think classes are important to use when you want a more generic slideshow; this one will be a bit more customized. That isn't to say, however, that I wont be creating another class in the future.
The HTML
Isn't it nice that our base HTML code hasn't changed since the first tutorial? :)
The CSS
#slideshow-container { width:512px; height:384px; position:relative; }
#slideshow-container img { width:512px; height:384px; display:block; position:absolute; top:0; left:0; z-index:1; }
#slideshow-container-controls { margin:10px 0 0 0; }
#slideshow-container-controls img { cursor:pointer; width:100px; height:75px; border:1px solid #ccc; float:left; margin:0 1px 0 0; }
#slideshow-container-caption { height:70px; position:absolute; bottom:0; left:0; right:0; background:#000; z-index:10; overflow:hidden; }
* html #slideshow-container-caption { width:100%; }
#slideshow-container-caption h3 { font-size:24px; font-weight:bold; color:#fff; padding:10px 10px 3px 10px; }
#slideshow-container-caption p { color:#eee; font-size:11px; padding:0 10px 10px 10px; }
.toc-active { border-color:#000; }
We've added a bit of CSS for the forthcoming controls/thumbnails and the caption elements. The caption will have a black background with light text. The thumbnails will be very small, floated next to each other, with fixed dimensions.
The MooTools JavaScript
window.addEvent('domready',function() {
/* settings */
var showDuration = 5000;
var container = $('slideshow-container');
var images = container.getElements('img');
var currentIndex = 0;
var interval;
var toc = [];
var tocActive = 'toc-active';
var thumbOpacity = 0.7;
/* new: create caption area */
var captionDIV = new Element('div',{
id: 'slideshow-container-caption',
styles: {
//display:none,
opacity: thumbOpacity
}
}).inject(container);
var captionHeight = captionDIV.getSize().y;
captionDIV.setStyle('height',0);
/* new: starts the show */
var start = function() { interval = show.periodical(showDuration); };
var stop = function() { $clear(interval); };
/* worker */
var show = function(to) {
images[currentIndex].fade('out');
toc[currentIndex].removeClass(tocActive).fade(thumbOpacity);
images[currentIndex = ($defined(to) ? to : (currentIndex < images.length - 1 ? currentIndex+1 : 0))].fade('in');
toc[currentIndex].addClass(tocActive).fade(1);
captionDIV.set('tween',{
onComplete: function() {
captionDIV.set('tween',{
onComplete: $empty
}).tween('height',captionHeight);
/* parse caption */
var title = '';
var captionText = '';
if(images[currentIndex].get('alt')) {
cap = images[currentIndex].get('alt').split('::');
title = cap[0];
captionText = cap[1];
captionDIV.set('html','' + title + '
' + (captionText ? '' + captionText + '
' : ''));
}
}
}).tween('height',0);
};
/* new: create preview area */
var preview = new Element('div',{
id: 'slideshow-container-controls'
}).inject(container,'after');
/* new: control: table of contents */
images.each(function(img,i){
/* add to table of contents */
toc.push(new Element('img',{
src: img.get('src'),
title: img.get('alt'),
styles: {
opacity: thumbOpacity
},
events: {
click: function(e) {
if(e) e.stop();
stop();
show(i);
start();
},
mouseenter: function() {
this.fade(1);
},
mouseleave: function() {
if(!this.hasClass(tocActive)) this.fade(thumbOpacity);
}
}
}).inject(preview));
if(i > 0) { img.set('opacity',0); }
});
/* control: start/stop on mouseover/mouseout */
container.addEvents({
mouseenter: function() { stop(); },
mouseleave: function() { start(); }
});
/* start once the page is finished loading */
window.addEvent('load',function(){ show(0); start(); });
});
The first step is creating the caption container within the main image container. We measure the height of the caption container and hide it right away to prevent it from being seen. The next step is adding a few chained tweens within the show method that parses the image's alt attribute, sets the HTML within the caption container, and slides it up and down. I set the HTML of the caption container instead of using MooTools to create new H3 and P elements because (a) setting the HTML is faster and (b) we have no plan to do anything with each element individually.
A preview container is also created to hold the thumbnails. As we cycle through the large images, we create IMG elements with a fixed size (from the CSS above) that will act as thumbnail navigation for the slideshow. As an image receives focus, it's border and opacity changes to show focus. Awesome!
Do you like this version better than the previous? I certainly do. Look forward to a class version soon. Have any improvement ideas? Share them!
Discussion
Be Heard!
Share your thoughts with fellow developers of all skill levels! I want to hear from you!

I believe that the most correct way to mark up images and captions is to use definition lists. The img element’s alt attribute allows us to provide fallback content; captions, however, are not fallback content.
I’ve created a JavaScript slider for images captioned in this way. [http://davidchambersdesign.com/examples/prototype-image-slider/]
It’s a bit buggy…sometimes an image shows for longer than normal, and then the next caption and image appears and disappears immediately only to be replaced by the following caption and image…weird… on firefox 3.6
Wow, very nice :DDD
And how do i do this with div’s?
That is very good stuff, thanks for sharing
@Adriaan Nel: Mac or PC? I’m on Mac and it’s silky smooooth.
haunting picture to say the least! thanks for taking the time putting together the tut.
AMD Turion 2.3, Chrome 4, Windows 7 Home Premium: the animation is quite jumpy…
Just tested on all Mac browsers (Firefox, Chrome, Safari, Opera) and looks good. Slight jump in Opera but still looks good. Will investigate Windows-based browsers more.
Checked on Virtual Box / IE6, IE7, IE8 and it looked all good. I’ll check on native Windows tomorrow.
make it more user friendly – animation should stop when mouse pointer is on main image or thumbnails
anyway, nice tut!
@David Walsh: on Windows 7, but did you adjust the display time of each slide or something, as it seems much slower now…I am also no longer able to reproduce the buggy behaviour.
@Adriaan Nel: Nope, didn’t touch anything.
@David Walsh: mmm, maybe there was something buggy on my machine then, I’ve been working (browsing,experimenting with js, php, photoshop, etc) the whole day on it…this morning just after booting, everything seems fine
Hi David, will you be making a jQuery demo of this as well. It’s good to have only one JS-framework to add to our websites ;-) Otherwise the http-requests get too big!
Nice adittion to this series. I also noticed the bug Adriaan reported (on win XP FF 3.6) but today it seems ok. I can’t say exaclty what conditions generate the bug but I’m guessing it might have something to do with more then one timer running simultaneously, maybe related to page-reload but not sure. Anyway, tks again and I’m looking forward for more on this series
Hi all,
tks for this new lesson.
Re : pb mentionned by posts above
this line is not addressed
var interval;
on FF with this : var interval = 100; its OK
I was having the same Firefox problem a few others mentioned… a fast image followed by a slow image…
The fix that ghazal posted above fixed it for me… thanks!
Hi, David
Thanks for your work, it would be better for beginners if make your works available for zip download.
Thanks any way
Hi David!
Thanks for your work!
I try to change images in preview section.
I add
var thumb = $(‘color’).getElements(‘img’); /* another div element
and change images.each(function(img,i) to thumb.each(function(img,i)
I show new image in preview section, but when i click to thumb image the big images is not change.
How to change show = function(to)?
Help please!
im using chrome in windows vista and its very buggy… but it works
@ghazal: I tried that one. Doesn’t change anything in FF3.6 Whenever I am using the thumbnail navigation the slideshow still gets a bit jumpy.
I had the same problem with FF3.6
Since the issue just occured whenever I used the thumbnails to navigate, I tried to remove the start()-Event from the function there. It solved the problem for me.
Now it works just fine, even after navigating with the thumbs.
Great script. I’d really love to use this on my site but I have a question: I’m trying to implement two slideshows on one page and only the first one seems to be working. On the second one it just shows the image and nothing else – no thumbnails and no captions. I’ve tried cloning the javascript section with a different name for the div slideshow-container, but that doesn’t help either. Is there something more I should think of, or is it impossible to use this twice on one page?
@Zinco: hehehhehe a href=”image” rel=”lightbox” , to the big image :D
Hey how can you slow it down so that it blends into the next image a little slower?