Having read other people\'s questions I thought
window.onload=...
would answer my question. I have tried this but it executes the code the
<title>Pre Loading...</title>
</head>
<style type="text/css" media="screen"> html, body{ margin:0;
padding:0; overflow:auto; }
#loading{ position:fixed; width:100%; height:100%; position:absolute; z-index:1; ackground:white url(loader.gif) no-repeat center; }**
</style>
<script> function loaded(){
document.getElementById("loading").style.visibility = "hidden"; }
</script>
<body onload="loaded();"> <div id="loading"></div>
<img id="img" src="avatar8.jpg" title="AVATAR" alt="Picture of Avatar
movie" />
</body>
Want a one-liner?
Promise.all(Array.from(document.images).filter(img => !img.complete).map(img => new Promise(resolve => { img.onload = img.onerror = resolve; }))).then(() => {
console.log('images finished loading');
});
Pretty backwards-compatible, works even in Firefox 52 and Chrome 49 (Windows XP era). Not in IE11, though.
Replace document.images
with e.g. document.querySelectorAll(...)
if you want to narrow the image list.
It uses onload
and onerror
for brevity. This might conflict with other code on the page if these handlers of the img
elements are also set elsewhere (unlikely, but anyway). If you're not sure that your page doesn't use them and want to be safe, replace the part img.onload = img.onerror = resolve;
with a lengthier one: img.addEventListener('load', resolve); img.addEventListener('error', resolve);
.
It also doesn't test whether all images have loaded successfully (that there are no broken images). If you need this, here's some more advanced code:
Promise.all(Array.from(document.images).map(img => {
if (img.complete)
return Promise.resolve(img.naturalHeight !== 0);
return new Promise(resolve => {
img.addEventListener('load', () => resolve(true));
img.addEventListener('error', () => resolve(false));
});
})).then(results => {
if (results.every(res => res))
console.log('all images loaded successfully');
else
console.log('some images failed to load, all finished loading');
});
It waits until all images are either loaded or failed to load.
If you want to fail early, with the first broken image:
Promise.all(Array.from(document.images).map(img => {
if (img.complete)
if (img.naturalHeight !== 0)
return Promise.resolve();
else
return Promise.reject(img);
return new Promise((resolve, reject) => {
img.addEventListener('load', resolve);
img.addEventListener('error', () => reject(img));
});
})).then(() => {
console.log('all images loaded successfully');
}, badImg => {
console.log('some image failed to load, others may still be loading');
console.log('first broken image:', badImg);
});
Two latest code blocks use naturalHeight
to detect broken images among the already loaded ones. This method generally works, but has some drawbacks: it is said to not work when the image URL is set via CSS content
property and when the image is an SVG that doesn't have its dimensions specified. If this is the case, you'll have to refactor your code so that you set up the event handlers before the images begin to load. This can be done by specifying onload
and onerror
right in the HTML or by creating the img
elements in the JavaScript. Another way would be to set src
as data-src
in the HTML and perform img.src = img.dataset.src
after attaching the handlers.
This works great:
$(function() {
$(window).bind("load", function() {
// code here
});
});
Here is a quick hack for modern browsers:
var imgs = document.images,
len = imgs.length,
counter = 0;
[].forEach.call( imgs, function( img ) {
if(img.complete)
incrementCounter();
else
img.addEventListener( 'load', incrementCounter, false );
} );
function incrementCounter() {
counter++;
if ( counter === len ) {
console.log( 'All images loaded!' );
}
}
Once all the images are loaded, your console will show "All images loaded!".
What this code does:
incrementCounter
functionincrementCounter
will increment the counterHaving this code in a cross-browser way wouldn't be so hard, it's just cleaner like this.
A little late to the game, but I've found the following method to be the most straightforward:
function waitForImages () {
let isLoading = true
while (isLoading) {
const loading = [].slice.call(document.images).filter(img => img.complete !== true)
if (!loading.length > 0) {
isLoading = true
return
}
}
}
Note that this is blocking code (useful if you're trying to ensure images are loaded in something like phantomjs)
I was about to suggest the same thing Baz1nga said.
Also, another possible option that's maybe not as foolproof but easier to maintain is to pick the most important/biggest image and attach an onload event to only that one. the advantage here is that there's less code to change if you later add more images to your page.