• Getting an Image's onload to Fire

    Sep 28 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 at 4:23pm on September 30, 2007

    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 at 4:26pm on September 30, 2007

    @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 at 4:38pm on September 30, 2007

    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 at 4:41pm on September 30, 2007

    @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 at 3:08pm on October 1, 2007

    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 at 12:08pm on October 8, 2007

    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 at 3:25am on October 9, 2007

    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 at 11:33am on October 10, 2007

    Thanks, Jessie. Very useful.

    9. Justin McConnell at 12:30am on October 15, 2007

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

    10. Darius at 8:35am on October 19, 2007

    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 at 9:25am on November 5, 2007

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

    12. perl at 9:13pm on November 18, 2007

    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 at 8:49am on December 18, 2007

    thanks that tip helped me alot today on IE7

    14. Diego Guidi at 3:21pm on December 21, 2007

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

    15. Harry at 2:18am on January 7, 2008

    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 at 7:26pm on February 3, 2008

    Great post.

    Thanks for this...

    17. Alex at 10:37am on February 18, 2008

    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 at 10:40am on February 18, 2008

    @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 at 11:49pm on February 21, 2008

    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 at 7:01pm on March 12, 2008

    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 at 5:00pm on April 2, 2008

    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 at 4:51am on April 10, 2008

    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 at 2:07pm on April 21, 2008

    great :)
    thanks

    24. Samuele Catuzzi at 10:57pm on May 1, 2008

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

    25. greg whiteside at 12:05pm on May 5, 2008

    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 at 4:43am on May 15, 2008

    Seriously, thank you for sharing this!

    27. howie at 2:32am on May 18, 2008

    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 at 4:48pm on May 26, 2008

    Thanks for this.

    29. Liam at 11:46am on July 1, 2008

    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 at 11:56pm on July 9, 2008

    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 at 2:54am on August 20, 2008

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

    32. Duilio at 8:46pm on August 27, 2008

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

    33. Aikheel at 5:15pm on September 1, 2008

    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 at 4:37am on September 3, 2008

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

    35. Keith at 7:21pm on September 17, 2008

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

    Cheers.

    36. LFFATE at 3:11pm on October 16, 2008

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

    37. Jesse Skinner at 9:52am on October 18, 2008

    @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 at 4:46am on October 19, 2008

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

    39. andris at 7:38pm on October 22, 2008

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

    40. Diederik Stenvers at 3:34am on November 20, 2008

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

    41. Alex Dickson at 7:40pm on November 20, 2008

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

    42. Karan at 2:37am on November 25, 2008

    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 at 9:54am on December 4, 2008

    Thanks...
    You save me.

    44. blaze at 6:10pm on December 17, 2008

    Man, you are the man.

    45. AdamWu at 5:45am on December 30, 2008

    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 at 2:24pm on December 30, 2008

    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 at 8:02am on January 18, 2009

    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 at 12:05pm on January 18, 2009

    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 at 5:53pm on January 30, 2009

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

    ??

    50. Nietzsche at 6:15am on February 7, 2009

    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 at 4:44pm on February 18, 2009

    Had a problem with this. Thanks for the solution!

    52. Eric at 1:08am on April 3, 2009

    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 at 11:36pm on April 23, 2009

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

    54. Dimitar Christoff at 9:40am on May 11, 2009

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

    55. VkReddy at 2:29am on May 15, 2009

    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 at 9:01pm on July 5, 2009

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

    57. digitaldokuro at 9:14pm on July 30, 2009

    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 at 11:57am on August 1, 2009

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

    59. joe at 1:07pm on August 21, 2009

    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 at 1:42am on August 27, 2009

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

    61. soothing at 6:51pm on September 1, 2009

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

    62. Jon L at 11:15pm on September 30, 2009

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

    63. Juan Martín Socorro at 10:31am on October 7, 2009

    Very usefull. You saved me a lot of work.

    64. John John K at 5:18am on October 15, 2009

    OMFG thank you very much!

    65. Vadim at 10:53am on October 16, 2009

    Thanks Jesse, it's really useful.

    66. Ryan at 7:10pm on October 19, 2009

    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 at 5:12pm on November 6, 2009

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

    68. actionM at 2:07pm on December 22, 2009

    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 at 8:25am on December 30, 2009

    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 at 10:30am on January 6, 2010

    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 at 4:00pm on January 6, 2010

    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 at 4:05pm on January 6, 2010

    @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 at 3:46am on January 7, 2010

    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 at 10:11am on January 7, 2010

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

    75. Jack at 10:47am on January 7, 2010

    <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 at 12:20pm on January 7, 2010

    @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 at 12:24pm on January 7, 2010

    Replace:

    NDC.onLoad = NDC_;

    with:

    NDC.onload = NDC_;

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

    78. Jack at 4:18am on January 8, 2010

    Removing the capital L is not helping :/

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

    79. perl at 10:43am on January 8, 2010

    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 at 3:34am on January 11, 2010

    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 at 10:47am on January 11, 2010

    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 at 7:52am on January 12, 2010

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

    83. bogdan at 12:18pm on February 19, 2010

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

    84. Mindaugas at 7:30am on March 4, 2010

    Your post helped me-thanks!

    85. Stefan at 5:36pm on March 11, 2010

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

    86. Erik at 1:04pm on May 24, 2010

    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 at 9:38am on May 30, 2010

    You saved my life!!!

    thanks for this tip.

    Kill ie!

    88. Biff Tannen at 4:53pm on June 4, 2010

    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 at 6:23pm on June 4, 2010

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

    90. Graham at 11:57am on June 22, 2010

    Big help

    Cheers!

    91. Ruslan at 10:59am on July 14, 2010

    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 at 1:52pm on July 30, 2010

    Thanks man, helped me bunches.

    93. Mahwish at 8:01am on August 2, 2010

    Thnx for the tip.

    94. fb at 6:45pm on August 12, 2010

    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 at 5:46pm on August 28, 2010

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

    96. Gauri at 3:07am on September 16, 2010

    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 at 9:34pm on September 30, 2010

    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 at 10:05pm on September 30, 2010

    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 at 10:59pm on October 2, 2010

    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 at 11:10pm on October 2, 2010

    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 at 9:37am on October 27, 2010

    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 at 8:52pm on January 13, 2011

    Saved me a lot of frustration. Thanks for sharing!

    103. mahmoud at 3:31am on January 20, 2011

    you are a prince

    104. Fela Maslen at 3:48pm on February 7, 2011

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

    105. allan at 2:09pm on February 23, 2011

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

    106. Petr Hrudka at 4:51am on April 9, 2011

    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 at 1:43pm on April 11, 2011

    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 at 8:31am on October 10, 2011

    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 at 1:51am on October 12, 2011

    Thanks a lotttttt

    110. Swati at 6:37am on October 17, 2011

    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 at 12:02pm on November 3, 2011

    Thanks a lot man.

    112. Ben at 5:33pm on November 9, 2011

    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 at 5:27pm on February 15, 2012

    You rock. Nuff said.

    114. Matteo at 12:32pm on February 22, 2012

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

    From Italy

    115. Ricardo at 9:23pm on April 2, 2012

    Nice! Simple and functional! Thanks for the tip.

    116. Randy at 7:46pm on June 21, 2012

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

    Commenting is now closed. Come find me on Twitter.