Coding with Jesse

Getting an Image's onload to Fire

September 28th, 2007

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.


Comments

1 . Michael on September 30th, 2007

Michael

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.

2 . Jesse Skinner on September 30th, 2007

Jesse Skinner

@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. :)

3 . michael on September 30th, 2007

michael

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.

4 . Jesse Skinner on September 30th, 2007

Jesse Skinner

@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.

5 . David on October 1st, 2007

David

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.

6 . Adam Norwood on October 8th, 2007

Adam Norwood

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!

7 . Rotem Harel on October 9th, 2007

Rotem Harel

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>.

8 . Steve on October 10th, 2007

Steve

Thanks, Jessie. Very useful.

9 . Justin McConnell on October 15th, 2007

Justin McConnell

Thanks Jesse, this saved me when the panic started setting in while working on a project late one night.

10 . Darius on October 19th, 2007

Darius

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!

11 . Zishan on November 5th, 2007

Zishan

Thanks!
Was getting frustrated why my onload didnt trigger 100% (ie7),
Really saved me some useless wasting of time ;).

12 . perl on November 18th, 2007

perl

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.

13 . Mike on December 18th, 2007

Mike

thanks that tip helped me alot today on IE7

14 . Diego Guidi on December 21st, 2007

Diego Guidi

Simply, you saved my life. Period.
If you come in Rome i need to offer a beer ;)

15 . Harry on January 7th, 2008

Harry

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

16 . Chris on February 3rd, 2008

Chris

Great post.

Thanks for this...

17 . Alex on February 18th, 2008

Alex

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)?

18 . Jesse Skinner on February 18th, 2008

Jesse Skinner

@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.

19 . Gaurav on February 21st, 2008

Gaurav

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!

20 . Priyanka on March 12nd, 2008

Priyanka

This was really helpful!! thanks a ton Jesse! spent all day...and finally stumbled across this article -- wish i'd seen it sooner:)

21 . Jan Van Lysebettens on April 2nd, 2008

Jan Van Lysebettens

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

22 . rob on April 10th, 2008

rob

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

23 . shaders on April 21st, 2008

shaders

great :)
thanks

24 . Samuele Catuzzi on May 1st, 2008

Samuele Catuzzi

Great! you save me!! thanks to you and google :-)

25 . greg whiteside on May 5th, 2008

greg whiteside

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!!

26 . etuan lecroix on May 15th, 2008

etuan lecroix

Seriously, thank you for sharing this!

27 . howie on May 18th, 2008

howie

Very helpful tip!

After making the suggested change, I was still getting problems with IE not firing the onload when trying to load multiple images.

I believe that the problem is that, as another commenter noted, IE limits the number of connections it can make to the same server (probably for the sake of politeness).

To get around this limitation for multiple images, I ended up loading the next image after the previous onload function was done. Something like:

var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var index = 0;

function loadNextImage() {
if (index < images.length) {
var image = new Image();
image.onload = onImageLoad;
image.src =images[index++];
}
}

function onImageLoad() {
// Do stuff with image
// ....

// Do a setTimeout to call loadNextImage instead of calling
// it directly, which might make a recursive call and cause
// a stack overflow with lots of images.
setTimeout('loadNextImage()', 10);
}

loadNextImage();

28 . matt Sephton on May 26th, 2008

matt Sephton

Thanks for this.

29 . Liam on July 1st, 2008

Liam

Thanks for the tip!
I think a lot of people instinctively set the src and then the onload because that is the order they expect the code to execute. But then you wouldn't call a function before you declare it, would you?
This is one of the catches of defining functions at runtime. I think a general rule to follow in all languages is that if you must define a function at runtime, do it at the earliest possible point in your code.

30 . Eco on July 9th, 2008

Eco

I may say it is a bug because HTML and JS are non procedural.

This is how it works:
1. The browser loads the code.
2. Builds the DOM.
3. Launches events and functions.

