Can you go into detail a little more about how you set up the gallery?
Sure.
Markup
The screen shot here should explain how the I’ve represented each image as a document in the site tree:

I’m using Ditto to output the thumbs markup like this:
<ul id="thumbs">
<li><a href="image.jpg" title="Tap 54365"><em></em><img src="assets/images/dream/thumb/dream_tap_54365.jpg" alt="Tap 54365" width="34" height="34" /></a></li>
</ul>
I’m using Ditto with the parameter save=`2` so that the result set is saved for later.
The big image #bigImg and #loading div look like this:
<div id="loading"></div>
<img src="myimage.jpg" alt="myimagetitle" id="bigImg" />
The default big image is the first image found in the Ditto result set. I’m using a little snippet to output it, like this:
# grab the saved ditto resource of images
$aImg = $modx->getPlaceholder("ditto_resource");
// get the first image in the array
return '<img src="'.$aImg[0]["imgBig"].'" alt="'.$aImg[0]["pagetitle"].'" width="430" height="407" id="bigImg" />';
CSS
This is the fun bit. You can make the thumbs look however you like. I have chosen to have them as a square grid, and to use a transparent png for the hover and active states. The key thing to understand is that I’m using absolute positioning inside a relatively positioned element, and shifting the left position on mouseover, or when the parent element has the class ’active’. This technique allows for *transparent* png rollovers in IE6. My css looks like this:
#thumbs li {
display: inline;
}
#thumbs a {
display: block;
position:relative;
float: left;
margin: 0 10px 10px 0;
text-decoration: none;
width: 34px;
height: 34px;
overflow: hidden;
}
#thumbs a em {
display: block;
width: 68px;
height: 34px;
position:absolute;
left:0; top:0;
background: transparent url('/_assets/img/thumbs_overlay.png') 0 0 no-repeat;
}
#thumbs a:focus em, #thumbs a:hover em, #thumbs a.active em {
left: -34px;
cursor: pointer;
}
/ * IE6 transparency */
* html #thumbs a em {
background-image: none;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader (src='/_assets/img/thumbs_overlay.png',sizingMethod='scale');
}
/* loading div is positioned over the top of the image */
#loading {
position: absolute;
top:0; left:185px;
width: 430px;
height: 407px;
background: #C8CED3 url('/_assets/img/loading2.gif') 201px 189px no-repeat;
display:none;
}
Javascript
The js does the following:
* on dom ready it iterates through each of the thumbnail image links and adds a click behaviour
* on click of a thumbnail the loading div fades in to hide the big image and the ’active’ class is applied to the selected thumbnail.
* the selected image is loaded into a temporary image object and then swapped with the big image when the new image has loaded
* the loading div is now faded out and hidden, revealing the new image.
This class simply provides a container for each gallery image. I seperated it out like this so that other meta data about an image could be modeled by the object, but for this gallery I’m just using the image url and title:
var GalleryImage = function (image,title) {
// private vars
var self = this; // get the scope of the instantiated object
// public instance variables
this.image = image; // array
this.title = title;
}
This object attaches the behaviour to the thumbnail images and handles the on click event. Here I’m using jQuery to do the alpha fades, the selection of objects in the document, and to handle callbacks (which it is brilliant at). Previously I’d hand coded this but now I realise that it’s best to not reinvent the wheel and just let jQuery get on with it...
// Gallery object (literal notation)
var Gallery = {
//default config
imageId : '#bigImg',
loadId : '#loading',
thumbs : '#thumbs > li > a', // selector for image thumb links
CSSselectedClass : 'active', // css class to apply to selected items
startImg : 0,
startShowImg : true,
aImages : new Array (),
//private vars
selectedImg : -1,
isPaused : false,
imgLinks : new Array (),
loaded : false,
showImg : function (img) {
if (Gallery.loaded && !Gallery.isPaused && Gallery.selectedImg != img) {
if (img !=-1) {
Gallery.showImage(img);
//manage links
Gallery.manageLinks(img);
}
}
},
manageLinks : function (img) {
//set css class on thumbnail images
for (i=0; i<Gallery.imgLinks.length; i++) {
if(i === img) { // set selected class
Gallery.imgLinks[i].attr("class",Gallery.CSSselectedClass);
} else { //remove class attribute
Gallery.imgLinks[i].removeAttr("class");
}
}
},
swapImage : function (img) {
$bigImg = $(Gallery.imageId);
$bigImg.attr("src", Gallery.aImages[img].image);
$bigImg.attr("alt", Gallery.aImages[img].title);
$bigImg.attr("title", Gallery.aImages[img].title);
},
showImage : function (img) {
// show loadmeter
$loading=$(Gallery.loadId);
$loading.css({
display: "block"
});
$loading.fadeTo(200,1, function() {
// preload image into a temporary image object so that it is cached
imgPreload = new Image();
// onload
imgPreload.onload=function(){
Gallery.swapImage(img);
//fade out loading
// pass the killPause() function to be called back on completion
Gallery.isPaused = true;
Gallery.selectedImg = img;
$loading.fadeTo("slow",0,Gallery.killPause);
}
imgPreload.src = Gallery.aImages[img].image;
});
},
killPause: function() {
Gallery.isPaused = false;
},
attachLinkBehavior : function () {
$(Gallery.thumbs).each(
//lopp trough each item found
function (i) {
//build array of big images
Gallery.aImages.push(new GalleryImage($(this).attr("href"),$(this).attr("title")));
// build array of thumbs
Gallery.imgLinks.push($(this));
$(this).bind (
"click",
function(){
// do stuff on click
Gallery.showImg(i);
return false; // stop link being followed
}
);
}
);
},
init : function () {
// add link behaviour
Gallery.attachLinkBehavior();
Gallery.loaded=true;
if (Gallery.startShowImg) {
//show start image
Gallery.showImg(Gallery.startImg);
}
}
}
So that’s it really. I hope you can see that you adapt this for all sorts of galleries, since you can use modx document tvs to store any kind of data and then extend the GalleryImage class so that it is available to the Gallery object.