Tutorial: Rotating Image Gallery for Pages and Sidebars

by Mike Nichols

Many of my clients have asked for a way to put their own images into a rotating gallery. There is no plugin that is entirely suitable for this purpose that I know of. The closest is the NextGEN gallery plugin, but it has only rigidly defined ways to use it, is complicated to set up, and lacks some important features.

What you need is a simple, easy to use, flexible image gallery that plays nice with Thesis.

This tutorial shows you how to implement a Rotating Image Gallery that can be placed anywhere on the Thesis page that there is a hook — and even in a widget. Shown above and in the sidebar are two instances of the Image Gallery. Note that each has different speeds, and that there are arrows and a pause control on the widget but not in the larger gallery.

The Rotating Image Gallery has these great features:

  • Easy to install and use.
  • Can be placed anywhere there is a hook, and even in a widget.
  • Any number of images of any size can be displayed.
  • Images can be clickable links.
  • Captions are optional, and can have links in them.
  • The Image Gallery can have optional directional arrows and a pause button.
  • Multiple galleries can be shown on the same page.
  • Loops to the beginning after showing the last image, rather than stopping.
  • You have complete control over slide speed, display time, captions, etc of every Image Gallery separately.
  • You can configure fonts, borders, etc in the custom.css file.
  • The JavaScript program is only 14k.
  • Gracefully degrades when JavaScript is turned off. The Image Gallery reverts to a box with scroll bars so the user can still see the images.
  • You can use the Image Gallery right out of the box! Included in the zip file are the images used in this tutorial.

The Rotating Image Gallery was developed from an idea at Catch My Fame. It is released under the Creative Commons Attribution-Share Alike 3.0 license, which means you are free to use and modify the code as long as you share it with others and attribute it to me.

It is mandatory that you download the zip file for this tutorial! It has everything you need — all files, folders and images — in a single zip file. Setting up the Rotating Image Gallery without downloading the zip file is not described in this tutorial! You can download it by clicking here.

Navigation in the Tutorial

This description of the Rotating Image Gallery is in 5 parts. If you want to skip to a particular section, just click on the links below:

How the Rotating Image Gallery works

There are four files used in the Rotating Image Gallery. Each has a full code listing below so you can see how it works. These files are:

  • The rotatingimages.js file, which is the JavaScript program that powers the Image Gallery.
  • for-custom_functions.php contains the functions that are put into the custom_functions.php file.
  • The for-custom.css file has two selectors that are placed in the custom.css file.
  • for-widget.php has only one line of code, which is put into a text widget if you are using the widget version of the Image Gallery.

The rotatingimages.js file

This program actually runs the Rotating Image Gallery. All the other files are necessary, but serve to support it. I modified it so that it would work with Thesis and the Image Gallery.

/*
* Rotating Image Gallery
* @author admin@catchmyfame.com - http://www.catchmyfame.com
* @version 1.2.2 - August 31, 2009
* @copyright (c) 2009 admin@catchmyfame.com (www.catchmyfame.com)
* @license Creative Commons Attribution-Share Alike 3.0
* @http://creativecommons.org/licenses/by-sa/3.0/
* @Modified by Mike Nichols - December 20, 2009
*/