Gecko and KHTML are doing their job right, Trident and Presto probably not (As usual)...

31 . Tony on August 20th, 2008

Tony

You are awesome! Fixed my problem on IE7! Thanks!

32 . Duilio on August 27th, 2008

Duilio

it worked!!! Oh my God, I love you so much. I was about to kill myself... you saved my life! Thank you!

33 . Aikheel on September 1st, 2008

Aikheel

Switching the "onload" and "scr" lines solved half my problem. (Thanks!) I have the same problem as Jan Van Lysebettens. Both IE and firfox trigger the onLoad function, but starts downloading the images (again?) when I try to use them later. Any suggestions?

34 . Mike on September 3rd, 2008

Mike

Thanks alot for the article! Saved me lots of potential time loss and frustration :)

35 . Keith on September 17th, 2008

Keith

After coming to the article for a second time, I figured I'd offer a overdue thank you.

Cheers.

36 . LFFATE on October 16th, 2008

LFFATE

How I can get current values such as images height/width using this method?

37 . Jesse Skinner on October 18th, 2008

Jesse Skinner

@LFFATE - you can access them in the onload function:

var image = new Image();
image.onload = function(){
var width = this.width;
var height = this.height;

// do something with width and height
};
image.src = 'http://somewhere.on/the/internet.gif';

38 . Madster on October 19th, 2008

Madster

thankyou thankyou thankyou thankyou.
makes sense but I had totally overlooked it.

39 . andris on October 22nd, 2008

andris

sometime better use document.createElement( 'img' ), because new Image() don't store in browser cache.

40 . Diederik Stenvers on November 20th, 2008

Diederik Stenvers

Wow! I almost spend hours to debug this and your solution is oth simple as it is effective!
Thankx for sharing!

41 . Alex Dickson on November 20th, 2008

Alex Dickson

thank you very much! IE7 was causing me grief with this...

42 . Karan on November 25th, 2008

Karan

Hello Jesse,

The below didn't work in firefox 3. Somehow the onload event didn't fire. Can u suggest any other approach.

// good: var image = new Image(); image.onload = function() { // always called alert('image loaded'); }; image.src = 'image.jpg';

43 . Kim on December 4th, 2008

Kim

Thanks...
You save me.

44 . blaze on December 17th, 2008

blaze

Man, you are the man.

45 . AdamWu on December 30th, 2008

AdamWu

I FOUND the ANSWER!! :D

First, tried as suggested in the blog, and nope, it did not solve the problem -- sometimes it fires, sometimes it won't.

Preloader.prototype.LoadImg = function(url) {
var newImage = new Image();
newImage.onload = this.Loaded.bind(this);
newImage.src = url;
};

But then, OUT OF BLUE, I had the impossible guess in my head: could it be the variable SCOPE problem?

In this case, the image object has no external reference, so it *might* be possible that, when the image was loaded too fast, the *finished* image object got caught by the garbage collector before the javascript call stack is cleaned, and it never had the chance to place the onload call.

So I added an array outside of the function to hold the image object:

Preloader.prototype.LoadImg = function(url) {
var newImage = new Image();
newImage.onload = this.Loaded.bind(this);
newImage.src = url;

this.Images.push(newImage); // Keep the reference!
};

Guess what? Now IE RELIABLY fires onload event, regardless whether the image is in the cache or not!

LOL, I guess it is just another case IE puts a bullet in its own feet...

46 . AdamWu on December 30th, 2008

AdamWu

Okay, life just never gets easier... :D

I just (re)discovered another quirk in IE, which makes using onload event not so desirable.

The problem is that when loading animated GIF, the image object in IE fires onload each time the animation sequence repeats. (Funny that in this case, there is no scope problem anymore...)

