I want a function to run when specific images are loaded, but I don\'t know how to wait for both to load before running. I only know how to chain them, like below:
This fiddle might help. It's a simple generic 'loader'.
http://jsfiddle.net/8baGb/1/
And the code:
// loader will 'load' items by calling thingToDo for each item,
// before calling allDone when all the things to do have been done.
function loader(items, thingToDo, allDone) {
if (!items) {
// nothing to do.
return;
}
if ("undefined" === items.length) {
// convert single item to array.
items = [items];
}
var count = items.length;
// this callback counts down the things to do.
var thingToDoCompleted = function (items, i) {
count--;
if (0 == count) {
allDone(items);
}
};
for (var i = 0; i < items.length; i++) {
// 'do' each thing, and await callback.
thingToDo(items, i, thingToDoCompleted);
}
}
function loadImage(items, i, onComplete) {
var onLoad = function (e) {
e.target.removeEventListener("load", onLoad);
// this next line can be removed.
// only here to prove the image was loaded.
document.body.appendChild(e.target);
// notify that we're done.
onComplete(items, i);
}
var img = new Image();
img.addEventListener("load", onLoad, false);
img.src = items[i];
}
var items = ['http://bits.wikimedia.org/images/wikimedia-button.png',
'http://bits.wikimedia.org/skins-1.18/common/images/poweredby_mediawiki_88x31.png',
'http://upload.wikimedia.org/wikipedia/en/thumb/4/4a/Commons-logo.svg/30px-Commons-logo.svg.png',
'http://upload.wikimedia.org/wikipedia/commons/3/38/Icons_example.png'];
loader(items, loadImage, function () {
alert("done");
});
I took Paul Grime's example above and modified it to be more understandable while still accomplishing the OP need. I felt the other answers here were either to complicated or not enough. Hopefully this code is a little easier to pick up and put in. I used underscore for the each loop, but this is easy to change.
Also, I improved the solution now to have a callback for on img error. If the image is loaded, it is added to the array, if it fails it is not. I also changed it to utilize jquery.
var loadedImages = [],
imagePaths = [{"src": "myimg.png"}, {"src": "myotherimg.png"}];
loadImages(imagePaths, loadedImages, function(loadedImages) {
console.log(loadedImages)
});
function loadImages(imagePaths, loadedImages, callback) {
if (!imagePaths) { return; }
var count = imagePaths.length;
_.each(imagePaths, function(data, key, list) {
var onLoad = function (e) {
count--;
if (0 == count) {
callback(loadedImages);
}
}
$(document.createElement("img"))
.on('load', function() {
loadedImages.push(data);
onLoad();
})
.on('error', function() { onLoad(); })
.attr("src", data["src"]);
});
},
If you can't use something like jQuery, create a helper function that you can pass to the onload
of all your images you are interested in. Each time it is called, increment a counter, or add the src
name to a set. Once the counter or your set reaches the size of all of the images that you are expecting, then you can fire off whatever work you really wanted to do.
Something like:
var imageCollector = function(expectedCount, completeFn){
var receivedCount;
return function(){
if(++receivedCount == expectedCount){
completeFn();
}
};
}();
var ic = imageCollector(2, function(){alert("Done!");});
Image1.onload = ic;
Image2.onload = ic;