Are you attaching an onload function to an image but finding it doesn't always get called?
The problem is almost always this: you need to set the onload before you set the src. The reason is obvious when you think about it: if the image is in the cache, the image will be loaded immediately after setting the src, even before the onload is set.
Adding fuel to the fire, Firefox and Safari will let you set an onload immediately after (it seems they don't call the onload until the block of JavaScript finishes). This doesn't happen in Internet Explorer or Opera.
Long story short:
// evil:
var image = new Image();
image.src = 'image.jpg';
image.onload = function() {
// sometimes called
alert('image loaded');
};
// good:
var image = new Image();
image.onload = function() {
// always called
alert('image loaded');
};
image.src = 'image.jpg';
No matter how many times I come across this bug and find the solution, I end up making the same mistake a few weeks later. I'm hoping that blogging about it will get this stuck in my long-term memory.
curious as to the need for attaching an onload function to an image.
no, i'm not being a s/a, i'm a noob and want to know. i thoroughly understand you css, your code, and the explanation, now looking for the application/why.
Thanks! And thanks for your blog as well.
@Michael - Sometimes I don't want to show an image until it's completely loaded - for example, you might want to show a low-quality image in the meantime, and swap in the high quality image only when it finishes downloading.
I'm sure there are other uses but that's what I mostly use it for. :)
that totally makes sense.
you're enhancing the user's experience by not
causing the dreaded
'wait for the holes to fill in' syndrome.
thanks for this insight to the technique.
this would give an opportunity for sites to display better quality jpgs but do so without forcing the user to wait. substituting as you mentioned, a lesser quality jpg/image in its place whilst the primo one loads
curiosity again, is this technique a replacement for the lowsrc="xxx.jpg" option?
again though- Thanks for your quick reply.
@Michael - well I'm using it in photo galleries, where the thumbnail image is already loaded.. so I just stretch the thumbnail and put it in place.
I hadn't considered using lowsrc, perhaps that would work just as well. I'll have to try it out. Thanks for the tip.
another use is to display images in a slide show or a similiar application that would necessitate showing an image, and cache-ing the next one to come. so, when image1 loads, start loading image2 and so on. this is particularly valuable when you consider that IE has an issue downloading more than one file from the same host name. in this case you could cascade you image downloading as it may be faster/more fitting to download one image after another.
Just wanted to say thanks for the tip -- I was running into this problem myself and was getting pretty frustrated that it was only causing issues in IE7 (in my particular case), and seemingly intermittently (because of the caching). Moving the Image.src after the Image.onload solved it!
This is neither a bug or a problem. The logic behind it is like this:
The command "image.src = url" fires the downloading method of the image placed in the url you provided. Once that image is finished loading, it fires its onload event. If you define no method in the onload event by the time it is fired, then nothing is in fact supposed to happen on this event.
To me it totally makes sense to first <em>define</em> the method to be called once the onload event is fired, and only then to <em>fire it</em>.
Thanks, Jessie. Very useful.
Thanks Jesse, this saved me when the panic started setting in while working on a project late one night.
this Image() class is quite strange...example:
function(url){
var img = new Image();
img.onload = function() {};
img.src = url;
var width = img.width;
imgArr.push(width);
var height = img.height;
imgArr.push(height);
return imgArr;
}
ie6 - works fine, but in ie7 nope.. it can't upload a picture and define pictures parameters.. also ie7 popups an error becouse unLoad should be written with big 'L'.. so till now i don't know ka to solve the problem..
good luck!
Thanks!
Was getting frustrated why my onload didnt trigger 100% (ie7),
Really saved me some useless wasting of time ;).
While the aesthetic explanations are valid, and I've even used it for that purpose myself, another reason for Image.onload is that the width and height of an image cannot be known until the browser has downloaded the header of the image file. If you access the width and height properties of the image object too soon, you get garbage. If you wait for the onload function to fire, you know those values are there. That may explain why Darius is getting inconsistent results. You need to be accessing the width and height from within the onload function. Unfortunately, this would require some restructuring of your application, since the outer function would not be able to return the values.
thanks that tip helped me alot today on IE7
Simply, you saved my life. Period.
If you come in Rome i need to offer a beer ;)
After an hour of changing things I went searching and came across this post.
Sometimes you feel really stupid!
I am hoping that commenting here will put this in my long term memory!
Thank you
Great post.
Thanks for this...
Unfortunately, in XHTML (and HTML 4.01) "onload", "onerror", and "onabort" are all invalid attributes of the IMG tag. I wrote JavaScript code for my site's home page so that the page displays only when all images are displayed (or error out, or the load is aborted by the user) by assigning a function to each of those three properties to every IMG tag on the page. But now my page fails W3C XHTML validation...!
So seeing your JS code above made me think "Hey, maybe the onload attribute is valid in the DOM, but not in HTML", but going a script-only route would mean anyone without JS enabled would be screwed. And... checking the DOM Level 2 spec, I see in section 1.6.5:
"The load event occurs when the DOM implementation finishes loading all content within a document, all frames within a FRAMESET, or an OBJECT element."
No mention of the IMG element.
Urgh! Should we anticipate the disappearance of these event handling attributes from IMG since they're nonstandard? Or have I misread the standard (as I've done in the past)?
@Alex - well, whether you use HTML attributes or use DOM scripting, it's a JS-only solution either way.
I suggest you use DOM scripting because it works, and that way your HTML will remain valid.
Thanks for posting this! It seems so obvious once you explain it, but it can have you scratching your head for ages until Enlightenment dawns. Thank you!
This was really helpful!! thanks a ton Jesse! spent all day...and finally stumbled across this article -- wish i'd seen it sooner:)
Strange, but the .onLoad doesn't works as supposed to over here.
It fires before the images has finished loading:
preload_image = new Image();
preload_image.onLoad= startTimer();
preload_image.src=image;
Online version:
http://jan-kask.dreamhosters.com/snazzy/test/
( the full-view images should load first.. and then fade in. )
any ideas ?
Mozilla Firefox 2.0.0.13
All hail!
I've been looking into this same issue until I found this post, I'll try now to remeber it myself.
thanks!
r
Great! you save me!! thanks to you and google :-)
Hi,
Thanks for posting this, I was looking in the wrong direction, thinking IE7 was the problem, when it was actually oversight on my part.. Your post really helped out!!