(function($){
$.fn.extend({
rotatingImages: function(options)
{
var defaults =
{
transitionSpeed : 1500,
displayTime : 6000,
textholderHeight : .2,
displayProgressBar : 0,
displayThumbnails: 0,
displayThumbnailNumbers: 0,
displayThumbnailBackground: 0,
thumbnailWidth: '20px',
thumbnailHeight: '20px',
thumbnailFontSize: '.7em'
};
var options = $.extend(defaults, options);

return this.each(function() {
var randID = Math.round(Math.random()*100000000);
var o=options;
var obj = $(this);
var curr = 1;

var numImages = $('img', obj).length; // Number of images
var imgHeight = $('img:first', obj).height();
var imgWidth = $('img:first', obj).width();
var autopilot = 1;

$('p', obj).hide(); // Hide any text paragraphs in the rotating image gallery
$(obj).width(imgWidth).height(imgHeight);

// Build progress bar
if(o.displayProgressBar)
{
$(obj).append('<div id="progress'+randID+'" style="position:absolute;bottom:0;background:#bbb;left:'+$(obj).css('paddingLeft')+'"></div>');
$('#progress'+randID).width(imgWidth).height(5).css('opacity','.5');
}

// Move last image and stick it on the front
$(obj).css({'overflow':'hidden','position':'relative'});
$('li:last', obj).prependTo($('ul', obj));
$('ul', obj).css('left',-imgWidth+'px');
$('ul',obj).width(9999);

$('ul',obj).css({'list-style':'none','margin':'0','padding':'0','position':'relative'});
$('li',obj).css({'display':'inline','float':'left'});

// Build textholder div thats as wide as the rotating image gallery and 20%-25% of the height
$(obj).append('<div id="textholder'+randID+'" class="textholder" style="position:absolute;bottom:0px;margin-bottom:'+-imgHeight*o.textholderHeight+'px;left:'+$(obj).css('paddingLeft')+'"></div>');
var correctTHWidth = parseInt($('#textholder'+randID).css('paddingTop'));
var correctTHHeight = parseInt($('#textholder'+randID).css('paddingRight'));
$('#textholder'+randID).width(imgWidth-(correctTHWidth * 2)).height((imgHeight*o.textholderHeight)-(correctTHHeight * 2)).css({'backgroundColor':'#FFF','opacity':'0.5'});
showtext($('li:eq(1) p', obj).html());

// Prev/next button(img)
html = '<div id="btn_rt'+randID+'" style="position:absolute;right:0;top:'+((imgHeight/2)-15)+'px"><a href="javascript:void(0);"><img style="border:none;margin-right:2px" src="'+o.arrowRight+'" /></a></div>';
html += '<div id="btn_lt'+randID+'" style="position:absolute;left:0;top:'+((imgHeight/2)-15)+'px"><a href="javascript:void(0);"><img style="border:none;margin-left:2px" src="'+o.arrowLeft+'" /></a></div>';
$(obj).append(html);

// Pause/play button(img)
html = '<a href="javascript:void(0);"><img id="pause_btn'+randID+'" src="'+o.pauseButton+'" style="position:absolute;top:3px;right:3px;border:none" alt="Pause" /></a>';
html += '<a href="javascript:void(0);"><img id="play_btn'+randID+'" src="'+o.playButton+'" style="position:absolute;top:3px;right:3px;border:none;display:none;" alt="Play" /></a>';
$(obj).append(html);
$('#pause_btn'+randID).css('opacity','.5').hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.5'},250)});
$('#pause_btn'+randID).click(function(){
autopilot = 0;
$('#progress'+randID).stop().fadeOut();
clearTimeout(clearInt);
$('#pause_btn'+randID).fadeOut(250);
$('#play_btn'+randID).fadeIn(250);
showminmax();
});
$('#play_btn'+randID).css('opacity','.5').hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.5'},250)});
$('#play_btn'+randID).click(function(){
autopilot = 1;
anim('next');
$('#play_btn'+randID).hide();
clearInt=setInterval(function(){anim('next');},o.displayTime+o.transitionSpeed);
setTimeout(function(){$('#pause_btn'+randID).show();$('#progress'+randID).fadeIn().width(imgWidth).height(5);},o.transitionSpeed);
});

// Left and right arrow image button actions
$('#btn_rt'+randID).css('opacity','.75').click(function(){
autopilot = 0;
$('#progress'+randID).stop().fadeOut();
anim('next');
setTimeout(function(){$('#play_btn'+randID).fadeIn(250);},o.transitionSpeed);
clearTimeout(clearInt);
}).hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.75'},250)});
$('#btn_lt'+randID).css('opacity','.75').click(function(){
autopilot = 0;
$('#progress'+randID).stop().fadeOut();
anim('prev');
setTimeout(function(){$('#play_btn'+randID).fadeIn(250);},o.transitionSpeed);
clearTimeout(clearInt);
}).hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.75'},250)});

if(o.displayThumbnails)
{
// Build thumbnail viewer and thumbnail divs
$(obj).after('<div id="thumbs'+randID+'" style="position:relative;overflow:auto;text-align:left;padding-top:5px;"></div>');
$('#thumbs'+randID).width(imgWidth);
for(i=0;i<=numImages-1;i++)
{
thumb = $('img:eq('+(i+1)+')', obj).attr('src');
$('#thumbs'+randID).append('<div class="thumb" id="thumb'+randID+'_'+(i+1)+'" style="cursor:pointer;background-image:url('+thumb+');display:inline;float:left;width:'+o.thumbnailWidth+';height:'+o.thumbnailHeight+';line-height:'+o.thumbnailHeight+';padding:0;overflow:hidden;text-align:center;border:2px solid #ccc;margin-right:4px;font-size:'+o.thumbnailFontSize+';font-family:Arial;color:#000;text-shadow:0 0 3px #fff">'+(i+1)+'</div>');
if(i==0) $('#thumb'+randID+'_1').css({'border-color':'#ff0000'});
}
// Next two lines are a special case to handle the first list element which was originally the last
thumb = $('img:first', obj).attr('src');
$('#thumb'+randID+'_'+numImages).css({'background-image':'url('+thumb+')'});
$('#thumbs'+randID+' div.thumb:not(:first)').css({'opacity':'.65'}); // makes all thumbs 65% opaque except the first one
$('#thumbs'+randID+' div.thumb').hover(function(){$(this).animate({'opacity':.99},150)},function(){if(curr!=this.id.split('_')[1]) $(this).animate({'opacity':.65},250)}); // add hover to thumbs

// Assign click handler for the thumbnails. Normally the format $('.thumb') would work but since it's outside of our object (obj) it would get called multiple times
$('#thumbs'+randID+' div').bind('click', thumbclick); // We use bind instead of just plain click so that we can repeatedly remove and reattach the handler

if(!o.displayThumbnailNumbers) $('#thumbs'+randID+' div').text('');
if(!o.displayThumbnailBackground) $('#thumbs'+randID+' div').css({'background-image':'none'});
}
function thumbclick(event)
{
target_num = this.id.split('_'); // we want target_num[1]
if(curr != target_num[1])
{
$('#thumb'+randID+'_'+curr).css({'border-color':'#ccc'});
$('#progress'+randID).stop().fadeOut();
clearTimeout(clearInt);
//alert(event.data.src+' '+this.id+' '+target_num[1]+' '+curr);
$('#thumbs'+randID+' div').css({'cursor':'default'}).unbind('click'); // Unbind the thumbnail click event until the transition has ended
autopilot = 0;
setTimeout(function(){$('#play_btn'+randID).fadeIn(250);},o.transitionSpeed);
}
if(target_num[1] > curr)
{
diff = target_num[1] - curr;
anim('next',diff);
}
if(target_num[1] < curr)
{
diff = curr - target_num[1];
anim('prev', diff);
}
}

function showtext(t)
{
// the text will always be the text of the second list item (if it exists)
if(t != null)
{
$('#textholder'+randID).html(t).animate({marginBottom:'0px'},500); // Raise textholder
showminmax();
}
}
function showminmax()
{
if(!autopilot)
{
html = '<img style="position:absolute;top:2px;right:18px;display:none;cursor:pointer" src="'+o.arrowDown+'" title="Minimize" alt="minimize" id="min" /><img style="position:absolute;top:2px;right:18px;display:none;cursor:pointer" src="'+o.arrowUp+'" title="Maximize" alt="maximize" id="max" />';
html += '<img style="position:absolute;top:2px;right:6px;display:none;cursor:pointer" src="'+o.closeButton+'" title="Close" alt="close" id="close" />';
$('#textholder'+randID).append(html);
$('#min').fadeIn(250).click(function(){$('#textholder'+randID).animate({marginBottom:(-imgHeight*o.textholderHeight)-(correctTHHeight * 2)+24+'px'},500,function(){$("#min,#max").toggle();});});
$('#max').click(function(){$('#textholder'+randID).animate({marginBottom:'0px'},500,function(){$("#min,#max").toggle();});});
$('#close').fadeIn(250).click(function(){$('#textholder'+randID).animate({marginBottom:(-imgHeight*o.textholderHeight)-(correctTHHeight * 2)+'px'},500);});
}
}
function borderpatrol(elem)
{
$('#thumbs'+randID+' div').css({'border-color':'#ccc'}).animate({opacity: 0.65},500);
setTimeout(function(){elem.css({'border-color':'#ff0000'}).animate({'opacity': .99},500);},o.transitionSpeed);
}
function anim(direction,dist)
{
// Fade left/right arrows out when transitioning
$('#btn_rt'+randID).fadeOut(500);
$('#btn_lt'+randID).fadeOut(500);

// animate textholder out of frame
$('#textholder'+randID).animate({marginBottom:(-imgHeight*o.textholderHeight)-(correctTHHeight * 2)+'px'},500);

//?? Fade out play/pause?
$('#pause_btn'+randID).fadeOut(250);
$('#play_btn'+randID).fadeOut(250);

if(direction == "next")
{
if(curr==numImages) curr=0;
if(dist>1)
{
borderpatrol($('#thumb'+randID+'_'+(curr+dist)));
$('li:lt(2)', obj).clone().insertAfter($('li:last', obj));
$('ul', obj).animate({left:-imgWidth*(dist+1)},o.transitionSpeed,function(){
$('li:lt(2)', obj).remove();
for(j=1;j<=dist-2;j++)
{
$('li:first', obj).clone().insertAfter($('li:last', obj));
$('li:first', obj).remove();
}
$('#btn_rt'+randID).fadeIn(500);
$('#btn_lt'+randID).fadeIn(500);
$('#play_btn'+randID).fadeIn(250);
showtext($('li:eq(1) p', obj).html());
$(this).css({'left':-imgWidth});
curr = curr+dist;
$('#thumbs'+randID+' div').bind('click', thumbclick).css({'cursor':'pointer'});
});
}
else
{
borderpatrol($('#thumb'+randID+'_'+(curr+1)));
$('#thumbs'+randID+' div').css({'cursor':'default'}).unbind('click'); // Unbind the thumbnail click event until the transition has ended
// Copy leftmost (first) li and insert it after the last li
$('li:first', obj).clone().insertAfter($('li:last', obj));
// Update width and left position of ul and animate ul to the left
$('ul', obj)
.animate({left:-imgWidth*2},o.transitionSpeed,function(){
$('li:first', obj).remove();
$('ul', obj).css('left',-imgWidth+'px');
$('#btn_rt'+randID).fadeIn(500);
$('#btn_lt'+randID).fadeIn(500);
if(autopilot) $('#pause_btn'+randID).fadeIn(250);
showtext($('li:eq(1) p', obj).html());
if(autopilot)
{
$('#progress'+randID).width(imgWidth).height(5);
$('#progress'+randID).animate({'width':0},o.displayTime,function(){
$('#pause_btn'+randID).fadeOut(50);
setTimeout(function(){$('#pause_btn'+randID).fadeIn(250)},o.transitionSpeed)
});
}
curr=curr+1;
$('#thumbs'+randID+' div').bind('click', thumbclick).css({'cursor':'pointer'});
});
}
}
if(direction == "prev")
{
if(dist>1)
{
borderpatrol($('#thumb'+randID+'_'+(curr-dist)));
$('li:gt('+(numImages-(dist+1))+')', obj).clone().insertBefore($('li:first', obj));
$('ul', obj).css({'left':(-imgWidth*(dist+1))}).animate({left:-imgWidth},o.transitionSpeed,function(){
$('li:gt('+(numImages-1)+')', obj).remove();
$('#btn_rt'+randID).fadeIn(500);
$('#btn_lt'+randID).fadeIn(500);
$('#play_btn'+randID).fadeIn(250);
showtext($('li:eq(1) p', obj).html());
curr = curr - dist;
$('#thumbs'+randID+' div').bind('click', thumbclick).css({'cursor':'pointer'});
});
}
else
{
borderpatrol($('#thumb'+randID+'_'+(curr-1)));
$('#thumbs'+randID+' div').css({'cursor':'default'}).unbind('click'); // Unbind the thumbnail click event until the transition has ended
// Copy rightmost (last) li and insert it after the first li
$('li:last', obj).clone().insertBefore($('li:first', obj));
// Update width and left position of ul and animate ul to the right
$('ul', obj)
.css('left',-imgWidth*2+'px')
.animate({left:-imgWidth},o.transitionSpeed,function(){
$('li:last', obj).remove();
$('#btn_rt'+randID).fadeIn(500);
$('#btn_lt'+randID).fadeIn(500);
if(autopilot) $('#pause_btn'+randID).fadeIn(250);
showtext($('li:eq(1) p', obj).html());
curr=curr-1;
if(curr==0) curr=numImages;
$('#thumbs'+randID+' div').bind('click', thumbclick).css({'cursor':'pointer'});
});
}
}
}

var clearInt = setInterval(function(){anim('next');},o.displayTime+o.transitionSpeed);
$('#progress'+randID).animate({'width':0},o.displayTime+o.transitionSpeed,function(){
$('#pause_btn'+randID).fadeOut(100);
setTimeout(function(){$('#pause_btn'+randID).fadeIn(250)},o.transitionSpeed)
});
});
}
});
})(jQuery);


