the Future of the Web
  • Home
  • Hire Us
  • Articles
  • About
  • Contact
  • 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.

    Tags: javascript debugging
    View 25 Comments | Add a comment
  • Comments

    1. Michael at 10: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 10: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 10: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 10: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 9: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 6: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 9: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 5:33pm on October 10, 2007

    Thanks, Jessie. Very useful.

    9. Justin McConnell at 6: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 2:35pm 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 3:25pm 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 3:13am on November 19, 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 2:49pm on December 18, 2007

    thanks that tip helped me alot today on IE7

    14. Diego Guidi at 9: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 8: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 1:26am on February 4, 2008

    Great post.

    Thanks for this...

    17. Alex at 4:37pm 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 4:40pm 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 5:49am on February 22, 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 1:01am on March 13, 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 11: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 10: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 8:07pm on April 21, 2008

    great :)
    thanks

    24. Samuele Catuzzi at 4:57am on May 2, 2008

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

    25. greg whiteside at 6: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!!

    Add a Comment

    Note: HTML tags and entities will be converted so that they are displayed as you type them. This means if you type in <em>, people will see <em>, and if you type &lt;em&gt;, people will see &lt;em&gt;.

  • Request a Quote

  • Jesse Skinner

    Jesse Skinner
    • Hire Me
    • About Me
    • Email Me
    • RSS Feed RSS Icon
  • Recent Articles

    • Parse Accept-Language to detect a user's language
    • Twitter
    • Three years of The Future of the Web
    • Saving data to a file with PHP
    • Easy web scraping with PHP
    • See all the articles
    • IBM: Where and when to use Ajax
    • Code Igniter 1.6.0 Released
    • Update a Dev Site Automatically with Subversion
    • JavaScript Functions are Variables
    • See All...
  • Categories

    • javascript (37)
    • links (19)
    • about (18)
    • web (14)
    • server (10)
    • html (10)
    • css (8)
    • carnival (7)
    • browsers (7)
    • design (4)
    • seo (4)
    • ads (4)
    • standards (4)
    • events (4)
    • work (4)
  • Older Articles

    • May 2008
    • April 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • September 2007
    • August 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    • March 2007
    • February 2007
    • January 2007
    • December 2006
    • November 2006
    • October 2006
    • September 2006
    • August 2006
    • July 2006
    • June 2006
    • May 2006
    • April 2006
    • March 2006
    • February 2006
    • January 2006
    • December 2005
    • November 2005
    • October 2005
    • September 2005
    • August 2005
    • April 2005
    • See All...
Copyright © 2008 Jesse Skinner | CSS | XHTML | RSS | Help | Impressum | Cutie Quilts | Internet Blog Top Sites