Question

Here is my attempt at the ability to test if all images are loaded:

for (var i = 0; i < imgCount; i ++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src='img'+i+'.png'
    imgArr[i].onload = function() {
        loadArr[i] = true //but wait! At the end of
                          //the loop, i is imgCount
                          //so this doesn't work.
    }
}

The problem is that once the loop is done, the variable i is imgCount. That means all the other "loaded" flags never get set to true when their images are loaded.

Is there some way to add a "loaded" property to an image, or is there some workaround to this problem?

Was it helpful?

Solution

You need to define the onload function using a closure:

for (var i = 0; i < imgCount; i ++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src='img'+i+'.png'
    imgArr[i].onload = (function(i){
        return function(){ loadArr[i] = true }
    })(i);
}

Here's a jsFiddle which demonstrates this working in a similar scenario.

Also, note that the solution you've currently selected as the answer doesn't actually work:

imgArr[i].onload = (function() {
        loadArr[i] = true;
    })();

This function is evaluated immediately. This means that in the loop, each element of the loadArr is set to true as is the onload event. That code is functionally identical to:

imgArr[i].onload = loadArr[i] = true;

OTHER TIPS

You must pass the index value to anonymous function like this,

for (var i = 0; i < imgCount; i++) {
    loadArr[i] = false
    imgArr[i] = new Image()
    imgArr[i].src = 'img' + i + '.png'
    imgArr[i].onload = function (index) {
        return function () {
            loadArr[index] = true //but wait! At the end of
            //the loop, i is imgCount
            //so this doesn't work.
        };
    }(i);
}

This is why closures were made! Your loop runs almost instantly, and it ends long before the first image is loaded. So i==imgCount right away, "skipping" all other values. Closures can avoid this and affect each value of i to a distinct image.

However in your case, I would indeed add a "loaded" attribute to each image.

// Construct your image array
for (var i = 0; i < imgCount; i++) {
    imgArr[i] = new Image();
    imgArr[i].src='img'+i+'.png';
}

//Then iterate over the array, adding a 'loaded' attribute when it occurs
imgArr.each(function(){
    $(this).onload(function() {
        $(this).attr('loaded','true');
    });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top