2
\$\begingroup\$

I can't seem to find a very simple light weight image gallery, so I decided to build my own. I'm not an expert in jQuery/JavaScript, so I was hoping some suggestions could be made to make this production material. I have a working example on jsfiddle.

data-rel will end up being the full size image URL while img src will become the thumb url. I'd like to limit full size images from having to be all loaded at once on page render.

jsFiddle

<div id="gallery">
    <img data-rel="http://2.bp.blogspot.com/-MUcNEVzLIB8/TrStjvP92kI/AAAAAAAABLI/eK3vb1QMrrw/s1600/slide1-new.png" src="http://2.bp.blogspot.com/-MUcNEVzLIB8/TrStjvP92kI/AAAAAAAABLI/eK3vb1QMrrw/s1600/slide1-new.png" style="max-width:150px;max-height:50px"/>

    <img data-rel="http://1.bp.blogspot.com/-KDiH65CZ8Hs/TjO9rQbmt9I/AAAAAAAAAfg/HeVV38ckUzk/s1600/3.jpg" src="http://1.bp.blogspot.com/-KDiH65CZ8Hs/TjO9rQbmt9I/AAAAAAAAAfg/HeVV38ckUzk/s1600/3.jpg" style="max-width:150px;max-height:50px"/>

    <img data-rel="http://4.bp.blogspot.com/-pZuNX8uqQhw/TjO9rDvyC8I/AAAAAAAAAfY/N91storzGWc/s1600/2.jpg" src="http://4.bp.blogspot.com/-pZuNX8uqQhw/TjO9rDvyC8I/AAAAAAAAAfY/N91storzGWc/s1600/2.jpg" style="max-width:150px;max-height:50px"/>

    <img data-rel="http://4.bp.blogspot.com/-y1cPqvkIts8/TjPDKH1-XDI/AAAAAAAAAgA/l8JbwyqcQvI/s1600/hompimenu.jpg" src="http://4.bp.blogspot.com/-y1cPqvkIts8/TjPDKH1-XDI/AAAAAAAAAgA/l8JbwyqcQvI/s1600/hompimenu.jpg" style="max-width:150px;max-height:50px"/>
</div>

<div id="area">test</div>
<div id="button-previous">prev</div>
<div id="button-next">next</div>

JavaScript

$("#gallery img").first().load(function(){
    activeImg($(this));
});

$("#gallery img").on('click, mouseover', function(){
    activeImg($(this));
});

$('#button-next').click(function(){    
    var isLast = $('#gallery img.active').is(':last-child');

    if (isLast) {
        activeImg($('#gallery img').first());
    } else {
        activeImg($('#gallery img.active').next());            
    }          
});

$('#button-previous').click(function(){    
    var isFirst = $('#gallery img.active').is(':first-child');

    if (isFirst) {
        activeImg($('#gallery img').last());
    } else {
        activeImg($('#gallery img.active').prev());            
    }          
});

var activeImg = function($img) {
    $('.active').removeClass('active');

    var imgUrl = $img.addClass('active').data('rel');        
    $("#area").html("<img src='" + imgUrl + "' alt='description' />");
};

CSS

#button-previous {float:left;}
#button-next {float:right;}
img{border:1px solid #000}
img.active{border-color:red}
\$\endgroup\$
  • \$\begingroup\$ Welcome to Code Review! Great question and kudos for providing a fiddle. +1! \$\endgroup\$ – Phrancis Oct 31 '14 at 21:07
2
\$\begingroup\$

Why not make it a jQuery plugin?

A basic example to get you started:

(function ($, window, undefined) {

    $.fn.gallery = function() {

        var $nextButton = this.find('div.button-next'),
            $previousButton = this.find('div.button-previous'),
            $images = this.find('img');

        $images.on('click, mouseover', function(e){
            activeImage($(e.target));
        });

        $nextButton.on('click', function(){
            var activeIndex = $images.filter('.active').index(),
                nextIndex = (activeIndex + 1 !== $images.length) ? activeIndex+1 : 0,
                $nextImage = $images.eq(nextIndex);

            activeImage($nextImage);
        });

        function activeImage($img) {
            $images.removeClass('active');
            $img.addClass('active');
        };

        return this;
    };

})(jQuery, window);

$(function(){
    $('#gallery').gallery();
});

http://jsfiddle.net/4Lgtecx0/1/

I changed your id:s to classes in the code above so that you can have multiple galleries on the same page.

activeImage() will no longer pollute the global namespace.

Elements are cached instead of looked up over and over again (e.g. $('#gallery') vs this).

Keep in mind that the load event doesn't work on cached images in IE. On the other hand, you don't need to listen for the load event - just apply the class to the first element as in my fiddle.

\$\endgroup\$
  • \$\begingroup\$ Thanks Johan, What do you recommend doing with the main image? I see that was missing in your example. Shouldn't that be a part of the plugin as well so that we can utilize the click/mouse event handler? Also I see the preloaded image is missing, any recommendations? \$\endgroup\$ – Code Junkie Nov 1 '14 at 5:13
  • \$\begingroup\$ I added those few missing pieces back in, just curious as to what your thoughts were. jsfiddle.net/4Lgtecx0/7 \$\endgroup\$ – Code Junkie Nov 1 '14 at 6:05
  • \$\begingroup\$ I intentionally left some parts for you to figure out yourself ;) In short it looks good. Perhaps make a common function to handle next/prev. Keep your code DRY. Also, I'd make a fixed grid so that your images don't jump around depending on size. Something to consider when you're in the CSS. If you want your plugin more flexible, look in to passing some options to it, like this learn.jquery.com/plugins/basic-plugin-creation/… \$\endgroup\$ – Johan Nov 1 '14 at 19:39
  • 1
    \$\begingroup\$ Thanks Johan, in production I have a responsive design that also prevents jumping around as you'll see here, cardaddy.com/forsale/vehicle/… Anyhow, I'll work on further improvements, thank you again. \$\endgroup\$ – Code Junkie Nov 3 '14 at 2:04
2
\$\begingroup\$

It's quite fine, but it can be simplified a little bit. In the HTML, the img elements all have the same style value. It would be better to remove the style attribute from all the img, and define in the stylesheet instead:

#gallery img {
    max-width:150px;
    max-height:50px;
}
\$\endgroup\$
  • \$\begingroup\$ Yes I agree and thanks, I probably should have done that for the demo, but I was a bit more focused on the js side. \$\endgroup\$ – Code Junkie Nov 1 '14 at 4:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.