Question

Trying to get my rollovers to change src on rollover. This is working ok, though there is a bug. After I have clicked on a thumbnail, the src can sometimes contain the wrong src (the rollover state remains even on mouseout). . To find the bug, click on a few thumbnails and mouseover a few, you should see the rollover src remain for ones that have been clicked already. Demo is no longer available, sorry!

The jQuery -

function image_gallery (){

if ($('ul.thumbs').length > 0) {
    $('.gallery').each(function(){
        $('ul.thumbs li img:gt(0)').addClass('unselected');
        $('ul.thumbs li img:eq(0)').addClass('selected');

        function mouse_overs () {
            var unselected = $('li img.unselected');
            unselected.hover(function(){
                    var thumb = $(this);
                    thumb.attr('src',thumb.attr('src')
                           .replace(/([^.]*\d)\.(.*)/, "$1r.$2"));
                }, function(){
                      var thumb = $(this);
                  thumb.each(function(){
                      $(this).attr('src',$(this)
                           .attr('src').replace('r.jpg','.jpg'));
                  });
            });
        };
        mouse_overs();
        var img_main = $(this).find('img.main:first');
        $(this).find('ul.thumbs img').each(function(){
            $(this).click(function(){
                var thumb =  $(this);
                var src = thumb.attr('src');
                if ( src.indexOf('r.jpg') == -1) {
                     $(this).attr('src',thumb.attr('src')
                                .replace(/([^.]*)\.(.*)/, "$1r.$2"));
                }
                var selected = $('ul.thumbs li img.selected');

                // previous img remove r.jpg
                selected.attr('src',selected.attr('src')
                                    .replace('r.jpg','.jpg'));
                  selected.removeClass('selected');
                selected.addClass('unselected');

                //current thumb add class "selected", remove "unselected"
                thumb.addClass('selected');
                thumb.removeClass('unselected');
                mouse_overs();
                var rel = $(this).parent('a').attr('rel');
                img_main.fadeOut(500, function(){
                    img_main.attr('src', rel);
                    img_main.fadeIn('slow');
                });

                thumb.mouseout(function(){
                    var src = $(this).attr('src');
                    if ( src.indexOf('r.jpg') == -1) {
                        $(this).attr('src',thumb.attr('src')
                                      .replace(/([^.]*)\.(.*)/, "$1r.$2"));
                    }
                    else return false;
                });
            });
});
    });
   }
}

The HTML:

<div class="gallery">
<img class="main" src="images/gallery/yes-campaign/NL1.jpg"/>
<ul class="thumbs">
        <li><a rel="images/gallery/yes-campaign/NL1.jpg"><img src="images/thumbs/yes-campaign/NL-1r.jpg"/></a></li>
        <li><a rel="images/gallery/yes-campaign/NL2.jpg"><img src="images/thumbs/yes-campaign/NL-2.jpg"/></a></li>
        <li><a rel="images/gallery/yes-campaign/NL3.jpg"><img src="images/thumbs/yes-campaign/NL-3.jpg"/></a></li>
        <li><a rel="images/gallery/yes-campaign/NL4.jpg"><img src="images/thumbs/yes-campaign/NL-4.jpg"/></a></li>
    </ul>
</div>

This HTML is repeated various times throughout the page. The rollover states are NL1r.jpg, NL2r.jpg etc. The images are organized in folders, so all image filenames use the same naming convention.

Was it helpful?

Solution

Can I suggest the following code instead of yours?

$(function gallery (){

        var transparency = .5;
        var selectedClassName = 'selected';
        var imageFadeSpeed = 'fast';

        $('.gallery').each(function(i, gallery) {
            var $gallery = $(gallery);

            var $main = $gallery.find('.main');

            $gallery.find('.thumbs a')

                // image preloader
                .each(function(){
                    var tempImg = $('<img src="'+ $(this).attr('rel') +'" width="'+ $main.width() +'" />').appendTo('body').hide();
                })

                .hover(function() {
                    if ($(this).is('.'+selectedClassName))
                        return;
                    $(this).children().css('opacity', 1);
                }, function() {
                    if ($(this).is('.'+selectedClassName))
                        return;
                    $(this).children().css('opacity', transparency);
                })

                .click(function(ev) {
                    ev.preventDefault();

                    var self = $(this);

                    $main.fadeOut(imageFadeSpeed, function() {                      
                        var tempImg = $('<img src="'+ self.attr('rel') +'" width="'+ $main.width() +'" />').appendTo('body');
                        var newHeight = tempImg.height();
                        tempImg.remove();

                        $(this)
                            .attr('src', self.attr('rel'))
                            .height(newHeight);

                        $(this).fadeIn(imageFadeSpeed);
                    });

                    $gallery.find('.'+selectedClassName)
                        .removeClass(selectedClassName)
                        .children()
                        .css('opacity', transparency);

                    self
                        .addClass(selectedClassName)
                        .children()
                        .css('opacity', 1);
                    return;
                })

                .children()
                .css('opacity', transparency)
                .end()

                .filter(':first')
                .addClass(selectedClassName)
                .children()
                .css('opacity', 1);
        });
});

I've replaced your image swap on hover with an opacity change which cuts down on server load but you could easily replace these with src swapping. you will need to use the images with the "r.jpg" ending only.

I've also pulled out some config variables so you can play around with things a bit.

OTHER TIPS

Although I think Matt did a terrific job with the script (+1 for that), I'd still recommend using the GalleryView plugin (Demo here).


I'm still learning as well, so I may not be correct in my assumptions below so feel free to correct me if I'm wrong. But after taking another look at your code, I wanted to add these comments:

  • Your mouse_overs function appears to fix the initial "unselected" classes. The best way around it would be to use jQuery's "live" event handler. This way when you change your selected class to unselected, or vice-versa, the live event will update (Note: hover is not supported with the current version of jquery, so you'd have to use mouseover and mouseout). It also appears that the mouseover portion of the hover is called 3 times which might also be related.
  • The regex used in the replace function isn't working properly. After clicking on a thumbnail to switch the image, I noticed that as soon as you mouseout (which is from the thumb.mouseout function), the URL started adding r's to the end of the word static... after about 10 mouseouts, I ended up with this URL "http://staticrrrrrrrrrr.yourdomain.com/someimage.jpg". I don't know my regexp very well, so I can't help you fix this.
  • Instead of modifying the URL it would be much easier to do as Matt suggested and use opacity, but if you want to use a different image, I'd store the URL in the img's rel attribute and just switch it that way, then it would be less likey for a problem to occur with the URL.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top