Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Yifang kuo
seal-mask
.a{fill-rule:evenodd;}techdegree
Yifang kuo
Front End Web Development Techdegree Student 12,376 Points

jQuery: How to make prev/next arrows for gallery lightbox overlay

Hi, I have working on treehouse project. I try to make my button work, I tried different solution but it just failed. Can anyone helped me to check my code to see where I did wrong?

Here is my code

//Problem: User when clicking on image goes to a dead end
//Solution: Create an overlay with the large image - Lightbox & Provide previous and next button

var $overlay = $('<div id="overlay"><div></div></div>');
var $image = $("<img id='main' src='' alt=''>");
var $caption = $("<p></p>");

//Keep track of image index for prev/next,we will use a list index
//position to determine where we are and what it means to move forward and backword by 1

var current_li;

//this id grabbing the list items from the imageGallery element
//and we are assign the length total
//this makes it flexible to expend the gallery or take away

var $galleryLength = $("#imageGallery li").length;

//An image to overlay
$overlay.children("div").append($image);

//A caption to overlay
$overlay.children("div").append($caption);

//Add some nav buttons and assign unique ids to them
$overlay.children("div").append("<button id='btnPrev'> < </button>");
$overlay.children("div").append("<button id='btnNext'> > </button>");

//Add overlay
$("body").append($overlay);

//Update image overlay
var updateImage = function(imageLocation,imageCaption) {

    //update the overlay with the image linked in the link
    $image.attr("src",imageLocation);

    //get child <img> alt atribute and set caption
    $caption.text(imageCaption);

}

//Capture the click event on a link to an image
$("#imageGallery a").click(function(event){
  event.preventDefault();

  //This contains the source for the curren image
  var imageLocation = $(this).attr("href");
  var imageCaption = $(this).children("img").attr("alt");

  //Update overlay with the image linked in the link
  var current_li = $(this).parent();

  //this is calling that new Update overlay function above
  updateImage(imageLocation,imageCaption);

  //Show the overlay.
  $overlay.slideDown(imageLocation);

});



$("#btnNext").click(function(){
  if (current_li.is(":last-child")){
     var next_li =("#imageGallery li").first();
  } else {
    var next_li = current_li.next();
  }
  var next_src = next_li.children("img").attr("src");
  $("#main").attr("src", next_src);
  current_li = next_li;
});


$("#btnPrev").click(function(){
  if (current_li.is(":last-child")){
     var prevt_li =("#imageGallery li").last();
  } else {
     var prev_li = current_li.prev();
  }

  var prev_src = prev_li.children("img").attr("src");
  $("#main").attr("src",prev_src);
  current_li = prev_li;


});


//When overlay is clicked
$overlay.click(function(event){
  //Hide the overlay
  if(event.target.id == "overlay")
    $(this).slideUp("fast");
});
<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" title="no title" charset="utf-8">
        <title>Image Gallery</title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!--CSS-->
        <link rel="stylesheet" href="css/normalize.min.css">
        <link rel="stylesheet" href="js/slick/slick.css">
        <link rel="stylesheet" href="css/main.css">
    </head>
