Fresh Sliding Thumbnails Gallery with jQuery and PHP

In this tutorial we are going to create another full page image gallery with a nice thumbnail area that scrolls automatically when moving the mouse. The idea is to allow […]

In this tutorial we are going to create another full page image gallery with a nice thumbnail area that scrolls automatically when moving the mouse. The idea is to allow the user to slightly zoom into the picture by clicking on it. The thumbnails bar slides down and the image resizes according to the screen size.

The scrolling functionality of the thumbnails bar is based on the great tutorial by Andrew Valums: Horizontal Scrolling Menu made with CSS and jQuery.
Additionally, we will be using PHP to get the images and thumbs automatically from the folder structure. The folders will contain album sub-folders and we will add a select option to the gallery which allows to choose an album.

Just like in the Sliding Panel Photo Wall Gallery with jQuery we will be using a resize function for the image displayed.

We will also add an XML file that (optionally) contains the descriptions of the images.

Another neat functionality that we are going to add is the changing cursor: depending in which mode and in which position of the full image we are, the cursor will change to a left or right arrow (for browsing the pictures), or to a plus or minus sign (for zooming in or out).

The beautiful images in the demo are from the Models 1 – Photoshoots album from Vincent Boiteau’s photostream on Flickr.

We also have a static version of the image gallery without the album option. You can find the demo link and the ZIP file in the end of this post.

And don’t forget to check out the tutorial of the  mobile version of this gallery: Awesome Mobile Image Gallery Web App

So, let’s start!

The Folder Structure

Today we will start this tutorial by the folder structure since it is important for our PHP functionality.

The necessary folders for the PHP to work are the images folder and the thumbs folder. They both need to be located in the root folder (where you will have the index.php file).

Whatever album sub-folder will be in the thumbs folder, also needs to be in the images folder. So, if we have thumbs/album1/22.jpg we also need images/album1/22.jpg which will be the full-size image.

With that organization we will be able to automatically display the album thumbnails and create a select box for all albums.

In each album folder of the thumbs we will also have an XML file with the descriptions for the images. We will call that file desc.xml. Adding the description for images is not obligatory, i.e. we will just read the ones that are there. The structure of the XML file will be the following:

<descriptions>
	<image>
		<name>1.jpg</name>
		<text>This is a nice description</text>
	</image>
	<image>
		<name>2.jpg</name>
		<text>red!</text>
	</image>
	<image>
		<name>3.jpg</name>
		<text>another one...</text>
	</image>
	...
</descriptions>

It is important that we name the images in the name tag correctly.
And also, make sure not to have any other files lying around in those folders.

The Markup and PHP

Let’s take a look at the HTML and also the PHP. We have a simple structure that will be dynamically “filled” by our PHP and JavaScript code:

<div class="albumbar">
	<span>Vincent Boiteau's photostream</span>
	<div id="albumSelect" class="albumSelect">
		<ul>
			<!-- We will dynamically generate the items -->
			<?php
				$firstAlbum = '';
				$i=0;
				if(file_exists('images')) {
					$files = array_slice(scandir('images'), 2);
					if(count($files)) {
						natcasesort($files);
						foreach($files as $file) {
							if($file != '.' && $file != '..') {
								if($i===0)
									$firstAlbum = $file;
								else
									echo "<li><a>$file</a></li>";
								++$i;
							}
						}
					}
				}
			?>
		</ul>
		<div class="title down">
			<?php echo $firstAlbum;?>
		</div>
	</div>
</div>
<div id="loading"></div>
<div id="preview">
	<div id="imageWrapper">
	</div>
</div>
<div id="thumbsWrapper">
</div>
<div class="infobar">
	<span id="description"></span>
</div>

The select box items get generated dynamically: we check the sub-folders in the images folder and put all the names in our items. The first album will be “selected” by default.

When we click on one of the items we will call the thumbs.php (inside the ajax folder) from within the JavaScript. We will get back an array (JSON) with all the information that we need to build our thumbnails. Let’s look at that PHP code first and later we will go through the JS:

$album 		= $_GET['album'];
$imagesArr	= array();
$i		= 0;

