Hi peeps,
I wonder if anybody can give me a hand with this. Basically on my website http://antobbo.webspace.virginmedia.com/photography/testing/gloom.htm to view a picture you need to use the left hand-side menu. Now, all good except that when you want to view any picture at the bottom of the left hadn-side nav you need to scroll all the way down, losing the main picture and then you need to scroll all the way up again. So I was thinking to have a next button which will have the same function as the left hand-side navigation. I thought it would have ben easy but it's now 10 hours I am working on it and I really don't seem to be able to get anywhere. I tried many conbinations, here's some of the attempts:
1) I created the button:

<div class="next_button"><!-- NEXT BUTTON-->
<a href="javascript:void(0);" onClick="nextPicture()">Next</a>
</div><!-- END OF NEXT BUTTON -->

then the script:

<script type="text/javascript">
<!--
/*NEXT PICTURE */
$(document).ready(function()
{
var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

mainPictures.current = 0;
thumbPictures = 0;
thumbShadedPictures = 0;

function nextPicture()
{
$("pic_1").fadeOut(2000, function()
{
$(this).attr('src',mainPictures[1]).fadeIn(2000)

});
}
});
//-->
</head>

Let me explain what I was attempting to do. I created 3 arrays mainPictures, thumbPictures and thumbShadedPictures because when I click on a thumbnail on the left the big picture in the middle changes and the thumbnail becomes shaded. Then when I click on a another thumbnail, the previous one goes back to normal and the selected one turns shaded and so on, hope it is clear. So what I want to do with the arrays is to make sure that all that happens.
So in function nextPicture() I grabbed the id pic_1 which is referenced in the body of the page

<img src="images/gloom_full_1.jpg" alt="" id="pic_1">

that didn't work
2)after few hours I came up with this, managing to at least fading out the main picture:

<script type="text/javascript">
<!--
/*NEXT PICTURE */
function nextPicture()
{
var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

var current_picture = 1;

mainPictures.current = 0;
thumbPictures = 0;
thumbShadedPictures = 0;
var current_picture = 1;

$("#pic_1").fadeOut(2000, function()
{
while(current_picture<mainPicture.length)
{
$("#pic_1").attr('src',mainPictures[current_picture]).fadeIn(2000);
}
current_picture++;
});
}

3) then I finally got to a point where I managed ot fade the main pix away and fade in the next one:

<script type="text/javascript">
<!--
/*NEXT PICTURE */
function nextPicture()
{
var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

mainPictures.current = 0;
thumbPictures = 0;
thumbShadedPictures = 0;
var current_picture = 0;
	current_picture++;
		mainPictures.current = current_picture;

changePix();


function changePix()

	{

		$("#pic_1").fadeOut(2000, function()
			{
				$(this).attr('src',mainPictures[current_picture]).fadeIn(2000);

			});

	}
}
//-->
</script>

</script>

The problem here is that I can only change the first 2 pictures because I don't seem to be able to assign to pic_1 the subsequent values in the mainPictures array

I can go on for quite a bit, but I will post only the last attempt which didn't use arrays:

4)

<script type="text/javascript">
<!--
/*NEXT PICTURE */



function nextPicture()
{


var change_picture = "images/gloom_full_2.jpg";


changePix();


function changePix()

	{

		$("#pic_1").fadeOut(2000, function()
			{
				$(this).attr('src',change_picture).fadeIn(2000);

			});

	}
}

It works but again I can only change the first 2 pictures I am not sure how to do the same thing with the rest of them (27). Let's not forget that I also have to changes the thumbnails because I need to keep the same functionality as the left hadn-side navigation. After 10 hrs I am losing it sorry, can't think straight anymore. Can anybody suggest anything?
thanks a lot

Recommended Answers

All 13 Replies

Hi Violet,

There's no point driving yourself nuts writing something like this.

Slideshows is one area that is seriously well supported with jQuery plugins, most of which would do the job far better than you or I could ever achieve in a reasonable timescale.