The for-custom_functions.php file

This file contains the functions necessary to load the JavaScript program and configure the images. They are placed in the custom_functions.php file.

/*================================================*/
/* ROTATING IMAGES GALLERY */
/* Version 1.0 */
/* Written by Mike Nichols December 20, 2009 */
/* Website: http://thesisthemetools.com/ */
/* Copyright (c) 2009 by Michael L Nichols */
/* License: Creative Commons Share-Alike 3.0 */
/* http://creativecommons.org/licenses/by-sa/3.0/ */
/*================================================*/

/* ------------------------------------ */
/* Call JavaScript and JQuery in footer */
/* and configure the image galleries */
/* ------------------------------------ */
function rotating_images_foot() {
?>
<!-- call JQuery and JavaScript -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

<script type="text/javascript" src="<?php bloginfo('template_url') ?>/custom/rotating_images/rotatingimages.js"></script>

<!-- Configure rotating gallery -->
<script type="text/javascript">

<!-- Configure rotating gallery for a widget begin -->
<!-- You can delete this if not using a widget -->
$(function(){
$('#image_gallery_widget').rotatingImages({
//time in milliseconds to transition between 2 images - default 1500
transitionSpeed : 2000,
//time in milliseconds to display each image - default 6000
displayTime : 10000,
//height of the caption. Fraction of height of images - default .2
textholderHeight : .14,
//display progress bar 0=no 1=yes
displayProgressBar : 0,
//URLs of the arrows and buttons
arrowRight: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/rt.png',
arrowLeft: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/lt.png',
pauseButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/pause.png',
playButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/play.png',
//do not change the following settings!
arrowUp: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/up-clear.png',
arrowDown: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/down-clear.png',
closeButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/close-clear.png'
});
});
<!-- Configure rotating gallery for a widget end -->

<!-- Configure rotating gallery for a page or post begin -->
<!-- You can delete this if not using for a page or post -->
$(function(){
$('#image_gallery_page').rotatingImages({
//time in milliseconds to transition between 2 images - default 1500
transitionSpeed : 1000,
//time in milliseconds to display each image - default 6000
displayTime : 5000,
//height of the caption. Fraction of height of images - default .2
textholderHeight : .1,
//display progress bar 0=no 1=yes
displayProgressBar : 0,
//URLs of the arrows and buttons
arrowRight: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/rt-clear.png',
arrowLeft: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/lt-clear.png',
pauseButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/pause-clear.png',
playButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/play-clear.png',
//do not change the following settings!
arrowUp: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/up-clear.png',
arrowDown: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/down-clear.png',
closeButton: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/close-clear.png'
});
});
<!-- Configure rotating gallery for a page or post end -->

</script>
<?php
}
add_action('thesis_hook_after_html','rotating_images_foot');