/* read the descriptions xml file */
if(file_exists('../thumbs/'.$album.'/desc.xml')) {
    $xml = simplexml_load_file('../thumbs/'.$album.'/desc.xml');
}
/* read the images from the album and get the
 * description from the XML file:
 */
if(file_exists('../thumbs/'.$album)) {
    $files = array_slice(scandir('../thumbs/'.$album), 2);
    if(count($files)) {
        foreach($files as $file) {
            if($file != '.' && $file != '..' &&  $file!='desc.xml') {
                if($xml) {
                    $desc = $xml->xpath('image[name="'.$file.'"]/text');
                    $description = $desc[0];
                    if($description=='')
                        $description = '';
                }
                $imagesArr[] = array('src' => 'thumbs/'.$album.'/'.$file,
                    'alt'	=> 'images/'.$album.'/'.$file,
                    'desc'	=> $description);
            }
        }
    }
}
$json 		= $imagesArr;
$encoded 	= json_encode($json);
echo $encoded;
unset($encoded);

So, we basically get all the thumbnails of the requested album and prepare the information for each img element. The final element that we will then add to our HTML will contain an alt attribute with the full image location as value and a title attribute with the description of the regarding picture as value. The description of the image is taken from the XML file we mentioned before. With an xpath expression we get to the node “name” that contains the image name and then we get the text of the description. In the JS we will then say that the description should be the value of the “title” attribute.

Now, let’s take a look at the style.

The CSS

First, we will add some default styling to the body:

body{
    font-family:Verdana;
    text-transform:uppercase;
    color:#fff;
    font-size:10px;
    overflow:hidden;
    background-color:#f9f9f9;
}

The current background color will be almost white but you can try other colors, it looks really wonderful with some!

Let’s style the album bar for the title of the page:

.albumbar{
    height:24px;
    line-height:24px;
    text-align:center;
    position:fixed;
    background-color:#000;
    left:0px;
    width:100%;
    top:0px;
    -moz-box-shadow:-2px 0px 4px #333;
    -webkit-box-shadow:-2px 0px 4px #333;
    box-shadow:-2px 0px 4px #333;
    z-index:11;
}

And also the info bar which will contain the description of each image:

.infobar{
    height:22px;
    line-height:22px;
    text-align:center;
    position:fixed;
    background-color:#000;
    left:0px;
    width:100%;
    bottom:0px;
    -moz-box-shadow:0px -1px 2px #000;
    -webkit-box-shadow:0px -1px 2px #000;
    box-shadow:0px -1px 2px #000;
}
span#description, .albumbar span{
    text-shadow:0px 0px 1px #fff;
    color:#fff;
}
.albumbar span a{
    color:#aaa;
    text-decoration:none;
}
.albumbar span a:hover{
    color:#ddd;
}

The info bar and the album bar will be fixed and located at the top and bottom of the page.
The select box and the inner list will be styled as follows:

.albumSelect{
    height:18px;
    line-height:18px;
    position:absolute;
    right:5px;
    top:2px;
    width:120px;
}
.albumSelect .title{
    color:#f0f0f0;
    z-index:10;
    border:1px solid #444;
    background-color:#555;
    background-repeat:no-repeat;
    background-position:90% 50%;
    cursor:pointer;
    text-align:left;
    text-indent:10px;
    width:100%;
    position:absolute;
    top:0px;
    left:0px;
}

The title div will have a little triangle as background image. We define two classes, up and down, that we will then set dynamically depending on if the album list is expanded or not:

.down{
    background-image:url(../icons/down.png);
}
.up{
    background-image:url(../icons/up.png);
}

The unordered list with all the albums will be styled as follows:

.albumSelect ul {
    list-style:none;
    display:none;
    padding:0px;
    width:100%;
    border:1px solid #444;
    background-color:#555;
    margin:22px 0px 0px 0px;
    -moz-box-shadow:0px 0px 2px #000;
    -webkit-box-shadow:0px 0px 2px #000;
    box-shadow:0px 0px 2px #000;
}
.albumSelect ul li a{
    text-decoration:none;
    cursor:pointer;
    display:block;
    padding:3px 0px;
    color:#ccc;
}
.albumSelect ul li a:hover{
    background-color:#000;
    color:#fff;
}

