Creating a jQuery Slideshow – Adding Thumbnail Navigation

jQuery Slideshow | Programmers

slideshow-thumbnailsIn this post series we’re creating a jQuery Slideshow from scratch. In the last post we adding functionality when the user clicks on a thumbnail. In this post we’re going to add basic thumbnail navigation.

Example: See jsFiddle at the bottom of this post. Note: The jsFiddle at the bottom of this post is a composite of all previous posts on this jQuery Slideshow.

jQuery Slideshow Tutorials

[list_category name=”jQuery Slideshow”]

What We’re Creating

In the last post we added thumbnails, but didn’t have any way to navigate through them. So we’re going to add navigational arrows to our slideshow in this post, and provide a way for the user to scroll through them. We will add another, quicker way in a future post, but for now, the user will simply hover of the arrow and the Thumbnails will move to the right or left.

The New HTML

We’ll have to add a few things to our HTML to make the arrows go where we want them to.

<div id="thumbnails">
 <div class="thumbnailArrows"><img src="http://kimjoyfox.com/wp-content/uploads/leftA.jpg" id="Tleft"/>
 </div>
 <div id="window">
 <div id="imageHolder"></div>
 </div>
 <div class="thumbnailArrows"><img src="http://kimjoyfox.com/wp-content/uploads/rightA.jpg" id="Tright" />
 </div>
 </div>

We added a Div around our previous HTML called “thumbnails”. Then before and after the “window” Div that holds the thumbnails, add a Div class called “thumbnailArrows”. These will hold… you guessed it!… our thumbnail navigational arrows. The one before will have an image of a left arrow; the one after an image of a right arrow.

Notice both of these Divs have IDs: “Tleft” and “Tright”. We’ll reference those later.

Editing the CSS

The thumbnail CSS will now have a few additional Divs. Below is the entire CSS relating to the thumbnails:

#thumbnails { width:300px; height:50px; margin-top:20px;}
 #window { width:250px; height:50px; overflow:hidden; float:left; position:relative;}
 #imageHolder { height:50px; position:absolute; top:0px; left:0px;}
 #imageHolder img { width:35px; height:50px; float:left; margin-right:5px;}
 #thumbnails .thumbnailArrows { width:25px; height:50px; float:left; }
 #thumbnails .thumbnailArrows:hover {cursor:pointer; }

We added “thumbnails” Div, with a width of 300 pixels, a height of 50 pixels and we added a margin to add some nice spacing between the thumbnails and the main image.

We also changed the “window” Div’s width to 250 pixels. We edited the width here because we have to fit two arrows of 25 pixels each within the thumbnails section, which is made to be as wide as the main image. We also added float:left so that it will sit nicely with the arrows on either side.

Finally, we get to the actual arrows Div. Remember in CSS, writing a class or ID of a Div and then adding another one means the second is inside the first. For example, on the second to the last line, “.thumbnailArrows” must be inside of the “thumbnails” Div for the CSS to find it. If we added a comma in between, then we would be telling the CSS to change the width and height and float qualities of both the “thumbnails” Div and the “thumbnailArrows” Div.

The “thumbnailArrows” Div (which is used twice, once for each arrow – left and right) will have a width of 25 pixels, a height of 50 pixels and will float left, next to the “window” Div.

Finally, when the user hovers over one of the arrows, we want the cursor to change to a pointer, line 6. You can add a :hover to pretty much any Div.

The jQuery: Heavylifting Function

We’re really going to get into some heavy-lifting (or heavy-thinking) in this jQuery function. The entire function coding is below, and I’ll reference line numbers as I explain what’s happening.

function movingThumbs(speed, direction) {
 var currentLeft = $('#imageHolder').position().left;
 var moving = $('#imageHolder').width() - (Math.abs($('#imageHolder').position().left) + $('#window').width());
 if (currentLeft == 0 && direction == '+') {
       //do nothing
 } else if (Math.abs($('#imageHolder').position().left) + $('#window').width() >= $('#imageHolder').width() && direction == '-') {
       //do nothing
 } else if (direction == '+' && currentLeft != 0) {
       $('#imageHolder').animate({
            left: 0,
       }, speed);
 } else {
       $('#imageHolder').animate({
           left: '+='+direction + moving,
       }, speed);
 }
 }

Line 1 we name the function and set to accept two variables being passed. The first will be the speed of the animation and the second will be the direction the animation will go (ie, left or right depending on which arrow is being hovered over).