/* ------------------------------------------------ */
/* SET UP ROTATING IMAGE GALLERY FOR A PAGE OR POST */
/* ------------------------------------------------ */
function image_gallery_page_setup() {
?>
<div id="image_gallery_page">
<ul>

<!-- IMAGE SETUP FORMAT
<li>
<img alt="ALT-TITLE" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/IMAGE-NAME" width="WIDTH" height="HEIGHT" />
<p>TEXT-IN-CAPTION (optional - delete this line if no description)</p>
</li>
-->

<li>
<img alt="bluebird in the snow"
src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/bluebird-in-snow.jpg"
width="500" height="353" />
<p>A bluebird in the snow</p>
</li>

<li>
<img alt="frosty leaves" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/frosty-leaves.jpg" width="500" height="353" />
<p>Frosty leaves with red berries</p>
</li>

<li>
<a href="http://anxietypanichealth.com/"><img alt="frosty wood" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/frosty-wood.jpg" width="500" height="353" /></a>
<p>This image is clickable. Try it!</p>
</li>

<li>
<img alt="lake with reflections" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/reflected-trees.jpg" width="500" height="353" />
<p>A lake with snowy trees reflected in the water</p>
</li>

<li>
<img alt="surrealist snow" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/surrealist-snow.jpg" width="500" height="353" />
<p>An example of a clickable link in a caption is <a href="http://anxietypanichealth.com/">my other blog</a>.</p>
</li>
</ul>
</div>
<?php
}
/*ADD THIS FUNCTION TO ANY HOOK WHERE YOU WANT IT TO APPEAR */
add_action ('thesis_hook_before_post','image_gallery_page_setup');