<body>
        <header class="header">
            <input type="search" id="search-bar">
        </header>

         <div class="wrapper">  
            <ul id="imageGallery">
                <li><a href="Photos/01.jpg"><img src="Photos/Thumbnails/01.jpg" width="150px" alt="Hay Bales
                I love hay bales. Took this snap on a drive through the countryside past some straw fields."></a></li>
                <li><a href="Photos/02.jpg"><img src="Photos/Thumbnails/02.jpg" width="150px" alt="Lake
                The lake was so calm today. We had a great view of the snow on the mountains from here."></a></li>
                <li><a href="Photos/03.jpg"><img src="Photos/Thumbnails/03.jpg" width="150px" alt="Canyon
                I hiked to the top of the mountain and got this picture of the canyon and trees below."></a></li>
                <li><a href="Photos/04.jpg"><img src="Photos/Thumbnails/04.jpg" width="150px" alt="Iceberg
                It was amazing to see an iceberg up close, it was so cold but didn’t snow today."></a></li>
                <li><a href="Photos/05.jpg"><img src="Photos/Thumbnails/05.jpg" width="150px" alt="Desert
                The red cliffs were beautiful. It was really hot in the desert but we did a lot of walking through the canyons."></a></li>
                <li><a href="Photos/06.jpg"><img src="Photos/Thumbnails/06.jpg" width="150px" alt="Fall
                Fall is coming, I love when the leaves on the trees start to change color."></a></li>
                <li><a href="Photos/07.jpg"><img src="Photos/Thumbnails/07.jpg" width="150px" alt="Plantation
                I drove past this plantation yesterday, everything is so green!"></a></li>
                <li><a href="Photos/08.jpg"><img src="Photos/Thumbnails/08.jpg" width="150px" alt="Dunes
                My summer vacation to the Oregon Coast. I love the sandy dunes!"></a></li>
                <li><a href="Photos/09.jpg"><img src="Photos/Thumbnails/09.jpg" width="150px" alt="Countryside Lane
                We enjoyed a quiet stroll down this countryside lane."></a></li>
                <li><a href="Photos/10.jpg"><img src="Photos/Thumbnails/10.jpg" width="150px" alt="Sunset
                Sunset at the coast! The sky turned a lovely shade of orange."></a></li>
                <li><a href="Photos/11.jpg"><img src="Photos/Thumbnails/11.jpg" width="150px" alt="Cave
                I did a tour of a cave today and the view of the landscape below was breathtaking."></a></li>
                <li><a href="Photos/12.jpg"><img src="Photos/Thumbnails/12.jpg" width="150px" alt="Bluebells
                I walked through this meadow of bluebells and got a good view of the snow on the mountain before the fog came in."></a></li>

            </ul>
            </div>
            <script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
            <script src="js/slick/slick.min.js"></script>
            <script src="js/app.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>

This is unrelated to your problem and more of a suggestion.

If you want to remain consistent with your variable naming, your current_li variable could be named $currentLi

I switched it to camel case naming and also prefixed it with a $ to indicate that it's storing a jQuery object.

Likewise, your $galleryLength variable should not have a $ in front because it's only storing a simple integer and not a jQuery object.

These are not requirements but it would increase the readability and consistency of your code.

3 Answers

Hi Yifang,

You declared a global variable current_li near the top of your code. But then inside your #imageGallery a click handler you used the var keyword again when assigning the parent li, var current_li = $(this).parent();

This creates a local variable of the same name. At this point, your global current_li is still undefined

The handlers for your next and prev buttons are referring to the global current_li which is undefined.

If you remove the var keyword then it should fix that problem.

I didn't check for other problems but you can try that first and then post back if it's still not working.

Yifang kuo
seal-mask
.a{fill-rule:evenodd;}techdegree
Yifang kuo
Front End Web Development Techdegree Student 12,376 Points

Hi Jason,

Thanks for taking time to have a look. I've edited my code about what you said. However, it still not working. I guess it might be something wrong with my next and prev button.

Can you provide any additional details about how it's not working?

Do you know if it's making it to the click handlers for the next and prev buttons?

Do you know how to use your browsers console to see if you're getting any error messages?

Looking again at the prev and next handlers, I saw a few issues with the prev handler

$("#btnPrev").click(function(){
  if (current_li.is(":last-child")){
     var prevt_li =("#imageGallery li").last();
  } else {
     var prev_li = current_li.prev();
  }

  var prev_src = prev_li.children("img").attr("src");
  $("#main").attr("src",prev_src);
  current_li = prev_li;
});

You used last-child on your first line but I think you meant to use first-child.

Inside the if block you named the variable prevt_li but I think you meant prev_li

Yifang kuo
seal-mask
.a{fill-rule:evenodd;}techdegree
Yifang kuo
Front End Web Development Techdegree Student 12,376 Points

Thank you Jason. I tried editing like below and the when I click the button, the console said prev & next is not defined. I guess it must be something wrong with my current_li.

