11th July 2008

Feature slideshow using Javascript

Quite a few websites have features on their homepage rotating news stories and attractive imagery - it's a cool way to capture the user's attention. I'm thinking of items like on ITV.com (done using Flash) and LussoLuxury.com (done using an iFrame). They're attractive and quite practical, so let's look at making a really simple implementation of one.

I'm using Mootools release 1.2 for this (bundled in the download).

feature slideshow

What it needs to do

All I want is a simple panel that shows an image and a strapline; this panel then fades out and a new one fades in every 8-10 seconds and continues forevermore. Nice and simple. So I've got 4 images (cars and boats) each with a strapline that I want to see rotating every 8 seconds. Simple, non?

XHTML

As always I've wrapped it in a container div, with a slideshow-container div wrapped around that (just to keep things tidy). Then each of the panels is set as a slideshow-item.

It's all very straight forward here; an image and the strapline (wrapped in the slideshow-text div. The important thing to note is the addition of the noscript class on the container. This is something I'm using to ensure that the page loads with different CSS rules when JS is disabled; because how I'm managing the transitions isn't very accessible otherwise - but we'll get to that in a minute.

CSS

I'm setting widths and height on the container which governs the panel's dimensions. I'm setting both width and height on the slideshow-item too with an overflow of hidden; this means that images larger than these dimensions will be cropped rather than breaking the layout.

What I'm doing is positioning each of the slideshow-item divs absolutely on top of each other, so they occupy the same space on the page. Therefore you'll only see one at any one time. I'm positioning the slideshow-text absolutely too at the bottom of the panel. Note the noscript class; this ensures that if the class of noscript is present, the slideshow-items are positioned relatively (one after another on the page, so all are visible). I'm using Javascript to remove this class on-dom-ready (see later). This means that users without Javascript will see all the panels on the page; it breaks layout but it is best for accessibility. You could probably make the container scroll on overflow to ensure layout doesn't break, but this is the method I'm sticking with.

Javascript

As always I'm initialising things onDomReady (to ensure the page has finished loading structure). I'm setting the obvious variables at the top:

One of the first things I'm doing is removing the noscript class from the container, so that the layout will appear as intended. I'm then loading into an array every single slideshow-item and hiding all of the items that are sitting underneath the current active item (determined by it's position on the page - it's the last one, item-4 in this case). So items 1-3 are all hidden with item-4 being displayed. I'm then setting the activeItem variable so I know for future reference which one is visible.

The rotate() function works out which item is currently active (using the activeItem variable declared earlier) and works out whether it's the last item in order in the list of slideshow-items. If it is, then we start back at the beginning. Otherwise we just increment the ID and move on. So if item-2 is active, it moves to item-3. item-3 to item-4 and item-4 back to item-1.

I'm using the started variable to ensure that we get one iteration through before images start shifting (otherwise it flickers on page load as it swaps the images out before you've had a chance to read the first one). At the bottom of the rotate() function I'm using the Mootools periodical function which works a bit like the native setTimeout function. I'm setting the periodical of 3000ms on the rotate function (defined by the slidetime variable above). Before this I'm clearing the timer using the $clear(timer) function provided by Mootools. This means that once started, the rotate() function will continue calling itself every 3 seconds for the rest of eternity.

Then at the very end I'm calling the first instance of rotate() to get the ball rolling; it powers itself hereafter. There you have it, a very simple feature rotation widget.

Improvements

At the moment the images don't line up well but that's an aspect ratio issue; they're merely cropping rather than resizing. It'd be a better idea to get clever with PHP's GDlib to ensure the images are a suitable size and aspect ratio, but that's expensive CPU time that a human could do better by spending a few extra minutes when creating the images. As I said earlier, when JS is disabled I'm just showing all the content on the page which does break layout (but it is best for accessibilty). To avoid doing this you could make the container div scroll on overflow.

Browsers etc

I've given it a test in Opera 9.5, Firefox 2, IE6 and IE7 and it's all groovy. If you experience any layout problems drop me an email and I'll investigate (although they should be easy for you to fix, the layout is super-simple already).

Tagged with javascript, xhtml, widget