To make the problem worse, removing all event handlers from the animated GIF image the first time onload event fires triggers another quirk in IE. Doing so, then create another animated GIF image with *same* url immediately after that, the new image shows up as image placeholder for a very short time window.
(If I don't touch the preloaded GIF image object, the new instance of image is rendered immediately, smooth and seamless, but then I have to endure the endless onload event...)

Finally I solved the problem by hooking onreadystatechange event and watch for the readyState to become 'complete', which, fortunately, is a one-time process for both static and animated image. But, since it is an IE only event for image object, the script has check the browser and hook different events (onload or onreadystatechange) accordingly.

47 . cdonner on January 18th, 2009

cdonner

I don't know what version of IE you are using, Adam. My version of IE does not animate the GIF at all. The onload event fires reliably. Reporting Services has to render a chart, which takes a few seconds. I am displaying the animated GIF in its place. Firefox animates it nicely while waiting for the chart image. IE does not, which defeats the purpose of having it there, sort of. I am looking at ways around this bug.
I did not run into issues with the order of the SRC and ONLOAD parameters.

48 . cdonner on January 18th, 2009

cdonner

The solution was to combine two techniques - CSS preloading and JS to swap the image. Because IE suspends the GIF animation while another image for the same tag is loading in the background, a 2nd (hidden) image tag was needed.

See http://cdonner.com/the-hrml-img-tab-and-onload-event-bugs-in-ie.htm for the code.

49 . masipay on January 30th, 2009

masipay

validating with http://validator.w3.org/check it says onload is not allowed inside img tag, (using doc type transitional)

??

50 . Nietzsche on February 7th, 2009

Nietzsche

Inline Javascript will invalidate your pages. For those of you wondering for a way around this, simply apply the DOM Level 2 model for catching events. It is the modern, preferred approach, and much more efficient than the traditional inline registration model (DOM 0).

Here's an example:

var image = new Image();
image.addEventListener("load", function(){}, false);
image.src = 'image.jpg';

You can either apply the anonymous function to the event listener as done above, or you can define a function elsewhere and write the name of the function where it says function() above, minus the parentheses.

Internet Explorer has it's own event handler (attachEvent), so I suggest reading up on the browser differences, and finding some generic addEvent function online somewhere. There are loads of them.

By the way, thanks for the insight, Jesse. :D

51 . Anon on February 18th, 2009

Anon

Had a problem with this. Thanks for the solution!

52 . Eric on April 3rd, 2009

Eric

Dude you just saved me hours of time...after a good hour of aggravations trying to figure out why my widget wasn't working on IE....and only sometimes on Firefox. Thanks! Whew!

53 . dacre on April 23rd, 2009

dacre

WOW your tip for postponing the .src assignment on images REALLY helped

54 . Dimitar Christoff on May 11st, 2009

Dimitar Christoff

this is quite interesting - i guess the problem is due to primed cache. just wanted to say, thank you.

55 . VkReddy on May 15th, 2009

VkReddy

Hi All,
I still have issues with src and onload working together in sync.
my code looks like this.
<c:when test="${sessionScope.pictureFile != null}" >
<img style="visibility=hidden" src='<c:out value="${sessionScope.pictureFile}" />' id="bankerPic" alt="" onload="window.setTimeout(resizePicture, 30)"/>
</c:when>

if (imageElement != null) {
// to make sure Height && width not equal to zero
h = imageElement.height;
w = imageElement.width;
if ((w > 150) || (h > 210)) {
// Picture bigger than min size - needs to be resized
var dimension = h/w;
if (dimension > 1) {
dimension = w/h;
newW = hSize * dimension;
imageElement.width = newW;
imageElement.height = hSize;
} else {
newH = wSize * dimension; imageElement.height = newH; imageElement.width = wSize;
}
}
}
imageElement.style.visibility='visible';
}
Can some body help me plsssssssss.

56 . Jason on July 5th, 2009

Jason

So simple, but wouldn't have guessed it - thanks!

57 . digitaldokuro on July 30th, 2009

digitaldokuro

THANK YOU! I would never have guessed about putting the src after the function. makes a lot of sense, but just didn't think about it!