The main idea of the thumbnails is that they move left or right within the “window” Div. If they move left, the “imageHolder” Div’s left position will be negative (for example, -120px). If it moves right, the the “imageHolder” Div’s left position will be positive (for example, 120px). This will be important to keep in mind as we go along.

We’re going to have several options in this function: lines 5, 7, 9, and 13. The options are: 

Line 5: User is hovering over left arrow, but the thumbnails are already at the beginning of the thumbnails

Line 7: User is hovering over right arrow, but the thumbnails are already at the end of the thumbnails

Line 9: User hovers over left arrow and we want to scroll the thumbnails left

Line 13: User hovers over right arrow and we want to scroll the thumbnails right.

So let’s break each of these down:

Line 5: User is hovering over left arrow, but the thumbnails are already at the beginning of the thumbnails

The first thing we’ll need to know is whether we are at the beginning of the thumbnails, ie. far left, there are no other thumbnails to the left. To do that, we use Line 2 to check the current position of our “imageHolder” Div.

$('#imageHolder').position().left;

position() is a built-in jQuery function that finds the position of the Div (if set) from right, left, top, and bottom.We wanted to know where it is from the left, so we added “left” after the “position()” function. We also put this in a variable because we’ll use it more then once in our function.

Next, in line 5, we want to check if the position:left is 0 (thumbnails are already far left) and the user is hovering over the left arrow. If that’s true, nothing happens. That’s because we don’t want the thumbnails to continue scrolling if we’re already at the beginning of the line of thumbnails. The direction variable is coming from what we pass to the function (remember line 1). We’re using ‘+’ as a value for the left arrow and ‘-‘ as a value for the right arrow; don’t change this, as it will be used later.

Line 7: User is hovering over right arrow, but the thumbnails are already at the end of the thumbnails

Alternately, if we’re at the end of the thumbnails on the right, we’ll need to check so that the user can’t continue scrolling right. To do that, we’ll write line 7.

Easy part first: at the end of the else if statement, you’ll see

&& direction == '-'

That means we’re checking to see if the user is hovering over the right arrow (see Line 5 explanation).

Then comes the tricky part:

Math.abs($('#imageHolder').position().left) + $('#window').width() >= $('#imageHolder').width()