/* ------------------------------------------ */
/* SET UP ROTATING IMAGE GALLERY FOR A WIDGET */
/* ------------------------------------------ */
function image_gallery_widget_setup() {
?>
<div id="image_gallery_widget">
<ul>

<!-- IMAGE SETUP FORMAT
<li>
<img alt="ALT-TITLE" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/IMAGE-NAME" width="WIDTH" height="HEIGHT" />
<p>TEXT-IN-CAPTION (optional - delete this line if no description)</p>
</li>
-->

<li>
<img alt="beautiful sunset" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/lake.jpg" width="220" height="138" />
<p>A beautiful sunset over a lake</p>
</li>

<li>
<img alt="ripening cherries" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/cherries.jpg" width="220" height="138" />
<p>Ripening cherries</p>
</li>

<li>
<a href="http://anxietypanichealth.com/"><img alt="yellow flowers" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/flowers.jpg" width="220" height="138" /></a>
<p>This image is clickable. Try it!</p>
</li>

<li>
<img alt="butterfly" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/butterfly.jpg" width="220" height="138" />
<p>Butterfly on a white flower</p>
</li>

<li>
<img alt="lake with clouds" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/lake-w-clouds.jpg" width="220" height="138" />
<p>An example of a URL in the message is <a href="http://anxietypanichealth.com/">my other blog</a>.</p>
</li>
</ul>
</div>
<?php
}


