Pre-loading image(s) with JavaScript & jQuery
<p>I'm using the following code to insert some HTML into a div, and to preload any images that might be contained in that HTML (the html var's data is actually fetched from an AJAX request in the real code). This is to prevent the browser from loading the fetched HTML's images upon showing the div (using the slideDown event) - because this results in the effect's fluidity being broken as it loads image mid-transition. I suppose I could use an interlaced JPEG so that the dimensions of the image are known almost immediately, but obviously it'd be nice to get a cleaner method worked out. :P</p>

<pre><code>var html = '&lt;img src="images/test.jpg" alt="test" /&gt;';

$('div.content').hide().html(html);

$('div.content img').each(function(){

    var img = new Image();

    img.src = $(this).attr('src');

    $(this).attr('src', img.src);

});

$('div.content').slideDown('normal');
</code></pre>

<p>I'm using the Image object and its subsequent assigning as per the advice given <a href="http://stackoverflow.com/questions/257550/php-ajax-best-practice-for-pre-loading-images/257594#257594">here</a>, but unfortunately the image still isn't cached by the browser using this method, because the sildeDown() effect is still interrupted as the image loads.</p>

<p>Any help or alternative methods? Many thanks.</p>

<h2>Edit - 21st Sept 09</h2>

<p><hr /></p>

<p>Progress! Turns out the browser <em>was</em> caching the image, I just wasn't giving it time to do so (it just needed a second to load with an alert() or setInterval()). Now introducing what is probably the messiest code ever - I am using an infinite loop to create that pause.</p>

<p>The new method extends the old code above by binding a function (that adds each image's src to an array) to that image's successful load event. It then gets stuck in an infinite loop as it waits until all the images have loaded and therefore appeared in the array. This seems to work as a way to synchronously pre-load images - but a problem remains; the while() loop for some reason cycles infinitely even once all the images are loaded, <em>unless</em> I add an alert() to pause it for a moment.</p>

<p>The new code:</p>

<pre><code>var html = '&lt;img src="images/test.jpg" alt="test" /&gt;';

$('div.content').hide().html(html);

// define usr variables object
$.usrvar = {};

// array of loaded images' urls
$.usrvar.images = [];

// boolean for whether this content has images (and if we should check they are all loaded later)
$.usrvar.hasimages = false;

// foreach of any images inside the content
$('div.content img').each(function(){

    // if we're here then this content has images..
    $.usrvar.hasimages = true;

    // set this image's src to a var
    var src = $(this).attr('src');

    // add this image to our images array once it has finished loading
    $(this).load(function(){

        $.usrvar.images.push(src);

    });

    // create a new image
    var img = new Image();

    // set our new image's src
    img.src = src;

});

// avoid this code if we don't have images in the content
if ($.usrvar.hasimages != false) {

    // no images are yet loaded
    $.usrvar.imagesloaded = false;

    // repeatedly cycle (while() loop) through all images in content (each() loop)
    while ($.usrvar.imagesloaded != true) {

        $('div.content img').each(function(){

            // get this loop's image src
            var src = $(this).attr('src');

            // if this src is in our images array, it must have finished loading
            if ($.usrvar.images.indexOf(src) != -1) {

                // set imagesloaded to trueai
                $.usrvar.imagesloaded = true;

            } else {

                // without the pause caused by this alert(), this loop becomes infinite?!
                alert('pause');

                // this image is not yet loaded, so set var to false to initiate another loop
                // (ignores whether imagesloaded has been set to true by another image, because ALL
                // need to be loaded
                $.usrvar.imagesloaded = false;

            }

        });

    }

}

$('div.content').slideDown('normal');
</code></pre>
