Isotope - dynamically load images with loading gif

For image galleries. First use small images for start-up. Then, when clicked, large high-res images are loaded dynamically. When large image is loaded, isotope is triggered again.

by Avinashullal

HTML

<script src="http://isotope.metafizzy.co/jquery.isotope.min.js"></script>
<p>Click for hi-res</p>
<div id="container" class="photos clearfix">
    <div class="photo"> <a href="http://fc06.deviantart.net/fs71/i/2011/083/2/5/moment_in_time_by_dyingstate-d3cd5jt.jpg"><img class="small-image" src="http://fc06.deviantart.net/fs71/i/2011/083/2/5/moment_in_time_by_dyingstate-d3cd5jt.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://fc09.deviantart.net/fs71/i/2011/155/0/1/belle_de_mai_by_dyingstate-d3i1civ.jpg"><img class="small-image" src="http://fc09.deviantart.net/fs71/i/2011/155/0/1/belle_de_mai_by_dyingstate-d3i1civ.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://fc09.deviantart.net/fs71/i/2011/195/d/7/distant_dreamer_by_dyingstate-d3r7wtz.jpg"><img class="small-image" src="http://fc09.deviantart.net/fs71/i/2011/195/d/7/distant_dreamer_by_dyingstate-d3r7wtz.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://th05.deviantart.net/fs71/PRE/i/2012/119/e/5/_it__s_the_little_things__by_lokiwolf14-d3kdlio.jpg"><img class="small-image" src="http://th05.deviantart.net/fs71/PRE/i/2012/119/e/5/_it__s_the_little_things__by_lokiwolf14-d3kdlio.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://th05.deviantart.net/fs70/PRE/i/2011/157/3/c/lullaby_by_mebilia-d3i728e.jpg"><img class="small-image" src="http://th05.deviantart.net/fs70/PRE/i/2011/157/3/c/lullaby_by_mebilia-d3i728e.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://fc03.deviantart.net/fs70/f/2011/171/c/9/c9b5ebbe30d49ad92754ff97ad1bcdaa-d3jewus.jpg"><img class="small-image" src="http://fc03.deviantart.net/fs70/f/2011/171/c/9/c9b5ebbe30d49ad92754ff97ad1bcdaa-d3jewus.jpg" /></a>

    </div>
    <div class="photo"> <a href="http://fc04.deviantart.net/fs71/f/2011/116/4/0/400980400b9241c25dc56c6446d8e838-d3ey4re.jpg"><img class="small-image" src="http://fc04.deviantart.net/fs71/f/2011/116/4/0/400980400b9241c25dc56c6446d8e838-d3ey4re.jpg" /></a>

    </div>
  ...

CSS

body {
    font-family: Segoe UI ;
    font-size: 20px;
    background-color:#C0E6FF;
}
#container {
    border: 2px solid #A2A2A2;
    width: 800px;
    background-color:#68C6E4;
}
.photo {
    width: 200px;
    float: left;
}
.photo.double {
    width: 480px;
}
.photo.large {
    width: 600px;
    z-index: 3;
}
.photo.large .small-image, .photo .big-image {
    display: none;
}
.photo .small-image, .photo.large .big-image {
    display: block;
}
.photo img {
    display: block;
    width: 100%;
}
.photo .loading {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
    z-index: 10;
    background: hsla(0, 0%, 100%, 0.7);
}
.photo .loading span {
    position: absolute;
    left: 50%;
    top: 50%;
}
.photo .loading img {
    width: auto;
    position: absolute;
    left: -16px;
    top: -16px;
}
/* Start: Recommended Isotope styles */

/**** Isotope Filtering ****/
 .isotope-item {
    z-index: 2;
}
.isotope-hidden.isotope-item {
    pointer-events: none;
    z-index: 1;
}
/**** Isotope CSS3 transitions ****/
 .isotope, .isotope .isotope-item {
    -webkit-transition-duration: 0.8s;
    -moz-transition-duration: 0.8s;
    transition-duration: 0.8s;
}
.isotope {
    -webkit-transition-property: height, width;
    -moz-transition-property: height, width;
    transition-property: height, width;
}
.isotope .isotope-item {
    -webkit-transition-property: -webkit-transform, opacity;
    -moz-transition-property: -moz-transform, opacity;
    transition-property: transform, opacity;
}
/**** disabling Isotope CSS3 transitions ****/
 .isotope.no-transition, .isotope.no-transition .isotope-item, .isotope .isotope-item.no-transition {
    -webkit-transition-duration: 0s;
    -moz-transition-duration: 0s;
    transition-duration: 0s;
}
/* End: Recommended Isotope styles */

JavaScript

$(function () {

    var $container = $('#container'),
        $photos = $container.find('.photo'),
        $loadingIndicator = $('<div class="loading"><span><img src="http://i.imgur.com/IE7iw.gif" /></span></div>');

    // trigger Isotope after images have loaded
    $container.imagesLoaded(function () {
        $container.isotope({
            itemSelector: '.photo',
            masonry: {
                columnWidth: 200
            }
        });
    });

    // shows the large version of the image
    // shows small version of previously large image
    function enlargeImage($photo) {
        $photos.filter('.large').removeClass('large');
        $photo.addClass('large');
        $container.isotope('reLayout');
    }

    $photos.find('a').click(function () {
        var $this = $(this),
            $photo = $this.parents('.photo');

        if ($photo.hasClass('large')) {
            // already large, just remove
            $photo.removeClass('large');
            $container.isotope('reLayout');
        } else {
            if ($photo.hasClass('has-big-image')) {
                enlargeImage($photo);
            } else {
                // add a loading indicator
                $this.append($loadingIndicator);

                // create big image
                var $bigImage = $('<img>', {
                    src: this.href
                });

                // give it a wrapper and appended it to element
                $('<div>', {
                    'class': 'big-image'
                })
                    .append($bigImage)
                    .appendTo($this)
                    .imagesLoaded(function () {
                    $loadingIndicator.remove()
                    enlargeImage($photo);
                });

                // add a class, so we'll know not to do this next time
                $photo.addClass('has-big-image');

            }
        }

        return false;
    });

});