The list is set to display:none in the beginning since we only want it to appear when the user clicks on the triangle to expand it.

The loading container will be set to appear at the center of the page, with just a little bit more to the top since we have the thumbnails bar appearing sometimes. Setting top to 40% gives us what we need:

#loading{
    display:none;
    width:50px;
    height:50px;
    position:absolute;
    top:40%;
    left:50%;
    margin-left:-24px;
    background:transparent url(../icons/loading.gif) no-repeat top left;
}

To make the thumbs bar scrollable by moving the mouse we need to give it a special style. The thumbsWrapper will be positioned absolutely and occupy the width of the window. We set the vertical overflow to hidden because we don’t want any scroll bar to appear on the right.
The horizontal overflow will be managed in the JavaScript (it will be hidden).

#thumbsWrapper{
    position: absolute;
    width:100%;
    height:102px;
    overflow-y:hidden;
    background-color:#000;
    bottom:0px;
    left:0px;
    border-top:2px solid #000;
}

The thumbsContainer will be the inner div that will have a width equal to the sum of all the thumbnail widths. We will calculate the width dynamically in the JavaScript, so we don’t define it in the class:

#thumbsContainer{
    height:79px;
    display:block;
    margin: 0;
}

The thumbnail images will have the following style:

#thumbsWrapper img{
    float:left;
    margin:2px;
    display:block;
    cursor:pointer;
    opacity:0.4;
    filter:progid:DXImageTransform.Microsoft.Alpha(opacity=40);
}

We give them a low opacity value since we want to add a hover effect.

The imageWrapper that contains the full image has the following style:

#imageWrapper{
    position:relative;
    text-align:center;
    padding-top:30px;
}

We add a top padding because we have the album bar at the top of the page. We don’t want the image to get hidden by it. The margin 0 auto will center the image horizontally:

#imageWrapper img{
    margin:0 auto;
    -moz-box-shadow:2px 2px 10px #111;
    -webkit-box-shadow:2px 2px 10px #111;
    box-shadow:2px 2px 10px #111;
}

We also create a neat box shadow for all modern browsers 🙂
Some of you might wonder why we set text-align center in the imageWrapper if we have the margin in the image. When we make things appear with the fadeIn function in jQuery, the display of the respective element becomes “block”. For that case our “margin:0 auto” will center the image. But for the case when we put the first image initially we need the inline centering property which is to give the parent “text-align:center”.

And finally, we define the classes for the different cursor types:

