views:

428

answers:

2

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.

+1  A: 

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.

Matt Smith
Awesome, big thanks, learnt a lot from this.
Dr. Frankenstein
demo is now using the code above
Dr. Frankenstein
Currently you have the float left CSS positions on your images make sure you add "overflow:hidden" to the LI elements surrounding them.
Matt Smith
Thanks - that makes sure they are visible - but the opacity changes are not happening unfortunately.
Dr. Frankenstein
I've changed the code to suit your situation. the opacity is now applied to the img elements not the anchor tags, this may be required because of your CSS.Another option to try is looking at your CSS for the LI and A elements . I would normally float the LI elements and then give the A tags the display property of "block".
Matt Smith
OK I've followed your advice with the CSS, and added the new code to the demo, I'm still having hover trouble though after a click. Don't you just love javascript :)
Dr. Frankenstein
OK I've changed the code and this time it's written in exactly the same way as your functions file. I've tested it in webkit with a copy of your files and it works OK for me.
Matt Smith
Thank you Matt. Top drawer, thanks for your persistence, I've learnt a lot.
Dr. Frankenstein
A: 

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.
fudgey
thanks for the vote of confidence fudgey
Matt Smith
Although my code is probably merely scratching the surface of jquery and js in general, by hand coding, I was one bug away from my goal, and I learnt a lot in the process. From looking at M.S's example, I have learnt a wealth more. If i used a plugin, I personally would learn nothing, I would go for minified version of the scripts, and spend time trying to hack it to the clients needs which would not feel productive, rather destructive, I'd be trying to overide out the functionality of the plugin, I'm sure the plugin rocks, though in this case it looks overkill for my small requirements.
Dr. Frankenstein
I appreciate that you want to learn, I myself am learning a lot from the experienced people here and I was merely suggesting making your life easier :P... I did look more in depth at your code and added a few comments to my post above. BTW, Firebug is your friend :)
fudgey
fudgey - thanks for your detailed analysis - I suspected "live" could help me out a lot with this one. Please remove the url from this page. I'll be taking it out of my post as soon as I've got the situation resolved. Thanks.
Dr. Frankenstein
Also - where is your evidence that "hover is not supported with the current version of jquery"? There's nothing mentioned here - http://docs.jquery.com/Events/hover
Dr. Frankenstein
There is information on the jQuery 'live' page... it doesn't say specifically that hover isn't supported, but it's not on the list of supported events: `click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup` and also I've attempted to use a live hover without success - you could potentially use the livequery plugin if you must use hover (but don't quote me on this).
fudgey
Ahh cool, I'm with you now, live hover support is not supported, thanks.
Dr. Frankenstein