I just googled "jquery slideshow plugin" and found these review pages (I'm sure there must be others):

Of those I looked at, I thought Galleria would probably suit your material best. It would inherently resolve the issue you have with scrolling albeit at the cost of your current page layout (it has its own way of displaying/scrolling thumbnails). It's a cool, professional looking plugin and I really think your time would be better invested in installing it (or some other plugin if you prefer) rather than pursuing a DIY approach.

Airshow

Hi Airshow,
thanks for that. I know what you mean and yes in a way I agree with you. Problem is I need to put this website on my cv to prove that I have some basic jquery and javascript skills, so if I use a jquery plug in, well, I can't prove much. IN an ordinary situation I would use it but I need to try to do as much as I can myself. I didn't know that adding a next button would have proved that dificult : - )!
The irony here is that if I don't add that button I could create some usability issues because users with small screens (like the one I am using now on a samsung nc10) will have to scroll up and down in order to view the pictures at the bottom of the left hand-side navigation, so I am in a bit of a dilemma: forget about the next button and leave that little usability issue unresolved or use a jquery plug in, solve the usability issue but not being able to prove that I have a basic understanding of how jquery works...

Hi Violet82,

This should be what you're looking for.

// load images
var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

// counter
var currentImage = 0;

// set picture to be 1st element in array (gloom_full_1.jpg)
$("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);

function nextPicture(){
	$("#pic_1").fadeOut(2000, function(){
		$(this).attr("src", mainPictures[++currentImage]).fadeIn(2000);
	});
}

Hi floatingDivs,
thanks for that, I had a look earlier on and yes the code works (this afternoon I had the impression that it wasn't working on my small laptop - sometimes it is a bit temperamental which is probably why).
I had a good look at your code and I didn't know that I could use variables outside the function, I thought that everything had to be in a funcion, and that's why I couldn't get my darn script to work. In my previous attempts I couldn't change the value of

currentImage

because it was in side the function and it had always the same value everytime the function was called.
I attempted to slightly modify your script to make sure that when users click on the "next" button gets to the last picture the first picture kicks in again but it doesn't seem to be working:

// load images
   
      var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
   
      var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
   
      var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];
   
       
   
      // counter
   
      var currentImage = 0;
   
       
   
      // set picture to be 1st element in array (gloom_full_1.jpg)
  
      $("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);
  
      
  
      function nextPicture(){
      
      if(currentImage<=27)
       {

  
      $("#pic_1").fadeOut(2000, function(){
  
      $(this).attr("src", mainPictures[++currentImage]).fadeIn(2000);
  
      });
      
        }
       else
        {

  	currentImage=0;
	 $("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);
	}

      }

http://antobbo.webspace.virginmedia.com/photography/testing/gloom.htm

However, more important than that is this: do you think that the "next" button should have exactly the same functionality that the left hand-side nav has? In other words should I make sure than when users click on the next buttons even the thumbnails change accordingly (same way as they change when using the navigation)?

I had a quick stab at it and I attempted to change only the first thumbnail in the navigation and it works but then I realized that this is not the way to do it because the following will change only the first thumbnail and not the other ones (the id thumbnail_1 represents just the first thumbnail image and each image thumb has a different id, so 27 different id's):

var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
   
      var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
   
      var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

var currentImage=0;
var currentThumbImage=0;
var currentThumbShadImage=0;
	
$("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);
function nextPicture()
{
$("#pic_1").fadeOut(2000,function(){
	$(this).attr("src",mainPictures[++currentImage]).fadeIn(function(){
		$("#thumbnail_1").attr('src',thumbPictures[currentThumbImage]).fadeIn(2000);

		});
	});
}

Fundamentally I have to find a way to increase the number of that #thumbnail_1 each time the function runs as well as increase thumbPictures[currentThumbImage] - for this is fine I can do what you've done in your example thumbPictures[++currentThumbImage] What do you think, is it worth the effort?
thanks

An array starts at 0, not 1. So, you need to calculate from 0 to whatever the last element in your array is (you actually don't...read below to find out how to save yourself time). Even though the image is gloom_full_27.jpg, the array index is 26. Remember, gloom_full_1.jpg is located at element 0, not element 1. So, what the function nextPicture was doing is this; it compared the currentImage variable value (0-xx) against the hard-coded integer 27 (which we also remove...explained below). The problem is, your array has 26 (0-26, not 1-27) elements! I'm guessing that broke your code since the array went out of bounds (past its last element).

Also, hard-coding an array length is inefficient and not necessary. What if you add 3 more images but forget to change that value from 26 (remember where arrays start!) to 29? You've added those images, but they won't show! Thankfully, JS has a length function built into it's language. So, instead of needing to change that value manually any time you add/remove pictures from your array, you simply place the array's length as the comparison in favor of the hard-coded integer.

array mainPictures has 26 elements. Instead of writing 26 in the IF statement in function nextPicture, write mainPictures.array. You'll see what I mean when you view the code. :D

I'm betting you were seeing no image when you clicked the NextPicture link the 28th time. :P I'm GUESSING the function broke your page and it didn't revert back to 0.

Try the code I paste below and let me know if it works for ya!

// load images
var mainPictures = ["images/gloom_full_1.jpg", "images/gloom_full_2.jpg", ... "images/gloom_full_27.jpg" ];
var thumbPictures = ["images/gloom_thumb_1.jpg", ... "images/gloom_thumb_27.jpg"];
var thumbShadedPictures = ["images/gloom_thumb_shad_1.jpg"... "images/gloom_thumb_shad_27.jpg"];

// counter
var currentImage = 0;

// set picture to be 1st element in array (gloom_full_1.jpg)
$("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);

function nextPicture() {
	// if(currentImage <= 27) {
	if(currentImage < mainPictures.length) { // this way you don't need to update this if statement if you add new pictures
		$("#pic_1").fadeOut(2000, function() {
			$(this).attr("src", mainPictures[++currentImage]).fadeIn(2000);
		});
	} else {
		currentImage = 0;
		$("#pic_1").attr('src',mainPictures[currentImage]).fadeIn(2000);
	}
}

Violet,

Hi Airshow,
thanks for that. I know what you mean and yes in a way I agree with you. Problem is I need to put this website on my cv to prove that I have some basic jquery and javascript skills, so if I use a jquery plug in, well, I can't prove much. IN an ordinary situation I would use it but I need to try to do as much as I can myself. I didn't know that adding a next button would have proved that dificult : - )!
The irony here is that if I don't add that button I could create some usability issues because users with small screens (like the one I am using now on a samsung nc10) will have to scroll up and down in order to view the pictures at the bottom of the left hand-side navigation, so I am in a bit of a dilemma: forget about the next button and leave that little usability issue unresolved or use a jquery plug in, solve the usability issue but not being able to prove that I have a basic understanding of how jquery works...

OK, I understand.

One of the benefits of jQuery is its ability to address multiple DOM elements with a single statement.

I have just looked at your page's source. At over 2500 lines, your javascript is somewhat voluminous. By taking advantage of jQuery's power and having just one generalized click handler for all the thumbnails, I reckon that your application would simplify to no more than about 20 lines of javascript. Even if it came down to 50 or 100 lines that would be a significant reduction. The HTML would also simplify.

Trouble is, it would be such a major departure from what you currently have, I would find it virtually impossible to talk you through the simplification process. I could only hope to write it for you, which is not what you want.

Airshow

Hi floatingDivs, thanks for the explanation, yes it makes sense, I should have thought about the out of bound problem. I replaced the if statement with the suggested one although it still doesn't work, when I get to the end of the pictures it skips the first picture (it's like the picture is missing, there is just the black background) and when I click next again it jumps to the second picture. Is it because we are saying in the code

$(this).attr("src",mainPictures[++currentImage]).fadeIn(2000);

effectively skipping the first element of

mainPictures[currentImage]

because of the

++

? http://antobbo.webspace.virginmedia.com/photography/testing/gloom.htm
Also on a different note, what do you think (and what do you guys think) of the second half of my original question,

do you think that the "next" button should have exactly the same functionality that the left hand-side nav has? In other words should I make sure than when users click on the next buttons even the thumbnails change accordingly (same way as they change when using the navigation)?

. Do you think it is doable or is it too complicated due to the nature of my clunky script? I had been thinking about that - there is a quick attempt in one of my previous replies above - and what I need to do is to try to increase thumbnail_1 which is the id of the thumbnails pictures in the navigation and change it accordingly to "shaded" and "normal". It is quite different from what we have done to pic_1 which was only 1 id, here instead I have 27 so I presume I have to copy them all into possibly an array and then take it from there. What do you think? Is it worth or not considering that users can have that functionality if they use the navigation menu, so if they instead choose to use the "next" button it might not be necessary...

@ Airshow:
Thanks Airshow, I know what you mean my script is clunky and simply unmanageable although I didn't know it was that long! I think I will leave it as it is but lesson learned, in that next time I will have to use that sort of functionality (and it will be soon because I need to do another similar photography website where I can dump all the GB of pix that I don't use) I will ask for advice beforeI start the script so that I can avoid such a bulky thing, thanks for your help

Violet,

For the record, I struggled to keep it down to my predicted 20 lines, but eventually managed to squeeze everything into 19, including both Next and Prev buttons. For readability, I would normally choose not to squeeze quite this far.

$(function(){
	var current = -1;
	var $thumbs = $(".gloom_thumbnails_wrapper img");
	var $pic_1 = $("#pic_1").hide().load(function(){ $pic_1.fadeIn(1000); });//This way, image is guarnateed to have loaded before fadein starts. Avoids possible nasty visual glitch.
	$thumbs.each(function(i){
		$(this).data({i:i}).click(function(){
			var $this = $(this), i = $this.data('i');
			$thumbs.eq(current).attr('src', 'images/gloom_thumb_%.jpg'.replace("%", current+1));//reset style of last thumbnail image
			$this.attr('src', 'images/gloom_thumb_shad_%.jpg'.replace("%", i+1));//set style of this thmbnail
			$pic_1.stop(true,true).fadeOut(1000, function(){ $pic_1.attr("src", 'images/gloom_full_%.jpg'.replace("%", i+1)); });//clear animation queue and force current fade to complete, then faade out and set new src on completion.
			current = i;//remember which image is current
		});
	});
	$(".next_button a").eq(0).click(function(){
		$thumbs.eq( ((current==0)?$thumbs.length:current)-1 ).trigger('click');//simulate click on prev thumbnail (with wraparound).
	}).end().eq(1).click(function(){
		$thumbs.eq((current + 1) % $thumbs.length).trigger('click');//simulate click on next thumbnail (with wraparound).
	}).click();// .click() initialises photo to first thumbnail.
});

There are some associated changes to the HTML, chiefly to reduce all thumbnails to:

<li><img src="images/gloom_thumb_1.jpg" alt=" " /></li>

and change the "next_button" div to :

<div class="next_button"><a>Prev</a>&nbsp;&nbsp;&nbsp;&nbsp;<a>Next</a></div>

and the "category_pictures" div to :

<div class="category_pictures"><img src="" alt="" id="pic_1"></div>

The code relies on the fact that your image names are all rule-based, ie they can be worked out from the index of the thumbnail. A slightly different approach would be necessary if each image name was unique.

Airshow

Appears to work for me now.

function nextPicture() {
				currentImage = currentImage + 1;
				
				if(currentImage < mainPictures.length) {
					$("#pic_1").fadeOut(2000, function() {
						$(this).attr("src",mainPictures[currentImage]).fadeIn(2000);
					});
				} else {
					currentImage = 0;
					$("#pic_1").attr('src',mainPictures[0]).fadeIn(2000);
				}
				
				alert(currentImage);
			}

HifloatingDivs,
thanks for that but I had to remove the alert box in some browsers (chrome, safari, opera) comes up everytime I click on the next button. If I remove it it is ok although the first picture doesn't fade in smoothly, but it is fine, thanks for all your help

@Airshow Wow Airshow, that is amazing, thanks for posting that. It is a little bit too advanced for me but I definitely want to give it a try to understand it first and then try it on the site.
I spent sometime studying it, googling (actually w3c schooling) but many things are still unclear. Would you mind if I go through line by line with you just to make sure that
I understand what's going on and clarify what's not clear? Hope you don't mind that

First thing, this script can then replace all that awfully long script of mine I seem to understand. Now is it replacing every function as in, will your function be called directly from my code?
You said all the thumbnails should be replaced by <li><img src="images/gloom_thumb_1.jpg" alt=" " /></li> but where do I call your function from?

Let's get to the script now:

$(function(){ //I suppose I can give it a name or should it remain as it is?
   
var current = -1; 
  
var $thumbs = $(".gloom_thumbnails_wrapper img"); //is this the same as 
var thumbs = $(".gloom_thumbnails_wrapper img");?
  
var $pic_1 = $("#pic_1").hide().load(function(){ $pic_1.fadeIn(1000); });//ok, I understand about the loading bit you mentioned but you are also hiding what's in pic_1 but that is empty because you told me to change the html to <div class="category_pictures"><img src="" alt="" id="pic_1"></div> so why hide it? what if pic_1 is enpty what are we fading in?
   
$thumbs.each(function(i){  //for each value in pic_1 - i really don't get where that parameter i is coming from - do:
   
$(this).data({i:i}).click(function(){ //I haven't found anywhere this use of the data method with a colon between 2 parameters. Then you add a click methods, fine
   
var $this = $(this), i = $this.data('i');//I kinda got lost a bit as to which value "this" has now, i think it is still the first picture isn't?
   
$thumbs.eq(current).attr('src', 'images/gloom_thumb_%.jpg'.replace("%", current+1));//reset style of last thumbnail image. Eq is a selecting method but what is it selecting here, current? so here you change what's in current (-1) with gloom_full_1.jpg
   
$this.attr('src', 'images/gloom_thumb_shad_%.jpg'.replace("%", i+1));//set style of this thmbnail. Here you are inserting the shad pic...but what value does i have?
  
$pic_1.stop(true,true).fadeOut(1000, function(){ $pic_1.attr("src", 'images/gloom_full_%.jpg'.replace("%", i+1)); });//clear animation queue and force current fade to complete, then faade out and set new src on completion. Why do we have to clear the animation queue and force current fade to complete? and you are also changing gloom_full_1 to whathever value i has, which is?
  
current = i;//remember which image is current
  
});
  
});
  
$(".next_button a").eq(0).click(function(){ //you select the link - what's that eq(0) for here?
  
$thumbs.eq( ((current==0)?$thumbs.length:current)-1 ).trigger('click');//simulate click on prev thumbnail (with wraparound). Here I am a bit lost...
  
}).end().eq(1).click(function(){//and here as well
  
$thumbs.eq((current + 1) % $thumbs.length).trigger('click');//simulate click on next thumbnail (with wraparound).//and here too sorry
  
}).click();// .click() initialises photo to first thumbnail.
  
});

Violet,

@Airshow Wow Airshow, that is amazing, thanks for posting that. It is a little bit too advanced for me but I definitely want to give it a try to understand it first and then try it on the site.
I spent sometime studying it, googling (actually w3c schooling) but many things are still unclear. Would you mind if I go through line by line with you just to make sure that
I understand what's going on and clarify what's not clear? Hope you don't mind that

First thing, this script can then replace all that awfully long script of mine I seem to understand. Now is it replacing every function as in, will your function be called directly from my code?
You said all the thumbnails should be replaced by <li><img src="images/gloom_thumb_1.jpg" alt=" " /></li> but where do I call your function from?

Let's get to the script now:

$(function(){ //I suppose I can give it a name or should it remain as it is?
   
var current = -1; 
  
var $thumbs = $(".gloom_thumbnails_wrapper img"); //is this the same as 
var thumbs = $(".gloom_thumbnails_wrapper img");?
  
var $pic_1 = $("#pic_1").hide().load(function(){ $pic_1.fadeIn(1000); });//ok, I understand about the loading bit you mentioned but you are also hiding what's in pic_1 but that is empty because you told me to change the html to <div class="category_pictures"><img src="" alt="" id="pic_1"></div> so why hide it? what if pic_1 is enpty what are we fading in?
   
$thumbs.each(function(i){  //for each value in pic_1 - i really don't get where that parameter i is coming from - do:
   
$(this).data({i:i}).click(function(){ //I haven't found anywhere this use of the data method with a colon between 2 parameters. Then you add a click methods, fine
   
var $this = $(this), i = $this.data('i');//I kinda got lost a bit as to which value "this" has now, i think it is still the first picture isn't?
   
$thumbs.eq(current).attr('src', 'images/gloom_thumb_%.jpg'.replace("%", current+1));//reset style of last thumbnail image. Eq is a selecting method but what is it selecting here, current? so here you change what's in current (-1) with gloom_full_1.jpg
   
$this.attr('src', 'images/gloom_thumb_shad_%.jpg'.replace("%", i+1));//set style of this thmbnail. Here you are inserting the shad pic...but what value does i have?
  
$pic_1.stop(true,true).fadeOut(1000, function(){ $pic_1.attr("src", 'images/gloom_full_%.jpg'.replace("%", i+1)); });//clear animation queue and force current fade to complete, then faade out and set new src on completion. Why do we have to clear the animation queue and force current fade to complete? and you are also changing gloom_full_1 to whathever value i has, which is?
  
current = i;//remember which image is current
  
});
  
});
  
$(".next_button a").eq(0).click(function(){ //you select the link - what's that eq(0) for here?
  
$thumbs.eq( ((current==0)?$thumbs.length:current)-1 ).trigger('click');//simulate click on prev thumbnail (with wraparound). Here I am a bit lost...
  
}).end().eq(1).click(function(){//and here as well
  
$thumbs.eq((current + 1) % $thumbs.length).trigger('click');//simulate click on next thumbnail (with wraparound).//and here too sorry
  
}).click();// .click() initialises photo to first thumbnail.
  
});

OK, I will try:

$(function(){ //It's an anonymous function, which will never be called in any other way so a name is unnecessary; it would only confuse. Leave it like this.

var current = -1; 

var $thumbs = $(".gloom_thumbnails_wrapper img"); //is this the same as 
var thumbs = $(".gloom_thumbnails_wrapper img");//Yes but like many people, I always start names with $ for jquery objects. It's just a convention.

var $pic_1 = $("#pic_1").hide().load(function(){ $pic_1.fadeIn(1000); });//This is an example of jquery's "method chaining". Read as follows, "initially, hide pic_1, then set up a fadeIn action to be performed every time pic_1 successfully loads an image". It needs to be initially hidden to avoid a visual glitch which would otherwise occur when the first image gets loaded, before its fadeIn starts.

$thumbs.each(function(i){  //This is an example of a "callback function". jQuery's .each() method calls the callback function once for each selected element in $thumbs in turn. The .each() method automatically inserts integer i=0, i=1, i=2, etc. so the callback function has the means of knowing the index of the each element within the function. Callback functions are key to many jQuery methods.

$(this).data({i:i}).click(function(){ //In the .each() pattern, the correct value of i is naturally available only within the immediate callback function. By setting .data({i:i}) on each $thumb, we make them "self aware" with regard to their index in the $thumbs jQuery object (and hence in the DOM). In a couple of places elsewhere in the code, we read this value back with .data('i').

var $this = $(this), i = $this.data('i');//Following "this" is very tricky and it took a lot of concentration when I wrote the code. Here, "this" is the clicked thumbnail's DOM element, though I agree it's not particularly obvious.

$thumbs.eq(current).attr('src', 'images/gloom_thumb_%.jpg'.replace("%", current+1));//Yes, $thumbs.eq(x) selects the xth element in $thumbs (without affecting $thumbs itself). Hence we have the means of addressing the "current"th element (so we can reset its src).

$this.attr('src', 'images/gloom_thumb_shad_%.jpg'.replace("%", i+1));//Remember how we made each $thumb "self aware" with regard to its index? This is where we benefit from having done that. i is the clicked thumbnail's index.

$pic_1.stop(true,true).fadeOut(1000, function(){ $pic_1.attr("src", 'images/gloom_full_%.jpg'.replace("%", i+1)); });//clear animation queue and force current fade to complete, then fade out and set new src on completion. 
//.stop(true,true) is necessary because the user might well click another thumbnail or "prev" or "next" before the current animation is complete (the full cycle takes 2 seconds). Try running the code without .stop(true,true) and things can get really messed up (I know, it happened in testing). The only way out would be to refresh the page.

current = i;//straightforward

$(".next_button a").eq(0).click(function(){ //Remember I added a "prev" button in the same container as the "next" button? .eq(0) selects the first button in the container (ie. "prev"). The container would now be better addressed with id="controls".

$thumbs.eq( ((current==0)?$thumbs.length:current)-1 ).trigger('click');//.trigger() is a brilliant piece of jQuery. It allows us to simulate an event that would normally arise from a user interaction ('click' in this case). The expression passed to .eq() simply subtracts 1 (for the "prev" action) with wraparound from the first (0th) thumbnail to the last thumbnail.

}).end().eq(1).click(function(){//.end() saves us from having to repeat $(".next_button a") in a separate statement.  .end() works by undoing the effect of .eq(0) (jQuery maintains an internal selection "stack" for this purpose) thus allowing us to select the "next" button with .eq(1) .

$thumbs.eq((current + 1) % $thumbs.length).trigger('click');//Same as for the "prev" button, but with a different expression to achieve wraparound from the last thumbnail to the first (0th) thumbnail.

}).click();// .click() initialises photo to first thumbnail.

});

IMHO, the best ways to learn jQuery are to:

  1. consult the online jQuery API. I go there frequently.
  2. buy the jQuery Pocket Reference. The title doesn't do this book full justice, it has a not insignificant tutorial narrative. The current price at Amazon (£5.47) is extremely keen; I paid about double that and it was still excellent value.

I have learned all my jQuery from these two resources.

Airshow

I'm off to the kitchen now. Cantaloupe melon has been ripening for 5 days, out of the fridge, and I judge it's about ready.

Airshow

Thanks for your patience Airshow, that's great. I managed to get hold od a copy of the jquery book as well as the javascript pocket reference, it's pretty good. I will try your code on my test site.
Hope you enjoyed your melon : -)

@floatingDivs, thanks for your help too much appreciated!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.