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

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

JQuery help in understanding steps needed to create a next button for a lightbox

Hello, I am trying to work through creating the code needed for my next and previous buttons to work in JQuery, on a light box photo gallery. bellow is my thought process, but I am missing steps, or on the wrong track!. I am keen to learn how to work out how to do this, if anyone has the time to explain the steps, and what I am missing, it would be appreciated.

button thoughts:

//button attempt
var $buttonNext = $("<button> > </button>");
var $buttonPrevious = $("<button> < </button>");

//var $thisImage = $(this).attr("img");
//var $nextImage =$thisImage.next("img");
//var $previousImage


 //trying to get buttons to function 

//$("$buttonNext").click(function(){
    $thisImage.remove();
    $thisImage.next("img");
    $nextImage.show();
});

here is my lightbox code.

var $overlay = $('<div id="overlay"></div>');
var $image = $("<img>");
var $caption = $("<p></p>");
//button attemp
var $buttonNext = $("<button> > </button>");
var $buttonPrevious = $("<button> < </button>");

//var $thisImage = $(this).attr("img");
//var $nextImage =$thisImage.next("img");
//var $previousImage


//an image
$overlay.append($image);

//a caption to overlay
$overlay.append($caption);

//attemting to add buttons.  This worked now need to get them to scroll fowards and back.

$overlay.append($buttonPrevious);
$overlay.append($buttonNext);


// add an overlay
$("body").append($overlay);

// capture the click event on a link to an image

$("#imageGallery a").click(function(event) {
  event.preventDefault();
 var imageLocation = $(this).attr("href");


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

// Show the overlay
  $overlay.show();


//Get child alt attribute and set caption

 var captionText = $(this).children("img").attr("alt");
  $caption.text(captionText);

} );

//When overlay is clicked

$overlay.click(function() {
  overlay.hide();
})


 //trying to get buttons to function 

//$("$buttonNext").click(function(){
    $thisImage.remove();
    $thisImage.next("img");
    $nextImage.show();
});

I am also struggling with adding next and previous arrows to scroll through images in a lightbox. In theory, it seems like it should be easy, but as I am very new to jQuery and it has proven to be more difficult than imagined. I would prefer to not use a plugin for the previous/next functionality.

Here is the HTML:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Image Gallery</title>
        <link rel="stylesheet" href="css/lightbox2-master/dist//css/lightbox.css">
        <link rel="stylesheet" href="css/main.css">
    </head>
    <body>
        <header>
            <div class="header-container">
                <form id="searchbox" method="get">
                    <input type="text" class="search_box" name="search-field">
                </form>
            </div>
        </header>
        <main>
            <ul id="imageGallery">
                <li><a href="photos/01.jpg"><img src="./photos/Thumbnails/01.jpg" alt="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" alt="The lake was so calm today. We had a great view of the snow on the mountains from here." class="photo"></a></li>
                <li><a href="photos/03.jpg"><img src="./photos/Thumbnails/03.jpg" alt="I hiked to the top of the mountain and got this picture of the canyon and tress below." class="photo"></a></li>
                <li><a href="photos/04.jpg"><img src="./photos/Thumbnails/04.jpg" alt="It was amazing to see an iceberg up close, it was so cold but didn't snow today." class="photo"></a></li>
                <li><a href="photos/05.jpg"><img src="./photos/Thumbnails/05.jpg" alt="The red cliffs were beautiful. It was realy hot in the desert but we did a lot of walking through the canyons." class="photo"></a></li>
                <li><a href="photos/06.jpg"><img src="./photos/Thumbnails/06.jpg" alt="Fall is coming, I love when the leaves on the trees start to change color." class="photo"></a></li>
                <li><a href="photos/07.jpg"><img src="./photos/Thumbnails/07.jpg" alt="I drove past this plantation yesterday, everything is so green!" class="photo"></a></li>
                <li><a href="photos/08.jpg"><img src="./photos/Thumbnails/08.jpg" alt="My summer vacation to the Oregon Coast. I love the sandy dunes!" class="photo"></a></li>
                <li><a href="photos/09.jpg"><img src="./photos/Thumbnails/09.jpg" alt="We enjoyed a quiet stroll down this countryside lane." class="photo"></a></li>
                <li><a href="photos/10.jpg"><img src="./photos/Thumbnails/10.jpg" alt="Sunset at the coast! The sky turned a lovely shade of orange." class="photo"></a></li>
                <li><a href="photos/11.jpg"><img src="./photos/Thumbnails/11.jpg" alt="I did a tour of a cave today and the view of the landscape below was breathtaking." class="photo"></a></li>
                <li><a href="photos/12.jpg"><img src="./photos/Thumbnails/12.jpg" alt="I walked through this meadow of bluebells and got a good view of the snow on the mountain before the fog came in." class="photo"></a></li>
            </ul>
        </main>
        <footer></footer>
        <script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="scripts.js" type="text/javascript" charset="utf-8"></script>
    </body>
</html> 

Here is the js file. I have added arrows and appended them to the overlay. On a click event I want to use prev() and next() to traverse through the sibling image elements. However, when I use this() and prev()/next() on the click event, it doesn't work because the images are not siblings to the button elements. I need help on focusing on the image on the button click event so that I can traverse through the image siblings.

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

//Append an image to the overlay
$overlay.append($image);