58 . criography on August 1st, 2009

criography

D'oh... I just wasted an hour on such an obvious thing... Thanks!

59 . joe on August 21st, 2009

joe

classic micro$oft buggy crap!
i'm glad you posted about it, i was ready to make and sink into some creepy workaround.. thanks

60 . Ben on August 27th, 2009

Ben

I love those quick-n-easy solutions. Big thank you.

61 . soothing on September 1st, 2009

soothing

major props. I thought this was a cache issue and was about to write some hacktastic code. Thank you!

62 . Jon L on September 30th, 2009

Jon L

Nicely written up, many thanks! (Was just about to start puzzling over IE's image-caching mechanics..)

63 . Juan Martín Socorro on October 7th, 2009

Juan Martín Socorro

Very usefull. You saved me a lot of work.

64 . John John K on October 15th, 2009

John John K

OMFG thank you very much!

65 . Vadim on October 16th, 2009

Vadim

Thanks Jesse, it's really useful.

66 . Ryan on October 19th, 2009

Ryan

CSS and input button with hover states need an onload() event handler; otherwise, you'll get a "flicker". The background image called in the CSS file is not displayed until its fully loaded.

67 . Vlad on November 6th, 2009

Vlad

Hi Jesse,
I was struggling with this problem for few days :)
thanks to YOU I can sleep peacefully again :D

68 . actionM on December 22nd, 2009

actionM

Thank you so much. I have been working on this problem for 1.5days now solid. I was about to rip my hair out.

69 . Dal on December 30th, 2009

Dal

Cheers, just what I was looking for, it solved the problem with IE8 but Opera 10.10 doesn't seem to like it?

var inspection = new Image();
inspection.onload = function() {
alert('Found image after load');
}
inspection.src = imagePath;

Sorry didn't get a chance to test it on the previous version to 10.10 so that needs confirming.

Cheers
Dal

70 . Jack on January 6th, 2010

Jack

I'm very interested by this thread, but I can see where is the solution :/

I'm trying to find a way to calculate the time to download an image : timestamp before, then another timestamp triggered by the onload, and calculate the diff


var ndc_time_start = (new Date()).getTime();
NDC = new Image();
NDC.onLoad = NDC_();

function NDC_()
{
var ndc_time_stop = (new Date()).getTime();
var ndc_time_diff = ((ndc_time_stop - ndc_time_start) / 1000);
document.write("Start Time for NDC "+ndc_time_start+" ms<br>")
document.write("Stop Time for NDC "+ndc_time_stop+" ms<br>")
document.write("Diff for NDC "+ndc_time_diff+" ms<br>")
}

NDC.src = 'http://img25.imageshack.us/img25/5315/n382wawoamd11fehbk31220.jpg';

As said, the src is after the onload, but it seems the onload function is called before the img has loaded.

Same with IE7 or firefox 3.5.6

any idea ?

71 . Dal on January 6th, 2010

Dal

Hi Jack,

I'd hazard a guess at the problem being with line;

NDC = new Image();

