user1293977
user1293977

Reputation: 149

Javascript image preloader doesn't show status

I put together an image preloader which works fine, but what doesn't work is updating the status after every image that has been loaded. Instead, all images are loaded and "done" (last line) is the only thing that shows up. It does work when I use an alert instead of the innerHTML command, but that is obviously of no use. What am I doing wrong?

<div id="preloader">
<span id="preloader_status"> </span>
<script language="JavaScript">
    imageObj = new Image();
    images = new Array();
    images[0]="bigimage.gif"
    images[1]="anotherbigimage.gif"
    /* and so on */

    var i = 0;
    var o = (images.length);

    for (i=0;i<o;i++) {
        var status = (Math.round(100*(i/o)));
        imageObj.src=images[i];
        document.getElementById("preloader_status").innerHTML = status;
    }
    document.getElementById("preloader_status").innerHTML = "done";
 </script>
 </div>

Upvotes: 0

Views: 409

Answers (2)

jfriend00
jfriend00

Reputation: 707318

To show image load progress, you will need to hook into the onload event for the images so you can track when their loading is actually complete. Images are loaded asychronously so assigning .src only STARTS the loading of the image. It is not completed until later when the onload handler is called. Because of that, your existing code will just immediately show "done" because it isn't tracking when the images are actually done loading.

In addition, you were successively assigning a new .src value to the same image object which is going to abort the previous image loading. You need to create a new image object for each new image you are loading.

You can fix your code like this:

<div id="preloader">
<span id="preloader_status"> </span>
<script language="JavaScript">
    var imageSrcs = [
        "bigimage.gif",
        "anotherbigimage.gif"
        /* and so on */
    ];

    function preloadImages(list, statusID) {
        var img, cnt = 0;
        var progress = document.getElementById(statusID);
        var preloads = [];

        for (var i = 0; i < list.length; i++) {
            img = new Image();
            img.onload = function() {
                ++cnt;
                var loadPercent = Math.round(100*(cnt/list.length));
                progress.innerHTML = loadPercent;
                if (cnt == list.length) {
                    progress.innerHTML = "done";
                }
            }
            img.src = list[i];
            preloads.push(img);
        }
    }

    preloadImages(imageSrcs, "preloader_status");
 </script>
 </div>

Upvotes: 1

Mark Bell
Mark Bell

Reputation: 29745

The for loop will happen almost instantly, because images load asynchronously; setting imageObj.src will just start the image request and move on to the next. It will not block the execution of the loop. This will cause the effect you're seeing, i.e the last line of the code is executed straight away.

I think what you're looking for is the JavaScript Image onload event, which will fire when an image has finished loading.

var image = new Image();
image.onload = function() {
    // always called
    alert('image loaded');
};
image.src = 'image.jpg';

Code was pinched from this article.

Upvotes: 1

Related Questions