2

I'm trying to use jQuery to generate my own gallery with a div of clickable thumbnails that show/hide a big image when the corresponding thumbnail is clicked.

I've got it working but only with a known number of images (in this case 3) in the gallery. What if I have 30 images in a gallery? I don't want to have to write out the code below 30 times!

What I really want is to change this code....

$('#slideshow-thumbs img.1').click( function() {
    $('#main-slideshow img.show').removeClass('show').addClass('hide');
    $('#main-slideshow img.1').removeClass('hide');
    $('#main-slideshow img.1').addClass('show');
});

$('#slideshow-thumbs img.2').click( function() {
    $('#main-slideshow img.show').removeClass('show').addClass('hide');
    $('#main-slideshow img.2').removeClass('hide');
    $('#main-slideshow img.2').addClass('show');
});

$('#slideshow-thumbs img.3').click( function() {
    $('#main-slideshow img.show').removeClass('show').addClass('hide');
    $('#main-slideshow img.3').removeClass('hide');
    $('#main-slideshow img.3').addClass('show');
});

...to a format more like this (where n is a number and j is the total number of images in the gallery):

for (n=1; n<=j; n++) {

$('#slideshow-thumbs img.n').click( function() {
    $('#main-slideshow img.show').removeClass('show').addClass('hide');
    $('#main-slideshow img.n').removeClass('hide');
    $('#main-slideshow img.n').addClass('show');
});

}

But I don't know how to write this properly in jQuery as I'm new to it. Would really appreciate some help! I would also like the script to calculate what j (the total number of images in the gallery) is too (by detecting it from the html I assume), so that the script will work for any gallery of any size.

Thanks in advance for any help.

Related HTML:

<div id="main-slideshow">
    <img class="1 show" src="images/booklet-open.jpg"/>
    <img class="2 hide" src="images/booklets.jpg" />
    <img class="3 hide" src="images/poster-1.jpg" />
</div>

<div id="slideshow-thumbs">
    <img class="1 active" src="images/booklet-open-thumb.jpg" />
    <img class="2 inactive" src="images/booklets-thumb.jpg" />
    <img class="3 inactive" src="images/poster-1-thumb.jpg" />
</div>

Related CSS:

.inactive {
    opacity:0.5;
}

.active {
    opacity: 1;
}

.hide {
    display:none;
}

.show {
    display:block;
}
Sarah
  • 744
  • 2
  • 9
  • 26

2 Answers2

1

You were close, just need to use the variable n, and not the string. I've also combined the last two statements, as you don't need to refetch the element. As Danny pointed out, you can find j the following way.

Attempt 1 (Wrong):

var j = $('#slideshow-thumbs img').size()

for (n=1; n<=j; n++) {
    $('#slideshow-thumbs img.' + n).click( function() {
        $('#main-slideshow img.show').removeClass('show').addClass('hide');
        $('#main-slideshow img.' + n).removeClass('hide').addClass('show');
    });
}

However, this solution is susceptible to the looping problem. Essentially, since that part of code is in a closure, it retains reference to the n variable even after the for loop has proceeded. Therefore, when an img is clicked, it looks for the max n value (in this case 4), and nothing happens. To avoid it, try putting the values that use n in an object (in this case, a function). There are numerous solutions, feel free to experiment.

Attempt 2 (Correct):

var j = $('#slideshow-thumbs img').size()

for (n=1; n<=j; n++) {
    $('#slideshow-thumbs img.' + n).click( function() {
        toggleImages(n);
    });
}

function toggleImages(n) {
    $('#main-slideshow img.show').removeClass('show').addClass('hide');
    $('#main-slideshow img.' + n).removeClass('hide').addClass('show');
}
Community
  • 1
  • 1
Igor
  • 33,276
  • 14
  • 79
  • 112
  • 1
    He also wanted `j` to be calculated. Based on his post it is likely something like `$('#slideshow-thumbs img').size()`. – Danny Jan 16 '13 at 20:29
  • Hi, thank you both for your help. I tried adding it to my test page and it's not working? I'm sure it's me (probably my syntax) and not you, I'm really new at this, but: http://www.allatsee.com/gallerytest/test-slideshow.html http://www.allatsee.com/gallerytest/js/slideshow.js @Danny (As a sidenote, I'm a "she" not a "he"...heh) – Sarah Jan 16 '13 at 20:58
  • @user1984868 Which part doesn't work? Can you update your question with the related html? – Igor Jan 16 '13 at 21:06
  • @GrailsGuy When I click on any thumbnail the main image disappears and doesn't reappear, see the test page linked above. I've just realised I removed `.show` from my CSS before I even posted this question as I decided it was irrelevant - but I don't think that matters because as long is `.hide` is removed then the image should display. – Sarah Jan 16 '13 at 21:20
  • @user1984868 Oh, my mistake, it's the looping problem: http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem. Basically, it is always using the max n value, rather than what it is at initialization. I'll update my answer in a minute. – Igor Jan 16 '13 at 21:30
  • @GrailsGuy I still can't get the updated answer to work either. see: http://jsfiddle.net/eaTjM/5/ – Sarah Jan 16 '13 at 21:49
0

You don't need so many classes and for loop. Look at this demo http://jsfiddle.net/eaTjM/1/

$("#slideshow-thumbs img").click(function(){
  $(this).addClass("active").siblings().removeClass("active");
  $("#main-slideshow img").eq($(this).prevAll().length)
    .addClass("show").siblings().removeClass("show")
});

$(this).prevAll().length gives us clicked preview index and .eq() method gives image by this index.

antejan
  • 2,594
  • 12
  • 15
  • Thank you, this worked, although to be honest I don't quite understand how it does! I will try and investigate both of the answers I've been given, thank you again for your help! – Sarah Jan 16 '13 at 21:35