(by the way, if it's not a constant I would advise against the use of capitals, pick a camelCase or words seperated with '_', sorry, pet hate :/ )

Anyway, try;

var ndc = new Image();

I tend to always declare a variable first as I fell into problems with this in javascript;

for(n = 0; n < x; n++)

Seems memory leaks are the reason why things dont go to plan and they are often the hardest to figure out!

I subsequently sorted this issue by doing;
for(var n = 0; n < x; n++


Cheers
James

Please post back if it worked/failed so others can may be helped.

72 . Jesse Skinner on January 6th, 2010

Jesse Skinner

@Jack Actually I'm thinking it may be this line:

NDC.onLoad = NDC_();

because that assigns the onload to the result of the NDC_ function, and that function doesn't return anything. And that is also why the function is being called before the image loads, it's being called on that line.

What you want to do instead is assign to the function itself by leaving off the ():

NDC.onload = NDC_;

And James/Dal is right, using 'var' is probably a good idea too.

73 . Jack on January 7th, 2010

Jack

updates :)

Having var ndc = new Image(); works as before, not better, not worse, but i'll keep it like that as it's clearner.
Behaviour : It prints everything, then load the image in background.

Leaving off the () is a great idea too, but it seems it breaks the script. The function is not called, I got nothing printed :/

Thanks for your help guys.

74 . Jack on January 7th, 2010

Jack

I may add that the script is in <body>, with nothing in <head>
dunno if it's important ...

75 . Jack on January 7th, 2010

Jack

<body onload="NDC_()"> works fine, but then I calculate the time to load the whole page, not only one pic.
Something wrong with the image onload event

76 . Jesse Skinner on January 7th, 2010

Jesse Skinner

@Jack - I think the problem is using 'document.write' after the page is done loading. This only works while the page loads and not in event callbacks.

Try using some DOM scripting methods instead.

77 . perl on January 7th, 2010

perl

Replace:

NDC.onLoad = NDC_;

with:

NDC.onload = NDC_;

The "l" in "onload" should not be capitalized. JavaScript is case sensitive.

78 . Jack on January 8th, 2010

Jack

Removing the capital L is not helping :/

Jesse, that could be an explanation yes. But it means there is not simple solution :/

79 . perl on January 8th, 2010

perl

Here's the code for the version that I put together to test. I even added an alert box to account for situations where document.write won't work. This is working for me under the following configurations:

Firefox 3.0.13 / Mac OS X 10.4.11
Firefox 3.0.15 / Microsoft Windows Server 2003 Standard Edition Service Pack 2
Internet Explorer 7.0.5730.11 / Microsoft Windows Server 2003 Standard Edition Service Pack 2

<html>
<head>
<title>onload test</title>
</head>
<body>
<script language="javascript">

var ndc_time_start = (new Date()).getTime();
var NDC = new Image();
NDC.onload = NDC_;

function NDC_()
{
var ndc_time_stop = (new Date()).getTime();
var ndc_time_diff = ((ndc_time_stop - ndc_time_start) / 1000);

alert("Start Time for NDC "+ndc_time_start+" ms\n"
+ "Stop Time for NDC "+ndc_time_stop+" ms\n"
+ "Diff for NDC "+ndc_time_diff+" ms");

document.write("Start Time for NDC "+ndc_time_start+" ms<br>")
document.write("Stop Time for NDC "+ndc_time_stop+" ms<br>")
document.write("Diff for NDC "+ndc_time_diff+" ms<br>")
}


NDC.src = 'http://img25.imageshack.us/img25/5315/n382wawoamd11fehbk31220.jpg';

</script>
</body>
</html>

80 . Jack on January 11st, 2010

Jack

Thank you for that.
It seems document.write has a strange behaviour indeed.

I also get some strange behaviour with both IE and firefox, the script does not end in a clean way. It looks like the browser hang and I can't start a refresh with control+F5. Do you have the same problem ?

81 . perl on January 11st, 2010

perl

Yes I do. As Jesse pointed out, using the write function after the page has finished loading is not proper. If you think about it, "write" inserts code into the HTML stream. If the browser has already received the "</html>" tag, you're adding code after that.

You can get around this using innerHTML. In the body of the document put:

<div id="ndc_div">
</div>

In place of the write's put:

var ndc_div = document.getElementById("ndc_div");

ndc_div.innerHTML = "Start Time for NDC "+ndc_time_start+" ms<br>"
+ "Stop Time for NDC "+ndc_time_stop+" ms<br>"
+ "Diff for NDC "+ndc_time_diff+" ms";

82 . Jack on January 12nd, 2010

Jack

Thank you very much guys !
I have learned a lot a the script is now working fine.

83 . bogdan on February 19th, 2010

bogdan

great the Image onload not always working issue took me ages to solve ... and I couldn't .. thanks mate!

84 . Mindaugas on March 4th, 2010

Mindaugas

Your post helped me-thanks!

85 . Stefan on March 11st, 2010

Stefan

Dude couldn't figure it out. Thanks for helping me out.

86 . Erik on May 24th, 2010

Erik

Thank you for your note. I was already in despair, why the Firefox, after the cache was emptied, the images has never appear at the first call.

87 . Neto on May 30th, 2010

Neto

You saved my life!!!

thanks for this tip.

Kill ie!

88 . Biff Tannen on June 4th, 2010

Biff Tannen

OMG thank you so much!
Hours wasted trying to get a fix for my solution & I think your wisdom has just solved it!

Dude; I'm so grateful

Cheers

Jesus... why does ie have to suck so bad!

89 . Jesse Skinner on June 4th, 2010

Jesse Skinner

@Biff thanks! So do you run Biffco these days, or is this the universe where you work for George?

90 . Graham on June 22nd, 2010

Graham

Big help

Cheers!

91 . Ruslan on July 14th, 2010

Ruslan

I encountered a bug when FF 3.6.6 calls the onload function too early, before the image is actually loaded.

the first time you load the page, the canvas will throw an error. If you reload the page (the image is already cached) everything will work.
Another way to make it work from the beginning (empty cache) is if you introduce a delay, i used the alert function.

All this tells me that the onload fuction is called too early. This is why the canvas element fails to draw the image the first time.


Here is the code to reproduce it (the image has to be large, and you need to run the code from a web server, even localhost will do):

<body>
<div class="container">
<canvas id="canvas" width="500" height="500"></canvas>
</div>

<script type="text/javascript">
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function(){
//alert('a small delay');
try{
ctx.drawImage(img, 0, 0);
}
catch(e)
{
debugger;
}
}
img.src = "image.jpg";

</script>
</body>

92 . mike on July 30th, 2010

mike

Thanks man, helped me bunches.

93 . Mahwish on August 2nd, 2010

Mahwish

Thnx for the tip.

94 . fb on August 12nd, 2010

fb

Now I know I wasn't crazy... For the first poster, I need this to swap images from the client when a user wanted to see the larger size.

95 . Barak on August 28th, 2010

Barak

ty ty ty ty ty ty ty ty ty ...you saved me :-)