WHAT THE *!J@($!!!!

Take a deep breath. This is a lot like algebra. We’ll break it down. What we’re basically doing is taking the area left of our “window” Div, adding the width of the “window” Div and checking if that’s bigger or equal to the “imageHolder” Div’s Width – we seeing if we’ve reached the end of the line of thumbnails.

Or, if this makes more sense, we’re adding the “imageHolder” Div’s left (let’s say -40 pixels) plus the “window” Div’s width (ie. 300 pixels), which would equal 340 pixels (yes, we got rid of the negative sign) and seeing if that is greater then or equal to the entire width of all the thumbnails. Let’s say our “imageHolder” Div’s width is 360 pixels. That means there’s still 20 pixels of thumbnails still on the right side of the “window” Div that can be scrolled.

Math.abs($('#imageHolder').position().left)

Math.abs is a build-in Javascript function for making a number positive (ie. removing negative numbers). This is important because the “imageHolder” Div’s position left is always going to be either 0 or negative, and we’ll need to find the width of the “imageHolder” Div plus the “window” Div’s width to check if we’ve reached the end.

Line 9: User hovers over left arrow and we want to scroll the thumbnails left

Only two more options to go! This one is again very simple. We’ll check to see if the left arrow is being hovered over and if the “imageHolder” Div is not to the far left.

else if (direction == '+' && currentLeft != 0) {
 $('#imageHolder').animate({
 left: 0,
 }, speed);
 }

If both these are true (notice the && between the two options) then we tell the “imageHolder” Div to animate till it has a left value of 0, meaning we’re at the beginning thumbnail. After we close the first brackets of the animate function, the curly brackets, we add a comma and the variable speed that we send to this function.

Line 13: User hovers over right arrow and we want to scroll the thumbnails right.

Finally, our last option is really the most basic one: the user is hovering over the right arrow to scroll through the thumbnails.

else {
$('#imageHolder').animate({
left: '+='+direction + moving,
}, speed);
}

This one, we don’t put a else if statement on because if none of the other options are true, this one must be. We use the built-in animate function again, using the speed variable again at the end, but in the middle we do something a little different.

We will be changing the left position of the Div, but we don’t an absolute position here (though we could have). In the Line 9 option, we moved the left position to an absolute position of 0. Here, we’ll move the left position, say, 300 pixels from wherever it starts. To do this, we use the ‘+=’. Then we’ll use the direction variable (a ‘-‘ for the right arrow), and the moving variable.

So basically, the line really translates to this:

left: +=-300,

Let’s take a look at the moving variable set at the beginning of this function:

var moving = $('#imageHolder').width() - (Math.abs($('#imageHolder').position().left) + $('#window').width());

This variable needs to figure out how many more pixels till we reach the end of the thumbnails. So we take the entire “imageHolder” Div’s width (which holds the thumbnails and is set to their width), and subtract the sum for the area already scrolled through (position:left), and the “window” Div’s width. Just like in algebra, we enclose the second half (after the ‘-‘) in parenthesis so that those are added first, and then the final number is subtracted from the total width.

All that math gets us how far from the end of the thumbnails we are, so we can move the “imageHolder” Div the appropriate amount.

jQuery Calling the Function

Promise, we’re almost done! Now we have to call the function and pass the variables it needs to operate.

    $('.thumbnailArrows').hover(function() {
var whiches = $(this).children('img').attr('id');
if (whiches == 'Tleft') {
movingThumbs(2000, '+');
}
else {
movingThumbs(2000, '-');
}
}, function() {
$('#imageHolder').stop();
});

Line 1 – when the user hovers over one of the arrows (or technically, the Div class “thumbnailArrows” that the arrow picture is inside of)

Line 2 – Get the children image’s ID (So the image inside of the hovered over Div – it’s ID)

Lines 3 and 6- If the ID is Tleft (the left arrow), or the right arrow (no need for the if statement)

Lines 4 and 7 – call the function we just created; set the speed variable to 2000 (2 seconds) and the direction variable appropriately.

Lines 9 -10 – When the user stops hovering over the “thumbnailArrows” Div, stop the animation.

The Example:

Comments
  • Zelenco Mihnea says:

    Hi.
    Thank you so much for your profesional information provided in Jquery series.I wanted you to ask if i can make your script dinamic with a php server side ,and JSON as exchange data format.
    So in the javascript begining you have two arrays : one for images path and the other for information about that images.
    My question is: Can i generate an array of images on the server side ,transmitted as a JSON to jquery ,and then populate your arrays (images and title) with dynamic number of images instead using your static predefined arrays? I mean, do i need to make further updates on your js file other then make your javascript arrays dynamic?And i see you have in your html code an image path defined as the default image.I think that can be also made dynamic.Because when you have a new album that image should be the first image in the specified album.If you can provide some example of php server side,especialy send json data to jquery and make your javascript static defined arrays ,dynamic.
    Thank you once again for your very detailed series of tutorials.

  • Joe says:

    so I am having an issue with getting the navigation buttons to work, the slideshow works just fine but when I add in the left and right arrow navigation the way you have it set up in the second post nothing happens. Also I get a broken image for the first slide every time, I am using a database to populate the image array. Would that be the problem or should everything flow propperly regardless?

    • KimJoyFox says:

      I’d fix the broken image first, just in case.
      Then check out any errors in the console. Just in case you haven’t used it before, using Chrome, right-click anywhere on the page, and choose “inspect element”, then go to the console tab. That gives you a good starting point for errors.
      Let me know how it works out!

  • Joe says:

    for the broken image it throws this error

    GET http://www.testServer.com/testDb/%5B 404 (not found)

    its the opening bracket for the array, why is it trying to display that? i can post my code for you if you would like.

  • Joe says:

    there is suposed to be a “[” before the 404 error there

  • Joe says:

    ok here is my php pulling the needed image information from my database

    “$picSql = mysql_query(“SELECT * FROM uploads WHERE ref_id = ‘$refID'”);

    while($picRow = mysql_fetch_assoc($picSql))
    {
    $picA[] = ‘pics/’ . $picRow[‘name’];
    }

    $array = json_encode($picA);”

    and then I use java to reference that with this

    “var picArray = ;”

    and then for the img src code I use this


    <img src="” id=”slideshow” />

    • KimJoyFox says:

      I don’t think you need to json_encode it.
      I usually do something like this:

      while ($picRow = mysql_fetch_array($picSql)){
      < img src="< ?php echo $picRow['rowInDatabaseThatHoldsImageURL']; ? >" / >
      //remove spaces above between the < ? and ? >
      }

      Unless you need it in a javascript array, you’re good just echoing it like that.

      EDIT: Just saw your comment about needing it in a javascript array. I don’t use json_encode very much, so I can’t really tell you about that one. I would try to make it work just regular, and then add in the added javascript functionality. When the finished product doesn’t work, I’d break it down piece by piece and see what part isn’t working.
      You can also ask at StackOverflow.com.
      I’ll be creating a post soon about the PHP stuff, but that’s a good question on using jQuery to dynamically change the gallery they’re viewing.

  • Joe says:

    ok it lost the php code so I will fill in the gaps

    var picArray = echo $array;

    img src = echo $array;

  • Joe says:

    I cant put in a static value for the images starting point because it is always going to be changing depending on which ‘gallery’ the person viewing the slideshow chooses to look at.

  • Joe says:

    that row only holds the name of the file the path to said file needs to be apended to the $picRow variable so the code would look something like this

    < img src = "pics/”

    when I do it that way the php code does not get read at all and so the page throws an error at me because all it sees is up to the pics/ and no img.jpg attached to the end

  • Joe says:

    just like in this part the php code dissapears, har har har. how did you get that grey window to come up?

    • KimJoyFox says:

      You’ll need to fill in wherever the image is. To add more then one row, do this:
      < ?php $row['folder'].'/'.$row['imgURL']; ? >

      Note the periods connecting them, and then I added a forward slash between parenthesis for the forward slash between the folder and the image url.

      To add code, just surround the text with a < code > and end with a < / code >
      (no spaces)

  • Joe says:

    i know your time is precious and I do appreciate the time you have taken thus far to help a nooblet with his issues using your code, I look forward to any other feedback you may be able to provide, there are a few things that I need to ask you about, if you get the chance perhaps you could email me and we can continue this at your convenience, I’m sure you have many demands on your time. My email address is sir.ravenwolf@gmail.com and don’t worry I’m not wanting any thing more then just advice and maybe some guidance as I try to learn jquery and how to use it in conjunction with the other languages I already know.

  • Joe says:

    ok thats I understand but I don’t have a row in the database that holds the folder location, any time I reference a picture I usually just reference like this


    < img src = "pics/ " height = "" / >

    which is why this one is stumping me so bad concidering it works everywhere else.

  • Joe says:

    Thank you so much for the guidance and assistance, I have narrowed down and fixed the problems, all I have left is getting the thimbnail navigation and functionality here in this last post implemented, you are a great teacher. Thanks Again.

  • Joe says:

    Ok one more bit of help if you can, I have everything working except for the sliding of the thumbnails, the hover function works but nothing moves, I opened up the inspector and there are no errors, and when I inspect the imageHolder div the value left appears when I hover over the arrows and cycles through the distance for the right button but as soon as I take the mouse away, if I put it back the value starts back at 0 and the left one just keeps the value at 0 doing nothing, I used exactly the code you did except mine are named tLeft and tRight, and I am not using the thumbnails id div because one the arrows are below the thumbnails and two when I did get it in there it made no difference in the operation of the arrows. please help.

  • Joe says:

    thanks in advance

  • Joe says:

    Unfortunately, I cant give you that information, the guy I work with is super peranoid and doesn’t even approve of me asking for help or guidance in forums, I had to fight with him for days just to get him to chill out about my posting on danyweb and other like sites. Too much information exchanged he says. But I can put code snippets up for you to see, and maybe a screen shot if I can sneek it by him.

  • So ,after after a couple of weeks i made the script working.The diference between using php json and javascript array then directly output all images in an img tag with php is: less http requests.
    If you use php to generate let’s say 10 img tags with the path to your images there will be 10 http request made one time, so more time to downlod.

    if you use php to output json and and populate a javascript array then you will make only a request at a time,so the site looks that is mooving faster.

    I had developed an application that is based on Kim’s tutorial,and i needed a way to link the slideshow with the cms/admin tutorial wrote by Alex from phpacademy.Since i coded myself,there are a few interface erros but i modified the scripts and ,i managed to make them work.

    Once again thanks Kim for sharing your knowledge with us.

  • Caroline D. says:

    Hi,
    Thanks for your tutorial ! Straight to the point and short.
    How would you add a href tags to the images of the slideshow ?
    Thanks !

  • Wow that was strange. I just wrote an very long comment but after
    I clicked submit my comment didn’t appear. Grrrr… well I’m not writing all that over again.

    Anyways, just wanted to say wonderful blog!

  • Kathy Henderson says:

    What plugins are required for this slider?