//Add a caption to the image in the overlay
$overlay.append($caption);

//Append the overlay to the body
$("body").append($overlay);

//When a click event occurs, link to an image
$("#imageGallery a").click(function(event){
  event.preventDefault();
  var imageLocation = $(this).attr("href");
  $image.attr("src", imageLocation);
  $overlay.show();
  //Add the child alt attr as a caption
  var captionText = $(this).children("img").attr("alt");
  $caption.text(captionText);
});

//Hide overlay on click event
$overlay.click(function(){
  $overlay.hide();
});

//Add arrows to scroll through images when the overlay is active

//1. Create previous and next buttons
var $leftarrow = $('<button> < </button>');
var $rightarrow = $('<button> > </button>');

//2. add arrows to light box 
  //2.1 left arrow
  $overlay.append($leftarrow);
  //2.2 next arrow
  $overlay.append($rightarrow);

//3. link arrows to previous($leftarrow) and next ($rightarrow) images
$leftarrow.click(function(){

});

$rightarrow.click(function(){

});

Thanks!

fixed code formatting in question and added html and js language hints to follow up comment

3 Answers

Hi Tracy Excell and Mary Hawley ,

I haven't implemented this myself but I can try walking you through one way you can approach it.

One thing you'll have to decide is is you want it to be circular or you can only go forwards and backwards. In other words, what should happen when you're on the first image and you click the previous button? It can either wrap around to the last image or do nothing.

The lightbox is completely separate from the thumbnail list so there is no way to traverse through the images based off of the one that is showing in the lightbox.

One thing that you can do is keep track of the index of which image is currently being shown. Then you can adjust that index up or down in the prev and next click handlers in order to figure out which image you're getting next.

Near the top of your code with the other variable declarations you can declare an index variable. There's no point in initializing it right now because you don't know what thumbnail the user will click on to start the lightbox. It will also be helpful to have a variable storing the length of the gallery.

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

The click handler for the links is where you want to set the value of the index variable. jQuery's .index() method can be used here.

The no argument version is the easiest one to use but it only works on sibling elements. The links are not siblings but their parent li's are siblings. So you need to get the parent of the clicked link and then its index.

Keep in mind that the index is zero-based like an array. So if gallery has 12 items, the valid indices will be 0 through 11. The last valid index is galleryLength - 1

$("#imageGallery a").click(function(event){
    index = $(this).parent().index();
    // existing code omitted
});

I'll cover part of the prev button handler and the next handler will be similar logic.

When the user clicks the previous button you need to decrement the index. But there's a special case to consider when the current image is the first one (index 0). If you decrement that, you'll get -1 which is an invalid index.

Assuming a circular gallery:

$leftarrow.click(function(){
  if (index == 0) {
    // set it to the last item
    index = galleryLength - 1
  } else {
    index--;
  }
  // now we need to get the link at the new index
  $link = $('#imageGallery a').eq(index);

  // Use this link to retrieve the href of the link and the alt text of the image within it.
  // Use those to set the source of the image and the caption text of the lightbox
  // Similar to what is done in the click handler for the link
});

I used the .eq() method here. All of the links are selected and then the set is reduced down to the one at the supplied index.

Let me know if I've missed something since none of this is tested or if you have any questions about how the code works.

Post back with updated code if either of you are still stuck.

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

Thank you for your help. I ended up using a plug in for this as I couldn't work out the code, but will use your advice to see if I can work through it now. Thank you for your time it is much appreciated.

Brian Hayes
Brian Hayes
20,986 Points

I'm sorry, but this is a little tough to read through. In the future you should take a look at the markdown cheetsheet link to better format you're questions. Putting your code into code blocks will help a lot.

What I think I am seeing is you trying to append html with variables that contain the html you want to add. The issue I think I'm seeing, however, is that you are using the the jQuery object $ and sticking those strings inside of it, instead of just having those variables contain the strings as is. By doing this, jQuery tries to target what is passed as a value to the method. So, all you really end up storing in those variables is probably a return of undefined or something.

I think what you need to do is take this:

var $buttonNext = $("<button> > </button>"); 

var $buttonPrevious = $("<button> < </button>");

and make it look like this:

var buttonNext = '<button> > </button>';

var buttonPrevious = '<button> < </button>';

Just an extra note here: I use single quotations when dealing with strings that contain html so that if i need to have double quotations with in the string, i won't run into problems. In this case, however, both single and double quotes will work.

That way, when you call those variables and pass them through the append method on a jQuery object, you are passing the html markup as a string, which is what the method is expecting.

Not everything needs to be a jQuery object. jQuery objects are meant to target nodes in the DOM structure, so if you aren't trying to get an element, or affect it, then you don't need to use it.

I hope that helps somewhat with what you are trying to do.

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

Thank you for taking the time to help me, sorry about the badly pasted code. I have been doing some code practice exercises to help me improve my use of jquery, this has been helpful. Thank you for the tips.

Hi Joey,

Doing this

var $buttonNext = $("<button> > </button>");

creates a dom element. The reason you would want to do it that way is so that you can attach a clicker handler to it as well as append it to the html.

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

Thank you for taking the time to help me, sorry about the badly pasted code. I have been doing some code practice exercises to help me improve my use of jquery, this has been helpful. Thank you for the tips.