The for-custom.css file

This file has only two selectors: one for the page/post version of the Rotating Image Gallery, and one for the widget version. These selectors are put into the custom.css file.

/*=============================================== */
/* ROTATING IMAGES GALLERY */
/* Version 1.0 */
/* Written by Mike Nichols December 20, 2009 */
/* Website: http://thesisthemetools.com/ */
/* Copyright (c) 2009 by Michael L Nichols */
/* License: Creative Commons Share-Alike 3.0 */
/* http://creativecommons.org/licenses/by-sa/3.0/ */
/*=============================================== */
/* image gallery in a widget */
#image_gallery_widget {
/* width and height must be the same size as images */
width:220px;
height:138px;
/* border if desired */
border:2px solid #999;
/* font size */
font-size: .7em;
/* font family if desired */
font-family: Georgia, serif;
/* bold or not */
font-weight: bold;
/* do not change these! */
overflow:scroll;
margin: 0;
padding: 0;
}

/* image gallery in a page or post */
#image_gallery_page {
/* width and height must be the same size as images */
width:500px;
height:353px;
/* border if desired */
border:4px double #000000;
/* font size */
font-size: 1.3em;
/* font family if desired */
/*font-family: Verdana, sans-serif;*/
/* bold or not */
font-weight: bold;
/* do not change these! */
overflow:scroll;
margin: 0;
padding: 0;
}


The for-widget.php file

This file is needed only if you are using the widget version of the Rotating Image Gallery. It contains one line of code, which is inserted into a text widget.

<?php image_gallery_widget_setup() ?>

Installing the Rotating Image Gallery

Installing the Rotating Image Gallery is very simple, and has only 3 steps, each of which is covered in detail. Following is an overview of the steps to install it:

  • Copy the rotating_images folder in the zip file to your /custom folder.
  • Insert the functions found in the for-custom_functions.php file into your custom_functions.php file.
  • Insert the selectors found in the for-custom.css file into your custom.css file.

If you are using the Rotating Image Gallery in a widget there are two additional steps, described in the next section.

STEP 1. Copy the rotating_images folder into your /custom folder

The “rotating_images” folder has these items in it:

  • The rotatingimage.js file, which is the JavaScript program that powers the Image Gallery
  • The /arrows folder containing all the buttons and arrows used.
  • A /gallery folder for your images. It already has all the images used this tutorial in it. Feel free to delete them and replace them with your own images.

All you have to do is to copy the entire /rotating_images folder to your /custom folder. Do not copy individual files!

Really, that’s all there is to this step!

STEP 2. Put the functions in for-custom_functions.php into the custom_functions.php file

The for-custom_functions.php file has three functions in it. You can put these functions anywhere you want in the custom_functions.php file, but I suggest putting them at the end. Here’s some information you need about copying them:
1. You must copy the rotating_images_foot function to custom_functions.php! It is used for both versions of the Image Gallery.
2. Copy the image_gallery_page_setup function if you will be using the Rotating Image Gallery for a post or a page.
3. Copy the image_gallery_widget_setup function if you will be using the Image Gallery in a widget.

STEP 3. Put the selectors in the for-custom.css file into custom.css

The for-custom.css file has two selectors. You can put these anywhere in the custom.css file, but I suggest putting them at the end. You do not have to copy both selectors unless you are using both the page/post version of the Image Gallery and the widget version:
1. Copy the image_gallery_page selector if you are using the post/page version.
2. Copy the image_gallery_widget selector if you are using the widget version.
3. It will not hurt anything if you copy both selectors to your custom.css file.

Installing the Rotating Image Gallery for a Widget

If you will be using the Rotating Image Gallery in a widget, there are two additional steps you must take:

  • Upload, install and set up a plugin that allows widgets to execute PHP code
  • Install a text widget and put the supplied code into it

STEP 1. Install a plugin that allows widgets to execute PHP code

Widgets do not execute PHP code without a little help from a plugin. I recommend the Exec-PHP plugin, but there are a few others that do the same thing. All you have to do is upload and activate it. The settings have only one check box, which must be checked.

STEP 2. Put the provided code into a text widget

Go to the Widgets panel in your WordPress dashboard. Put a text widget in the sidebar and location you want the Rotating Image Gallery to appear. Insert the one line of code provided in the file for-widget.php into the text widget and save it. The code is listed below for your convenience:

<?php image_gallery_widget_setup() ?>

Setting up the Rotating Image Gallery

Setting up your Image Gallery is not hard, but it does take a little care. There are three types of settings:

  • The properties for display time, speed, etc
  • The URL, size, etc of your images
  • The size of your image box, font choices, etc in the custom.css file