//Problem: User when clicking on image goes to a dead end
//Solution: Create an overlay with the large image - Lightbox & Provide previous and next button

var $overlay = $('<div id="overlay"><div></div></div>');
var $image = $("<img id='main' src='' alt=''>");
var $caption = $("<p></p>");

//Keep track of image index for prev/next,we will use a list index
//position to determine where we are and what it means to move forward and backword by 1

//this id grabbing the list items from the imageGallery element
//and we are assign the length total
//this makes it flexible to expend the gallery or take away

var $galleryLength = $("#imageGallery li").length;

//An image to overlay
$overlay.children("div").append($image);

//A caption to overlay
$overlay.children("div").append($caption);

//Add some nav buttons and assign unique ids to them
$overlay.children("div").append("<button id='btnPrev'> < </button>");
$overlay.children("div").append("<button id='btnNext'> > </button>");

//Add overlay
$("body").append($overlay);

//Update image overlay
var updateImage = function(imageLocation,imageCaption) {

    //update the overlay with the image linked in the link
    $image.attr("src",imageLocation);

    //get child <img> alt atribute and set caption
    $caption.text(imageCaption);

}

$(function(){
  var current_li;

  //Capture the click event on a link to an image
  $("#imageGallery a").click(function(event){
    event.preventDefault();

  //Update overlay with the image linked in the link
  var current_li = $(this).parent();

  //This contains the source for the curren image
  var imageLocation = $(this).attr("href");
  var imageCaption = $(this).children("img").attr("alt");

  //this is calling that new Update overlay function above
  updateImage(imageLocation,imageCaption);

  //Show the overlay.
  $overlay.slideDown(imageLocation);

  });

  $("#btnNext").click(function(){
    var next_li = current_li.next();
    var next_src = next_li.children("img").attr("src");
    $("#main").attr("src", next_src);
    current_li = next_li;
  });

  $("#btnPrev").click(function(){
    var prev_li = current_li.prev();
    var prev_src = prev_li.children("img").attr("src");
    $("#main").attr("src",prev_src);
    current_li = prev_li;
  });


//When overlay is clicked
$overlay.click(function(event){
  //Hide the overlay
  if(event.target.id == "overlay")
    $(this).slideUp("fast");
});

});

Inside your click handler you still have the var keyword

//Update overlay with the image linked in the link
  var current_li = $(this).parent();

You have to remove var because that creates a local variable within the click handler which is different from the one declared earlier.

Also, you've removed some code from your prev and next handlers where you were checking if you were either on the last item or the first item. The other versions you had were closer to what you need to do.

Tracy Excell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Tracy Excell
Front End Web Development Techdegree Graduate 15,333 Points

Can you please explain the steps needed to do this task as I struggling to get it to work and am keen to understand the process to help me learn how to code this in jquery.

can you explain why the .parent is included in the code?

var current_li = $(this).parent();

I am working on this task at the moment and my thought process is:

var $currentImage = $thisImage; var $nextImage = $currentImage.next().att(img, "src");

$("buttonNext").click(function(){ currentImage.hide(); nextImage.show(); });

It is obviously a lot more complex than this, so your help in understanding it would be appreciated.

Yifang kuo, I apologize for messaging here, but I did not want to start a new post.

I happened across your portfolio today. Two things:

  1. It looks great! :)
  2. Your navigation needs a quick fix, though.

Note: Before implementing this fix, resize your browser to 850px (wide), approximately. When you have done so, scroll down and you'll notice that portions of the navigation eventually disappear.

Here is a solution:

/* ---- Navigation ---- */
.main-nav {
  width: 100%;
  min-height: 45px;
  padding: 10px;
  position: fixed;
  text-align: center;
  background:#fff;
  z-index: 100; // This property-value pair fixes the disappearing navigation.
}

Here is a cool link that discusses z-index. If that link is a little verbose, this one is pretty good, too: z-index. :)

There are plenty of additional resources floating in the nebula of the net--if those don't help.

Keep up the great work!

Never Stop Learning