Image preloader javascript that supports events
Here's a function that will preload images from an array and call your callback when the last one has finished:
function preloadImages(srcs, imgs, callback) {
var img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
img.onload = function() {
--remaining;
if (remaining <= 0) {
callback();
}
};
img.src = srcs[i];
imgs.push(img);
}
}
// then to call it, you would use this
var imageSrcs = ["src1", "src2", "src3", "src4"];
var images = [];
preloadImages(imageSrcs, images, myFunction);
And since we're now in the age of using promises for asynchronous operations, here's a version of the above that uses promises and notifies the caller via an ES6 standard promise:
function preloadImages(srcs) {
function loadImage(src) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
resolve(img);
};
img.onerror = img.onabort = function() {
reject(src);
};
img.src = src;
});
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}
preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});
And, here's a version using 2015 jQuery promises:
function preloadImages(srcs) {
function loadImage(src) {
return new $.Deferred(function(def) {
var img = new Image();
img.onload = function() {
def.resolve(img);
};
img.onerror = img.onabort = function() {
def.reject(src);
};
img.src = src;
}).promise();
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return $.when.apply($, promises).then(function() {
// return results as a simple array rather than as separate arguments
return Array.prototype.slice.call(arguments);
});
}
preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});
Preloading images with JavaScript
Yes. This should work on all major browsers.
Preloading images in an array (and waiting until they have downloaded)
Here's a much, much simpler way to preload images and have it call a callback when the images are done loading in a related prior question/answer: Image preloader javascript that supports events.
onerror event not being detected during image preloading?
onerror
is asynchronous. It happens sometime in the future. You are testing the valid
variable long before onerror
or onload
has even run. If you only want to push good images into the array, then you should just push them into the array in the onload
handler like this:
for(i = 0; i < imgURLs.length; i++) {
var img = new Image();
img.onload = function(){
console.log('New Media Loaded')
goodArray.push(this);
};
img.onerror = function(){
console.log('error: bad image source');
};
img.src = url;
}
FYI. Note, I'm also pushing this
, not img
because the variable img
has been changed by the subsequent iterations of your for
loop, but this
will be the image that just successfully loaded.
If you want an image preloader that will notify when the last image has loaded, you can use the code form this answer.
Caching preloaded images possible over page switch?
The browser already caches the images in its memory and/or disk cache as long as the headers coming from the server aren't telling it to avoid caching. The browser cache endures across page loads. SO, if your images have been loaded once on the first page, they should be in the browser cache already for the second page and thus when requested on the second page, they should load locally and not have to be fetched over the internet.
If you're looking for client-side code that can be used to preload images, there are many examples:
How do you cache an image in Javascript
Image preloader javascript that supports events
Is there a way to load images to user's cache asynchronously?
FYI, it is possible in newer browsers to use a combination of Local Storage and data URIs to implement your own image caching, but I'd be surprised if there was any real world situation where that was required and if you have a lot of images, you may run into storage limits on Local Storage quicker than limits on the size of the browser cache.
Fire an event after preloading images
You can use the new "$.Deferred" if you like:
var preload = ["a.gif", "b.gif", "c.gif"];
var promises = [];
for (var i = 0; i < preload.length; i++) {
(function(url, promise) {
var img = new Image();
img.onload = function() {
promise.resolve();
};
img.src = url;
})(preload[i], promises[i] = $.Deferred());
}
$.when.apply($, promises).done(function() {
alert("All images ready sir!");
});
Might be a little risky to leave the Image objects floating around, but if so that could be fixed easily by shifting the closure. edit in fact I'll change it myself because it's bugging me :-)
JQuery - Preload Images (using JQuery / native JavaScript / CSS)
You can preload an image quite easily as follows:
using JQuery
function preloadImg(src) {
$('<img/>')[0].src = src;
}
preloadImg('http://yoururl/to/the/picture.jpg');
or Native Javascript
function preloadImg(src) {
var img = new Image();
img.src = src;
}
preloadImg('http://yoururl/to/the/picture.jpg');
or Using CSS (no JavaScript required)
You can also preload images using CSS (and HTML)
CSS: div#preload { display: none; }
HTML:
<div id="preload">
<img src="http://yoururl/to/the/picture1.jpg" width="1" height="1" alt="Image 1" />
<img src="http://yoururl/to/the/picture2.jpg" width="1" height="1" alt="Image 2" />
<img src="http://yoururl/to/the/picture3.jpg" width="1" height="1" alt="Image 3" />
</div>
Preloading images with jQuery
Quick and easy:
function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
// Alternatively you could use:
// (new Image()).src = this;
});
}
// Usage:
preload([
'img/imageName.jpg',
'img/anotherOne.jpg',
'img/blahblahblah.jpg'
]);
Or, if you want a jQuery plugin:
$.fn.preload = function() {
this.each(function(){
$('<img/>')[0].src = this;
});
}
// Usage:
$(['img1.jpg','img2.jpg','img3.jpg']).preload();
Retrieve preloaded image from cached array
You're going to have to make sure you can somehow retrieve the img
elements you've preloaded. There are many ways to do this but three that come to mind straight away.
1. Added loaded image in the DOM
In your example you're trying to retrieve the images with a query selector. This fails because the img
elements aren't added to the DOM. You could attach them to a DOM element that is hidden from the user.
var
images = [
{
src: '//placehold.it/550x250?text=A',
top: 0,
class:'img-a' // unique class name to retrieve item using a query selector.
},
{
src: '//placehold.it/550x250?text=B',
top: 0,
class:'img-b'
}],
imageCache = document.getElementById('image-cache');
function preloadImages(srcs) {
function loadImage(imgToLoad) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
// The image has been loaded, add it to the cache element.
imageCache.appendChild(img);
resolve(img);
};
img.onerror = img.onabort = function() {
reject(imgToLoad.src);
};
img.className = 'testimg ' + imgToLoad.class; //Test to see if I can retrieve img
img.src = imgToLoad.src;
img.style.top = imgToLoad.top;
});
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}
// Load all the images.
preloadImages(images)
.then(result => {
// Add img B from the cache to the proof div.
document.getElementById('proof').appendChild(imageCache.querySelector('.img-b'));
});
.hidden {
display: none;
}
<div id="image-cache" class="hidden"></div>
<div id="proof"></div>
Related Topics
HTML Drag and Drop on Mobile Devices
How to Focus on a Form Input Text Field on Page Load Using Jquery
How to Position a Div in a Specific Coordinates
JavaScript Regex Returning True.. Then False.. Then True.. etc
How Does Inline JavaScript (In HTML) Work
Which Characters Are Valid/Invalid in a JSON Key Name
Replace a Regex Capture Group with Uppercase in JavaScript
How to Delete Document from Firestore Using Where Clause
How to Scrape Pages with Dynamic Content Using Node.Js
JavaScript Syntax (0, Fn)(Args)
How to Solve 'Redirect Has Been Blocked by Cors Policy: No 'Access-Control-Allow-Origin' Header'
Javascript: Using a Condition in Switch Case
Return Positions of a Regex Match() in JavaScript
Uncaught Typeerror: Cannot Read Property 'Msie' of Undefined - Jquery Tools
Javascript: How to Dynamically Create Nested Objects Using Object Names Given by an Array