All these steps will be covered in detail in the following sections. Incidentally, the settings in the code listed above and the files in the zip file are the ones used in this tutorial.

STEP 1. Setting the properties for display time, speed, etc

This setting will probably only have to be done once unless you like to experiment. Note that each Image Gallery on a page can have different settings — the widget and the large Gallery at the top of this article have their own individual settings. Here are the steps to take:
1. Find the rotating_images_foot function in the provided code for the custom_functions.php file.
2. Find the “Configure rotating gallery…” comment for either the widget version or the page/post version.
3. Check and/or change the property settings in the section. Each property is commented, and there’s an explanation of each below the following code example. Here is what the property settings for the widget look like — the ones for the page/post are identical:

//time in milliseconds to transition between 2 images - default 1500
transitionSpeed : 2000,
//time in milliseconds to display each image - default 6000
displayTime : 10000,
//height of the caption. Fraction of height of images - default .2
textholderHeight : .14,
//display progress bar 0=no 1=yes
displayProgressBar : 0,

transitionSpeed is how fast the images move when changing from one to the next. If you set this too fast, images with a large file size may hesitate or stutter.
displayTime is how long the image is displayed. Setting it to a larger number makes the image stay visible longer.
textholderHeight determines how tall the caption box is. The number is a fraction of the height of the image. You may have to experiment with this number, especially if you have long captions that take two or more lines.
displayProgressBar You can choose to display a progress bar at the bottom of the image that shows how much longer the image has to display. It starts out all the way across the bottom and gets shorter as the view time decreases.

4. Do not change the section for the URLs unless you want to remove the arrows and pause buttons. That subject is covered in the following section.

How to remove the arrows, pause and other buttons in the properties section

The forward and backward buttons, pause button, and the little button and arrows that come up when the Image Gallery is paused can be removed so that they cannot be used. All you have to do is add “-clear” to the name of the image URL in the rotating_images_foot function in the custom_functions.php file. Note that the large Image Gallery at the top of the page has no arrows, pause button or other buttons and arrows, while the widget has all of them.

For example, this is what the arrowLeft property looks like when the left arrow appears:

arrowLeft: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/lt.png',

To hide the left arrow, add “-clear” to the end of the file name (not the file extension!) in the property like this:

arrowLeft: '<?php bloginfo('template_url') ?>/custom/rotating_images/arrows/lt-clear.png',

STEP 2. Setting the URL, size, etc of your images

This setting is the same for both the page/post version of the Rotating Image Gallery and the widget version. Making the settings is not hard once you get the hang of it, though it may look complicated at first glance.

Here’s how to do it:
1. Select the right function to work on. If setting up a page/post Image Gallery, look for the image_gallery_page_setup function in the “SET UP ROTATING IMAGE GALLERY FOR A PAGE OR POST” section of the code provided for the custom_functions.php file. If setting up the widget version, look for the image_gallery_widget_setup function under the “SET UP ROTATING IMAGE GALLERY FOR A WIDGET” section.
2. There is an “IMAGE SETUP FORMAT” comment at the beginning of both versions. It is repeated here with comments right below it:

<!-- IMAGE SETUP FORMAT
<li>
<img alt="ALT-TITLE" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/IMAGE-NAME" width="WIDTH" height="HEIGHT" />
<p>TEXT-IN-CAPTION (optional - delete this line if no description)</p>
</li>
-->

ALT-TITLE is a short description of the image. It is optional but highly recommended that you take the time to enter this information.
IMAGE-NAME is the file name of the image, for example “pickles.jpg”. Do not change any other part of the URL! It is set up so that it will find your images if you have put them in the /rotating_images/gallery folder (see below).
WIDTH and HEIGHT must be entered for each image. It seems redundant, but that’s the way it is!
TEXT-IN-CAPTION is the text shown in the caption under the image. If you make the caption long enough, it will wrap to two or more lines. If this happens, you will have to adjust the textholderHeight property, as described above.

And here is a fully set up image for the bluebird image shown in the larger Image Gallery at the top of the screen:

<li>
<img alt="bluebird in the snow"
src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/bluebird-in-snow.jpg"
width="500" height="353" />
<p>A bluebird in the snow</p>
</li>

How to get rid of the caption entirely

All you have to do is to delete the whole line with the paragraph tags in the item setup. If you were eliminating the caption in the example above, you would delete this line:

<p>A bluebird in the snow</p>

How to set up a clickable image

To get a clickable image, wrap the image URL in an HTML anchor tag. Using the “image setup format” example above, here’s what to do:

<li>
<a href="LINK-URL"><img alt="ALT-TITLE" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/IMAGE-NAME" width="WIDTH" height="HEIGHT" /></a>
<p>TEXT-IN-CAPTION</p>
</li>