96 . Gauri on September 16th, 2010

Gauri

hi all,
below is my code... it works fine in IE for some images and in firefox(Mozilla/5.0) it gives height and width both as zero.... what do i do for firefox to show up correct image size

<html>

<head>

<script language='JavaScript'>

function getImgSize(imgsrc)

{

var newImg = new Image();
newImg.onLoad = function() {
// always called
alert('image loaded');
};

newImg.src = imgsrc;

var height = newImg.height;

var width = newImg.width;

var filename = imgsrc.replace(/^.*\\/, '')

alert("'" + filename + "' is " + width + " by " + height + " pixels in size.");

alert ('The image size is '+width+'*'+height);

}

</script>

</head>

<body>

<form>

<INPUT TYPE="file" NAME="fileName" >

<p>

<INPUT TYPE="button" VALUE="check image dimensions" OnCLICK="getImgSize(this.form.fileName.value)">

</form>

</body>

</html>

97 . Shelby Moore on September 30th, 2010

Shelby Moore

There is an alternative solution which doesn't require assigning the image.onload before the image.src:

image.onload = callback
if( image.complete && image.width > 0 ) callback()

I have thoroughly tested this in IE6+, FF3+, Chrome.

98 . Shelby Moore on September 30th, 2010

Shelby Moore

Also make sure you remove the onload and onerror events (if they point to function which has long lived references, e.g. global or closure scope), so that there won't be a memory leak.

99 . Shelby Moore on October 2nd, 2010

Shelby Moore

Note at least IE6 doesn't set image.complete, so if using my prior suggestion, then probably better to do:

image.onload = callback
if( image.width > 0 ) callback()

