Image Replacement

by Gaurav Singh

HTML

<ul>
    <li data-image="http://lorempixel.com/120/100/sports" data-placeholder="http://placehold.it/120x100"><h3>Sport</h3></li>
    <li data-image="http://lorempixel.com/120/100/food" data-placeholder="http://placehold.it/120x100"><h3>Food</h3></li>
    <li data-image="http://lorempixel.com/120/100/people" data-placeholder="http://placehold.it/120x100"><h3>People</h3></li>
    <li data-image="http://does-not-esi.st" data-placeholder="http://placehold.it/120x100"><h3>Fails</h3></li>
</ul>

CSS

ul {
    overflow: hidden;
    width: 260px;
    margin: 20px auto;
}

li {
    width: 120px;
    height: 100px;
    float: left;
    background-color: #ccc;
    position: relative;
    border: 1px solid #999;
    margin: 2px;
}

li h3 {
    font-family: 'Oleo Script', cursive;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 32px;
    font-size: 24px;
    line-height: 32px;
    background-color: rgba(0,0,0,0.7);
    color: #fff;
    text-align: center;
}

JavaScript

$(function() {
    //Go through all the elements that should have a background
    $('li').each(function() {
        var $this = $(this),
            img = $this.data('image'),
            ph = $this.data('placeholder'),
            imgObject;
        //First of all, by default assign the placeholder image to all of them
        //This way if an image fails to load the UI is not affected
        $this.css('background-image', 'url(' + ph + ')');
        //Now create an empty Image object 
        imgObject = new Image();
        //Should an image fail to load (e.g. 404), replace the image data with the placeholder
        //in case we need to use it later
        imgObject.onerror = function() {
            $this.data('image', ph);
        };
        //When the image finally loads, replace the background with the final one
        imgObject.onload = function() {
            $this.css('background-image', 'url(' + img + ')');
        };
        //Assign the src property: this forces the browser to preload and
        //possibly cache the image and eventually either the onload or the onerror
        //event will be triggered.
        imgObject.src = img;
    });
});