Search

Image Loading

Posted on 4th February 2008 — Daniel Mee requested a tutorial and writes:

I have a large image (500k). I have a loading gif (little rotating circle thingy from ajaxload.info). I want the animated gif to be swapped with the large image once it’s loaded. The event may be on page load or may be some button onClick…

This is similar to how a LightBox would work, except Daniel wants complete control of the the load event.

This tutorial will show how to load images in the background, and once loaded handle the event and create your own response.

Basic Version

In our basic version, we will have a single div containing a loading spinner and once our large image is loaded (in the background) we will remove the spinner and insert our image.

There’s a few ways to approach the loading screen, two of which are:

  1. Use a background image on the holder div, this way we can easily centre align horizontally and vertically using CSS, rather than adding extra markup.
  2. Adding a styled div in our holder div, then remove the entire block of markup when the image loads.

I’ve provided a screencast explaining how to achieve this (though it is based on the CSS version, also shows how to do this with a separate loading div).

Watch the jQuery basic image load screencast (alternative flash version)

View the demo and source code used in the screencast

Note that in the demonstration as I am simulating loading a slow to load image by including a script tag at the bottom of the markup. In your real world version, you obviously would not include it.

HTML Markup

The markup (segment) that we’re using is extremely simple. Note, however, I’ve included a ‘loading’ class on the div. This will be manipulated in our jQuery once the image has loaded behind the scenes:

<div id="loader" class="loading"></div>

CSS

For the demo, I’ve set the height and width of the empty div, but also included a background image which indicates something is loading.

You can use any kind of image – I’ve seen applications use much larger animated gifs to simulate a loading message box.

DIV#loader {
  border: 1px solid #ccc;
  width: 500px;
  height: 500px;
}

/** 
 * While we're having the loading class set.
 * Removig it, will remove the loading message
 */
DIV#loader.loading {
  background: url(images/spinner.gif) no-repeat center center;
}

jQuery

The jQuery’s job is to:

  1. Load the image in the background
  2. Hook a load event
  3. Once the image has loaded, strip the loading class and insert the image
// when the DOM is ready
$(function () {
  var img = new Image();
  
  // wrap our new image in jQuery, then:
  $(img)
    // once the image has loaded, execute this code
    .load(function () {
      // set the image hidden by default    
      $(this).hide();
    
      // with the holding div #loader, apply:
      $('#loader')
        // remove the loading class (so no background spinner), 
        .removeClass('loading')
        // then insert our image
        .append(this);
    
      // fade our image in to create a nice effect
      $(this).fadeIn();
    })
    
    // if there was an error loading the image, react accordingly
    .error(function () {
      // notify the user that the image could not be loaded
    })
    
    // *finally*, set the src attribute of the new image to our image
    .attr('src', 'images/headshot.jpg');
});

Added Functionality

The jQuery code used is the constructs of our load function. If we wanted to style the image in any way, add classes or run an Ajax request before showing the image, it would go inside the .load() function.

This functionality could also be placed inside of a .click() event handler or anything else if you wanted to trigger the image loading.

For example, if you had a particular image map linked to this image that you wanted to request via Ajax the contents of the load function would be this:

$(img)
  .load(function () {
    $(this).hide();
    
    // our bespoke ajax hit that's required with the image
    // it will return the HTML for the <map> element and
    // linked <area> element.
    $.ajax({
      url: 'image-map.php',
      data: 'img=' + i.src, // the image url links up in our fake database
      dataType: 'html',
      success: function (html) {
        // because we're inside of the success function, we must refer
        // to the image as 'img' (defined originally), rather than 'this'
        $('#loader')
          .removeClass('loading')
          .append(img)
          .append(html);
          
        // now show the image
        $(img).fadeIn();
      }
    });
  })
  // code continues as before