.cursorRight{
.cursorRight{
    cursor:url("../icons/next.cur"), url("icons/next.cur"), default;
}
.cursorLeft{
    cursor:url("../icons/prev.cur"), url("icons/prev.cur"),  default;
}
.cursorPlus{
    cursor:url("../icons/plus.cur"), url("icons/plus.cur"), default;
}
.cursorMinus{
    cursor:url("../icons/minus.cur"), url("icons/minus.cur"), default;
}

OK, this is basically a hack and not really nice, but the reason for this ugliness is the browsers’ handling. The first url is the path for FireFox, the second one is for IE and the default value needs to be there again for Firefox. Read more about custom cursors and cross-browser compatibility here.

Now, let’s get to the JavaScript.

The JavaScript

Let’s go step by step through the jQuery code. I will not follow the order like it is in the script but by the usage of the functions. I hope that it will be easier to understand like that.
In our $(function() { } we will add the following JavaScript:

/* name of the selected album, in the top right combo box */
    var album	= $('#albumSelect div').html();
    /* mode is small or expanded, depending on the picture size  */
    var mode = 'small';
    /* this is the index of the last clicked picture */
    var current = 0;

So, we will first declare some variables that we will need later and then we call:

 buildThumbs();

The buildThumbs() function is going to get the current album and generate the images with the accoring source and information:

function buildThumbs(){
	current=1;
	$('#imageWrapper').empty();
	$('#loading').show();
	$.get('ajax/thumbs.php?album='+album, function(data) {
		var countImages = data.length;
		var count = 0;
		var $tContainer = $('<div/>',{
			id	: 'thumbsContainer',
			style	: 'visibility:hidden;'
		})
		for(var i = 0; i < countImages; ++i){
			try{
				var description = data[i].desc[0];
			}catch(e){
				description='';
			}
			if(description==undefined)
				description='';
			$('<img title="'+description+'" alt="'+data[i].alt+'" height="75" />').load(function(){
				var $this = $(this);
				$tContainer.append($this);
				++count;
				if(count==1){
					/* load 1 image into container*/
					$('<img id="displayed" style="display:block;" class="cursorPlus"/>').load(function(){
						var $first = $(this);
						$('#loading').hide();
						resize($first,0);
						$('#imageWrapper').append($first);
						$('#description').html($this.attr('title'));
					}).attr('src',$this.attr('alt'));
				}
				if(count == countImages){
					$('#thumbsWrapper').empty().append($tContainer);
					thumbsDim($tContainer);
					makeScrollable($('#thumbsWrapper'),$tContainer,15);
				}
			}).attr('src',data[i].src);
		}
	},'json');
}

As we mentioned before, we will be using the thumbs.php file to get the info we need. When we are done building all the thumb images we append it to the thumbsWrapper and determine the size of the container with thumbsDim (line 36):

/* adjust the size (width) of the scrollable container
- this depends on all its images widths
*/
function thumbsDim($elem){
	var finalW = 0;
	$elem.find('img').each(function(i){
		var $img 		= $(this);
		finalW+=$img.width()+5;
	//plus 5 -> 4 margins + 1 to avoid rounded calculations
	});
	$elem.css('width',finalW+'px').css('visibility','visible');
}

Then we use makeScrollable (line 37) to make the thumbnail container scrollable by mouse move:

//Get our elements for faster access and set overlay width
function makeScrollable($wrapper, $container, contPadding){
	//Get menu width
	var divWidth = $wrapper.width();

	//Remove scrollbars
	$wrapper.css({
		overflow: 'hidden'
	});

	//Find last image container
	var lastLi = $container.find('img:last-child');
	$wrapper.scrollLeft(0);
	//When user move mouse over menu
	$wrapper.unbind('mousemove').bind('mousemove',function(e){

		//As images are loaded ul width increases,
		//so we recalculate it each time
		var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + contPadding;

		var left = (e.pageX - $wrapper.offset().left) * (ulWidth-divWidth) / divWidth;
		$wrapper.scrollLeft(left);
	});
}

The following function takes care of the click event on a thumbnail and also the hover event:

/*
clicking on a thumb loads the image
(alt attribute of the thumb is the source of the large image);
mouseover and mouseout for a nice spotlight hover effect
*/
$('#thumbsContainer img').live('click',function(){
	loadPhoto($(this),'cursorPlus');
}).live('mouseover',function(){
	var $this   = $(this);
	$this.stop().animate({
		'opacity':'1.0'
	},200);
}).live('mouseout',function(){
	var $this   = $(this);
	$this.stop().animate({
		'opacity':'0.4'
	},200);
});

When a thumbnail is clicked we call the function loadPhoto (and we also pass the current cursor mode):

/*
loads a picture into the imageWrapper
the image source is in the thumb's alt attribute
*/
function loadPhoto($thumb,cursorClass){
	current		= $thumb.index()+1;
	$('#imageWrapper').empty();
	$('#loading').show();
	$('<img id="displayed" title="'+$thumb.attr('title')+'" class="'+cursorClass+'" style="display:none;"/>').load(function(){
		var $this = $(this);
		$('#loading').hide();
		resize($this,0);
		if(!$('#imageWrapper').find('img').length){
                  $('#imageWrapper').append($this.fadeIn(1000));
                  $('#description').html($this.attr('title'));
            }
	}).attr('src',$thumb.attr('alt'));
}

When want to adapt the size of the picture when we resize the window:

/* when resizing the window resize the picture */
$(window).bind('resize', function() {
	resize($('#displayed'),0);
});

The resize function is defined as follows:

/* function to resize an image based on the windows width and height */
function resize($image, type){
	var widthMargin     = 10
	var heightMargin    = 0;
	if(mode=='expanded')
		heightMargin = 60;
	else if(mode=='small')
		heightMargin = 150;
	//type 1 is animate, type 0 is normal
	var windowH      = $(window).height()-heightMargin;
	var windowW      = $(window).width()-widthMargin;
	var theImage     = new Image();
	theImage.src     = $image.attr("src");
	var imgwidth     = theImage.width;
	var imgheight    = theImage.height;

	if((imgwidth > windowW)||(imgheight > windowH)){
		if(imgwidth > imgheight){
			var newwidth = windowW;
			var ratio = imgwidth / windowW;
			var newheight = imgheight / ratio;
			theImage.height = newheight;
			theImage.width= newwidth;
			if(newheight>windowH){
				var newnewheight = windowH;
				var newratio = newheight/windowH;
				var newnewwidth =newwidth/newratio;
				theImage.width = newnewwidth;
				theImage.height= newnewheight;
			}
		}
		else{
			var newheight = windowH;
			var ratio = imgheight / windowH;
			var newwidth = imgwidth / ratio;
			theImage.height = newheight;
			theImage.width= newwidth;
			if(newwidth>windowW){
				var newnewwidth = windowW;
				var newratio = newwidth/windowW;
				var newnewheight =newheight/newratio;
				theImage.height = newnewheight;
				theImage.width= newnewwidth;
			}
		}
	}
	if((type==1)&&(!$.browser.msie))
		$image.stop(true).animate({
			'width':theImage.width+'px',
			'height':theImage.height+'px'
			},1000);
	else
		$image.css({
			'width':theImage.width+'px',
			'height':theImage.height+'px'
			});
}

The heightMargin depends on the mode we are in: if the thumbnails bar is out, we have less space so we reduce the allowed height of the image.

The following functions take care of what happens when we select an album:

/* Album combo events to open, close,
and select an album from the combo
*/
$('#albumSelect div').bind('click',function(){
	var $this = $(this);
	if($this.is('.up'))
		closeAlbumCombo();
	else if($this.is('.down'))
		openAlbumCombo();
});
$('#albumSelect ul > li').bind('click',function(){
	var $this 	= $(this);
	album 		= $this.find('a').html();
	buildThumbs();
	var $combo = $('#albumSelect div');
	$this.find('a').html($combo.html());
	$combo.html(album);
	closeAlbumCombo();
	orderCombo($this.parent());
});

And these are the three functions taking care of our self made combo box:

//functions to control the albums combos
function closeAlbumCombo(){
	var $combo = $('#albumSelect div');
	$combo.addClass('down').removeClass('up');
	$combo.prev().hide();
}
function openAlbumCombo(){
	var $combo = $('#albumSelect div');
	$combo.addClass('up').removeClass('down');
	$combo.prev().show();
}
function orderCombo($ul){
	var items = $ul.find('li').get();
	items.sort(function(a,b){
		var keyA = $(a).text();
		var keyB = $(b).text();

		if (keyA < keyB) return -1;
		if (keyA > keyB) return 1;
		return 0;
	});
	$.each(items, function(i, li){
		$ul.append(li);
	});
}

Now we define what happens when we hover over the main image or when we click on it. Depending on where we hover over the image, we want a certain cursor to appear. For that we check where we are with the mouse and apply the regarding class to the image:

/*
when hovering the main image change the mouse icons (left,right,plus,minus)
also when clicking on the image, expand it or make it smaller depending on the mode
*/
$('#displayed').live('mousemove',function(e){
	var $this 	= $(this);
	var imageWidth 	= parseFloat($this.css('width'),10);

	var x = e.pageX - $this.offset().left;
	if(x<(imageWidth/3))
		$this.addClass('cursorLeft')
			 .removeClass('cursorPlus cursorRight cursorMinus');
	else if(x>(2*(imageWidth/3)))
		$this.addClass('cursorRight')
			 .removeClass('cursorPlus cursorLeft cursorMinus');
	else{
		if(mode=='expanded'){
			$this.addClass('cursorMinus')
				 .removeClass('cursorLeft cursorRight cursorPlus');
		}
		else if(mode=='small'){
			$this.addClass('cursorPlus')
				 .removeClass('cursorLeft cursorRight cursorMinus');
		}
	}
}).live('click',function(){
	var $this = $(this);
	if(mode=='expanded' && $this.is('.cursorMinus')){
		mode='small';
		$this.addClass('cursorPlus')
			 .removeClass('cursorLeft cursorRight cursorMinus');
		$('#thumbsWrapper').stop().animate({
			'bottom':'0px'
		},300);
		resize($this,1);
	}
	else if(mode=='small' && $this.is('.cursorPlus')){
		mode='expanded';
		$this.addClass('cursorMinus')
			 .removeClass('cursorLeft cursorRight cursorPlus');
		$('#thumbsWrapper').stop().animate({
			'bottom':'-85px'
		},300);
		resize($this,1);
	}
	else if($this.is('.cursorRight')){
		var $thumb = $('#thumbsContainer img:nth-child('+parseInt(current+1)+')');
		if($thumb.length){
			++current;
			loadPhoto($thumb,'cursorRight');
		}
	}
	else if($this.is('.cursorLeft')){
		var $thumb = $('#thumbsContainer img:nth-child('+parseInt(current-1)+')');
		if($thumb.length){
			--current;
			loadPhoto($thumb,'cursorLeft');
		}
	}
});

When we click on the image, we check which cursor we had, because like that we know which image we have to display next (i.e. the next or the previous one). Our “current” variable helps us keep track of which picture we are currently viewing.

And that’s it! I hope you enjoyed this gigantic tutorial!

Note that in this demo we don’t use very big images, so the “zoom in”/ resize will just show you the full image maximum and never resize the picture beyond its real dimensions. If you use very large images the effect will be a nice experience for users with a large screen.

We also have a static version of this photo gallery without the album functionality. Check out the static demo or download the ZIP file.

We created a mobile version of this gallery: Awesome Mobile Image Gallery Web App

Message from TestkingJoin our online testking N10-004 web designing course to learn how to improve your website using PHP and jQuery. Download testking 70-640 tutorial and testking 220-701 design guide to learn how to create fresh sliding thumbnails gallery with jquery.

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 142

Comments are closed.
  1. Thank you! I’ve been waiting for something like this since the “Single File PHP Gallery” (http://sye.dk/sfpg/) is soooo ugly and the license makes you pay if you want to pretty it up.

    So thank you! But one request, could you make it so if the thumbs don’t exist they’ll be automatically created? SFPG employs this method, so I may try to use that and submit my changes back to you. But you guys are the experts.

    • @Shai Thank you so much for your feedback! Automatic thumbnail creation would be superb, we’ll consider it for one of our future tutorials! Cheers, ML

  2. Looking again at SFPG it’s actually not auto creating thumbs. My guess is because that would put certain requirements on the server (GD, ImageMagik) that not everyone has.

    Instead what it appears to be doing is just taking the full size image and resizing it in the browser for the preview. This seems like a no brainer and would be an easy thing to do. I’m going to try to add this to your code and see if I can get it to work and post back.

  3. That wasn’t hard after all. Not sure if it’s the proper way. But adding the following snippet else statement to the thumbs.php makes it so you no longer have to create that thumbs directory.

    You still have to create it if your going to use the desc.xml file. So that’s my next challenge. If no desc.xml exists, then create it in the thumbs folder with the proper structure, file names filled, and empty descriptions.

    Here’s the php else snippet mentioned above:
    http://pastie.org/976376

  4. Sorry for the duplicate posts. I’ve modified the thumbs.php to include my previous mod, no thumb folder required, and now when thumbs.db loads it will check for a thumbs folder for that album, if it doesn’t exist, it will create it and build a dummy desc.xml file with the proper folder names and structure (the spacing in the created .xml file is wonky, and I don’t want to spend all day playing with spacing, but it still works). The benefit is that now you only need to upload a folder with pictures into the /images folder, visit the newly created album, then go back and fill in the dummy desc.xml with descriptions.

    For simplicity you could use a php xml editor, but I think thats a bit overkill.

    So here’s my modded thumbs.php file: pastie.org/976466

    Thank’s again to the creators of this tutorial, without them none of this would be possible!

  5. Again, so sorry for multiple posts but I’ve managed to setup resizing on the server.

    Using my first idea of just html resizing the images works, but, when you have an album with 10 1mg files, that means that just to load the thumbstrip you’d have to download all 10 images at there full size, and the browser would resize them. That took too long. So using the timthumb project code.google.com/p/timthumb/ and one more php file, all the resizing, caching is done on the fly each time a new album is loaded.

    The preferred way would be to eliminate the caching and have the thumbs saved to the thumbs folder. But this works and I’m lazy. I also changed the tumbs.php logic so that if you have loaded some custom thumbnails into the thumbs/albumXYZ folder, and you later add new images to images/albumXYZ but forget to create the thumbnails (or are lazy like me), those new thumbnails will be created and cached on the fly by timthumb.

    So:
    1. replace the entire contents of ajax/thumbs.php with http://pastie.org/977106
    2. Download and save timthumb from its source @ http://timthumb.googlecode.com/svn/trunk/timthumb.php (version as of this writing is 1.14)

    You can change my settings in thumbs.php to whatever you like. But I found q=40 & w=100 to yield the smallest and still good looking images (avg is ~2K!).

    Again, sorry to the original devs for post jacking, just wanted to contribute back. Thank you again!

  6. Thanks for sharing !!

    You had Given me a good Idea !

    thanks Again

    ~Avinash

  7. Thanks for this great tutorial and nice script !!!

    I’ve use it for my photography portfolio : http://www.vp-photographie.fr

    I’ve changed CSS to have my own style.
    I’m not still modified script (shai modifications) But may be later !

    Great thank to author and Shai !!

  8. @Vincent That is truly beautiful! I love the background and the mouse cursors!! I am really glad that you are using this 🙂

  9. @Mary Lou
    Thank you so much !
    I’ve just add your copyright and the link to this tutorial

  10. @Vincent
    That’s very nice of you! Thank you! But you don’t have to, you know 🙂 We like more Copyleft 😉
    Oh, I really love the way the background structure imprints on the image when it fades, phénoménal!

  11. @Mary Lou, thank you for putting this together. I’ve managed to add youtube support, but it’s not quite finished and I need some help with the JS as I know 0 about JS.

    my new thumbs.php http://pastie.org/982035

    The way I have it working is if you put a jbSsoqdefOA.youtube file in the images/albumABC directory, the php will pull the video ID and use that for the thumbnail and the link to the video. Currently, I’m just passing the JS the link to the video’s high quality image. Passing the normal youtube link doesn’t work and causes the spinning wheel of death. My guess is the JS doesn’t know what to do with the video link.

    Would be best to pass the video ID as the alt in $imagesArr, and have the JS create the embed code.

    If you have thums/albumABC you have to put that same jbSsoqdefOA.youtube file in that folder to.

    Anyone willing to help out on this?

  12. Is there a way to add in keyboard support, say for left and right keys to move to the next image?

    Thanks again for such a wonderful bit of code!

  13. Great Post. Can we improve this with a flickr fetch segment. that is I can display my flickr photostream or a public tag result. Any way this is a Great post. Thanks for share.

    • That is a very good suggestion! We’ll sure make a tutorial including that! Thanks for you feedback, cheers, ML

  14. Hey, just a suggestion !
    It’ll be excelent to add a Ajax rating system and (or) comments system,
    like a blog ! It’s possible to add this !

  15. There’s lots of star/rating plugins for jquery one could use. Using some Ajax calls, you could retrieve the rating value or set it. Here is a complete (although a bit difficult to follow) example.
    http://www.yvoschaap.com/weblog/css_star_rater_ajax_version/

    I’m sure with minimal time this could be integrated. I believe any PHP code here, should be added to the thumbs.php in order to get this working. Hope that helps.

  16. I downloaded the script but my first album does not appear as default. In the select box appears DS_Store.
    Can anyone help me? Tks from Brazil

  17. @Shai Perednik

    Thanks 🙂 I would like to add rating system in “title”
    I think it’s possible 😉
    I’ll try to add this !!!

  18. This is a very complete gallery. I’d love to see the star rating and youtube vids working in this as well.

  19. i wanna use this amazing Gallery into my wordpress template and, put it on my home page.

    MY Question :

    how can i add the specific link for each image in the Xml ?
    and get every specific link fuction
    from the XML,

    but i am a noob

    And I very much want your help,
    i anticipate hearing from you.

  20. @ivanking What exactly are you planning? Do you want to wrap a link element around the full image? If so, you would have to change a lot of things, not only the reading of the XML file… Let me know, cheers, ML

  21. Kind Mary Lou:

    Yes ,that’s exactly what do i mean,

    i wanna wrap the link element for every full image,

    you know ,
    a gallery just can show
    you the full pictures is not enough any more if i wanna put the amazing Gallery on the homepage.

    i need using the full image for a web link to another page(Picture Links for the posts )

    but i am really a noob ,

    just konwing that maybe i have to write some code in the php
    so that the php can read the link information from the XML
    and when i click the full picture,
    i can open the target link page.
    (i guess that js ,php ,xml all need modify.)

    can u give me some direction ?,Anyway,thank U so Much!

  22. How can I get the thumbnails to scroll vertically? Can I do this within the CSS?

  23. buen trabajo sigan adelante, todos sus tutoriales estan very nice……
    saludos

  24. Hello,

    Thanks for sharing nice tutorial. But I have a request, my site hosted in windows platform, so I’m unable to use this(PHP) for my site. Can I have same gallery script for HTML file??

    Thanks in advance.

  25. Hello,

    I would like to try this great script and i unzip it on my website but…

    an error was displayed and it doesn’t work…

    “Message : ‘null’ a la valeur Null ou n’est pas un objet.
    Ligne : 137
    Caractère : 17
    Code : 0
    URI : http://www.euromen.es/shop/albums/jquery.gallery.js

    could you help me ?

    Really thanks
    Stefan

  26. Hello, I tried to add a keynav navigation, but it doesn’t work.
    Help me ! 😉

    $(document).keydown(function(e) {
    switch(e.keyCode) {
    // User pressed “right” arrow
    case 39:
    return $(‘#imageWrapper’).cursorRight();
    break;
    // User pressed “LEFT” arrow
    case 37:
    return $(‘#imageWrapper’).cursorLeft();
    break;

    }
    });

  27. Hello

    I’am african … Thanks you so much for all the inspiration you are giving me through all your tutorials … I have a trouble using Fresh Sliding Thumbnails Gallery with google chrome only few thumbnails can be seen when the page is loaded … thx for helping me (*_*)

  28. Thanks, this is a great gallery.

    Is it some how possibel to set a link (URL) direct to some specific album?

  29. i cannot figure out the vertical scroll on the thumbnail, where in the JavaScript do i modify. Someone please help, time is against me.

  30. Having problems just downloading and putting on my site. No images and thumbs appear. Could it be the PHP 4.4.9? or do I have to set links to the PHP path?

  31. Another question, is it easy to control the menu, I need the names of the gallery rather than album1, starting with recent, then personal, not alphabetical?

    Can the thumbnail part be eliminated all together? Just click to the next photo or back? Appreciate any help on this, thanks.

  32. how to add my images? if i add image and edit xml the gallery diesn’t work. even if i delete any image it doesn’t work how should i add my images and galleries?

  33. Hi David,

    I got the same problem as you which has no images and thumbs appear.

    I have downloaded and installed the PHP 5 (VC9 x86), but still nothing happen. Could you please explain it to me on how you got it work?

    Many Thanks in Advance.

  34. i’ve found the problem. the problem was that i was testing the script on my local server? and when i enter folder thumbs my windows creates file inside the folder thumbs.db, because of this file was crash of the script, now everything works well

  35. Mustafa, just switching to php 5 is all I did and worked fine. I guess double check to make sure that only php 5 is used now on your server.