The disadvantage could theoretically be that the image is not yet complete even if the width is already set.

100 . Shelby Moore on October 2nd, 2010

Shelby Moore

Correction of my comment #99, the image.complete is supported in IE6, but is not true within the onload handler.

http://www.w3schools.com/jsref/prop_img_complete.asp

101 . Carl on October 27th, 2010

Carl

wow - so blindingly obvious but this little gotcha got me! I found this while searching google on "IE8 onload" because I needed to solve this exact problem. Worked in earlier IE and firefox but not in IE8. Can't believe I missed this - seems so obvious now! thanks . . .

Incidentally, I have another use for the onload function (referring to the very first comment a few years ago) . . . I show an image for 3 seconds and then swap it. But the server call could take 2 seconds so the image would only be shown for 1 second. So I need to start my 3 second countdown only after the image is loaded.

102 . David Smith on January 13rd, 2011

David Smith

Saved me a lot of frustration. Thanks for sharing!

103 . mahmoud on January 20th, 2011

mahmoud

you are a prince

104 . Fela Maslen on February 7th, 2011

Fela Maslen

Thanks alot for this, I was wondering why IE was being erratic with my AJAX based slideshow...

105 . allan on February 23rd, 2011

allan

Friggin awesome! That really helped i had the same problem and this was the fix!

106 . Petr Hrudka on April 9th, 2011

Petr Hrudka

When arranging a sequential thumbnail loading on my site, I was trying for two days to break through this until I found your post. Greatly appreciated :)

107 . Sean on April 11st, 2011

Sean

We are possibly going to use an image's onload feature at work to help account for third party software. We display a list of vendors who meet specific criteria, and some of those vendors have live chat enabled. Since we want to capture statistics on the vendors with live chat, the only way we can tell is by checking the image returned from this third party and seeing if it's bigger than 1px. If so, then that vendor is considered online and available for chat.

We may start using the onload to decrement a semaphore. When the semaphore reaches zero, we will count up the vendors who are online for chat and use that in our reporting software.

Thanks very much for the tip!

108 . Arttu Manninen on October 10th, 2011

Arttu Manninen

Thanks for the post. It was still useful after four years when I needed to start debugging on IE8 hanging on a very simple array based preloader that worked pretty much on everything else. My gray hair grew length only for 10 minutes before I found your post. :)

109 . Swati on October 12nd, 2011

Swati

Thanks a lotttttt

110 . Swati on October 17th, 2011

Swati

Hi Jesse, I'm using drawimage() function of canvas for IE8 but the images are cut into halves. Its working fine for IE9 and chrome but not for IE8. Please help..
Here is my sample code:
var image = new Image();


image.onload = function () {
//Use if loop for IE8 and else for chrome
if (typeof window.G_vmlCanvasManager != "undefined")
{

col = window.G_vmlCanvasManager.initElement(col);
var ctx = col.getContext('2d');
}
else
{
var ctx = col.getContext('2d');
}


ctx.drawImage(image, 0, 0,300,150);

}


image.src = ['images', images[i]].join('/');

111 . Fluid on November 3rd, 2011

Fluid

Thanks a lot man.

112 . Ben on November 9th, 2011

Ben

With Firefox 8 it looks as if the pre-fetch no longer works properly. The width and height attributes are still arriving okay, but the image is not always fully loaded - i.e. if you display the image immediately following the onload function call it may still appear as if it is loading.

Anyone else seeing this?

113 . Nathanael Smith on February 15th, 2012

Nathanael Smith

You rock. Nuff said.

114 . Matteo on February 22nd, 2012

Matteo

Thank you, thank you, thank you!!!!!!!

From Italy

115 . Ricardo on April 2nd, 2012

Ricardo

Nice! Simple and functional! Thanks for the tip.

116 . Randy on June 21st, 2012

Randy

Really a very helpful tip...bookmarking this page for future reference...

Comments are closed, but I'd still love to hear your thoughts.