The only additional task is to fill in the “LINK-URL” which must be the full URL of the site you are linking to. Below is an example of the “Frosty Wood” image (the one of a piece of wood) in the large Image Gallery shown at the top of the screen:

<li>
<a href="http://anxietypanichealth.com/"><img alt="frosty wood" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/frosty-wood.jpg" width="500" height="353" /></a>
<p>This image is clickable. Try it!</p>
</li>

How to set up a clickable link in the caption

All you have to do to get a link in your caption is to wrap some words in a standard HTML anchor tag. Once again, using the “image setup format” example, here is what you have to fill in:

<li>
<img alt="ALT-TITLE" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/surrealist-IMAGE-NAME" width="WIDTH" height="HEIGHT" />
<p>TEXT-IN-CAPTION <a href="LINK-URL">LINK-DESCRIPTION</a></p>
</li>

LINK-URL is the URL of the site you want to link to. You must put in the full URL of the site, or you will get a 404 page!
LINK-DESCRIPTION are the words in the caption that will be linked and that the visitor will click on.

Here is an example of a completely set up image with a link in the caption. It is for the “Surrealist Snow” image shown in the large Image Gallery box at the top of this article:

<li>
<img alt="surrealist snow" src="<?php bloginfo(template_url)?>/custom/rotating_images/gallery/surrealist-snow.jpg" width="500" height="353" />
<p>An example of a clickable link in a caption is <a href="http://anxietypanichealth.com/">my other blog</a>.</p>
</li>

STEP 3. How to set up the selectors in custom.css

There are two selectors provided for your custom.css file: one for widgets and one for the page/post version. They are identical except for their names.

The selectors are heavily commented and contain only standard CSS properties. I won’t repeat the comments in the code so as not to bore you. I have put in a few properties for fonts, but you can add whatever other properties you want.

You may use the properties as-is, except you must set the height and width properties the same as the images that you entered above under Step 2 above! If you don’t your Image Gallery probably won’t work, or will appear as a box with scroll bars at the sides and bottom.

Preparing your images for the Rotating Image Gallery

All images within a Rotating Image Gallery must be the same size.

If they are not, your Image Gallery will at best look odd, or at worst not work at all. There are many programs available that can resize images, some of them free.

Determine the size that you want your Image Gallery to be

If putting the Image Gallery into the content column, be sure not to exceed the width you set in the Thesis Design Options. Likewise, if putting it into a widget, check the sidebar size to make sure your images are not too wide.

Optimize the size of your images for the best results

Images that have file sizes that are too large may cause stuttering or hesitation as they move into the image box. Make sure your images’ size is optimized for the web. There are many programs that will optimize them without significantly degrading their quality.

Note that you will put your own images into the /rotating_images/gallery folder. If you put them anywhere else they won’t be found!

Tips for using the Rotating Image Gallery

1. Setting the transition speed too fast can result in stuttering or hesitation as the image changes. Reset the transitionSpeed property in the rotating_images_foot function in the custom_functions.php file to a higher number.
2. Images that have file sizes that are too large may cause stuttering or hesitation, too. Make sure your images’ size is optimized for the web. There are many programs that will optimize them, many for free.
3. Captions that are too long will wrap to two or more lines. If these additional lines are not showing completely, change the textholderHeight property in the rotating_images_foot function in the custom_functions.php file to a larger value.

It is mandatory that you download the zip file for this tutorial! It has everything you need — all files, folders and images — in a single zip file. Setting up the Rotating Image Gallery without downloading the zip file is not described in this tutorial! You can download it by clicking here.

I hope you find this tutorial easy to follow, and that you give the Rotating Image Gallery a try. Be sure to download the zip file! As always, your comments are welcome. If you want to contact me directly by email, please click the “Contact” button in the menu.

©2009 Michael L Nichols. All rights reserved.

What next?

Your comments are always welcome, and are important to this blog’s community! Leave a comment now, or read the comments.

You can find several related articles in the “Related Articles” list below. In the footer you will find a lists of Popular Posts, Recent Posts, and you may browse by Categories, or tags. There’s also a Google Custom Search box to help you find just what you want.

Get free updates by RSS or email!

If you have enjoyed this article, please consider subscribing to article updates, using an RSS reader, or by email. It’s free and is a great way to make sure you don’t miss a single article! I also invite you to follow me on Twitter!

Why not share this article with others!

Share this article with your friends using your favorite social media service, such as StumbleUpon, or Digg. Check out the icons below under “Share This Article With Others” for other social media, including del.icio.us, Technorati, Sphinn, Friendfeed, FaceBook, MySpace andLinkedIn! You can also email or print the article, and even tweet it using Twitter!

Be Sociable, Share!