jdlm
jdlm

Reputation: 6644

Image fires onload event, but image is still undefined

I have a fiddle located here illustrating my problem, namely that when I load images using the Image object, onload gets called but the returned object is still undefined.

Here's the code in case the fiddle were to disappear into the void:

var ImageManager = function() {
    var _images = [], 
        _loaded = 0;

    var precache = function(imageArray) {
        if (!(imageArray instanceof Array)) {
            return;
        }

        for (var i = 0; i < imageArray.length; i++) {
            if (typeof imageArray[i] !== 'string') {
                continue;
            }

            _images[i] = new Image();
            _images[i].onload = function() { 
                _loaded++;
                document.write('<p>Successfully loaded: ' + imageArray[i] + ' [' + _loaded + '/' + imageArray.length + ']</p>'); 
            }
            _images[i].onerror = function() {
                document.write('<p>Unable to load: ' + imageArray[i] + '</p>'); 
            }
            _images[i].src = imageArray[i];
        }
    };

    var get = function(imagePath) {
        if (!_images.hasOwnProperty(imagePath)) {
            document.writeln('<p>' + imagePath + ' isn\'t precached!</p>');
            return null;
        }

        return _images[imagePath];
    };    

return { get: get, precache: precache }
};

// Test case starts here:

var testImages = [
    'http://jsfiddle.net/img/logo.png',
    'http://jsfiddle.net/img/logo.png',
    'http://jsfiddle.net/img/logo.png'
];

var imageManager = new ImageManager();
imageManager.precache(testImages);

Sample output:

Successfully loaded: undefined [1/3]

Successfully loaded: undefined [2/3]

Successfully loaded: undefined [3/3]

As per usual, it's likely something obvious I'm overlooking. Aid me, ye all-knowing oracles.

Upvotes: 0

Views: 876

Answers (1)

Rob W
Rob W

Reputation: 349002

i inside the event handlers are always equal to imageArray.length - 1, because i increases during the loop. Wrap the loop's body in a closure:

Also, don't use document.write, even for debugging purposes. Use console.log(..), alert(..) or at least document.body.innerHTML += ...

Demo: http://jsfiddle.net/dpDXp/7/

for (var i = 0; i < imageArray.length; i++) {
    if (typeof imageArray[i] !== 'string') {
        continue;
    }
    (function(i){ //<-- This

        _images[i] = new Image();
        _images[i].onload = function() { 
            _loaded++;
            console.log('Successfully loaded: ' + imageArray[i] + ' [' + _loaded + '/' + imageArray.length + ']'); 
        }
        _images[i].onerror = function() {
            console.log('Unable to load: ' + imageArray[i]); 
        }
        _images[i].src = imageArray[i];
    })(i); //<-- This
}

Upvotes: 1

Related Questions