Fixing .load() in IE for cached images

The .load() function fires when the element it's called upon is fully loaded. It is commonly used on images, which may not be fully loaded when the JavaScript originally runs, and thus would return incorrect information about themselves (e.g. height/width). Most browsers deal with this fine. IE can cause problems, when images on the page are cached.

Selecting the image and changing it's src attribute to append a random parameter (based on the date). This will trick IE into firing the .load() function properly.

myImge = $("<img />")
   .attr("src",anyDynamicSource+ "?" + new Date().getTime());

Now the .load() function will work, even in IE:

$(myImge).load(function() {
   alert("will alert even in IE")
});
See the first comment for a warning about using this technique with a CDN.

Comments

  1. User Avatar
    John Jimenez
    Permalink to comment#

    This method can really hurt some cdn servers. By calling the image with ‘?[whatever randomness you want]’ you are creating a copy of that file that propagates through the server farm with that extra randomness as the file name.

    someImg.jpg -> someImg.jpg gets propagated to the cdn.
    someImg.jpg?20100318000302 -> someImg.jpg?20100318000302 gets propagated to the cdn.
    someImg.jpg?20100318000303 -> someImg.jpg?20100318000303 gets propagated to the cdn.

    On smaller sites that don’t use cdn this may be a fine method, but it is not a viable option for higher end sites (CNN.com, PGATOUR.com, NBA.com, etc).

    • User Avatar
      Eliazer
      Permalink to comment#

      Thanks, Which solution would you suggest in such a case?

      Thanks again.

    • User Avatar
      John Jimenez
      Permalink to comment#

      Sorry Eliazer, I still do not have a solution for this case.
      I was just making it a point to bring it up as my team got dinged pretty hard for doing this type of method, and I wanted to help others avoid it if possible.

    • User Avatar
      Mark
      Permalink to comment#

      To avoid breaking caching and CDNs I append the image’s MD5 as a parameter, this also works to force browsers to update cached CSS files. Here’s an example of a cached CSS link emitted from PHP, image links should be constructed in the same way:

      <?php
          // returns the URL with its MD5 appended as a variable (used to force browsers to update their cached stylesheets)
          function AppendMD5Variable($url)
          {
              // get the $url's md5
              $md5 = md5_file($url);
              // return the url with the md5 appended as a variable
              return $url.'?md5='.$md5;
          } 
      ?>
      <link rel="stylesheet" href="<?php echo AppendMD5Variable("http://www.somesite.com/wp-content/themes/company/reset.css") ?>" type="text/css" media="all" />
      

      which emits:

      <link rel="stylesheet" href="http://www.somesite.com/wp-content/themes/company/reset.css?md5=d18499a24db47778f4147ee7a6b84434" type="text/css" media="all" />
      

      Hope this helps someone (and I hope this is formatted well, not used ‘markdown’ before).

  2. User Avatar
    Justin
    Permalink to comment#

    jQuery 1.4.2 already does this for you (using the $.ajax() function however). Just put cache : false to the AJAX setup and it should do it for you.

    • User Avatar
      TeMc
      Permalink to comment#

      This has nothing to do with AJAX requests, it’s about normal img-tags and firing a function when the image is loaded (ie. [img onload=this-function /]), and not about $(target).load(‘http address’, function(){}); which is something totally different.

      jQuery has several functions with equal names, and depending on the context something may mean something different.

      such as click() means trigger the click event, but click(function(){ }), means bind a click handler.

      See also
      http://api.jquery.com/load/
      http://api.jquery.com/load-event/

  3. User Avatar
    ben
    Permalink to comment#

    Thanks for this. I think I will take a slightly different approach in my case. The problem with doing it this way is that you loose all the benefits of image caching in all other browsers and I don’t want to reduce everyone elses experience just because of IE7.

    Instead I am going to leave the .load function there but also have a setTimeout function that will do the same as the load (since in my case it’s only removing a class it’s not a problem). I am sure there’s a better way though. Anyone?

    • User Avatar
      Matt

      Excellent find Ben!!!

      This is a much better solution. Chris should add this to his blog post!!!

      It doesn’t break caching, and it works in old IE.

  4. User Avatar
    nme

    as John Jimenez mentioned, given method will increase CDN hit ratio, there is an easier method to accomplish this, heres pseudo code:

    $('img').each(function() {
        if ($(this).height() > 0) {
           our callback
        } else {
           $(this).load(function() {
             our callback
           });
        }
    });
  5. User Avatar
    Bhanu Pratap
    Permalink to comment#

    Thanks. Now it is working in all browsers great.

    var url = any dynamic url;
    var img = new Image();
    $(“<img/>”) // Make in memory copy of image to avoid css issues
    .attr(“src”, url+ “?” + new Date().getTime())
    .load(function() {
    // Do any stuff
    });

    • User Avatar
      vishal suri
      Permalink to comment#

      Hello bhanu partap , i need your help , i am suffering from same issue , but not able to get clear

  6. User Avatar
    Adam Wadsworth
    Permalink to comment#

    I have the same problem but not sure where to start fixing it. Could someone please spend two mins and have a quick look at this problem.
    URL: http://www.media21a.co.uk/development/unknown/

    Any/All help will be credited thank you.

  7. User Avatar
    Miro Hristov
    Permalink to comment#

    Here is a one line solution that you can use insted of $(‘img’).load(function(){ //// });

    
    $('img').each(function(){  this.src = this.src + '?random=' + (new Date()).getTime()}).load(function(){
     alert("will alert even in IE")
    });
    
  8. User Avatar
    Rytis Lukoševičius
    Permalink to comment#

    I was struggling with this issue on one of the sites I’m making and actually there’s a bit better way to fixing this. It turn out the bug is fixed if you add “load” first and only after that change “src” for the image.

    So actually the best way would be to

    $('img').load(function() { ... }).attr('src', 'new_image_source'); 

    it worked for me as a charm on multiple runs for the same already cached images.

    Have a nice day

    • User Avatar
      Gemma D Lou
      Permalink to comment#

      Hey Rytis, Thanks! This works perfectly now in IE9, IE8, IE7 perfectly, Chrome, Mozilla and Safari. :)

    • User Avatar
      Henrique Müller
      Permalink to comment#

      Ow, man. It’s been a long time since this answer, but it still saved my life!

      Thanks!

    • User Avatar
      Shafiq

      Can you please tell how to do this in pure javascript. I tried to change the src inside onload function, that kept calling the source url and kept updating image, which makes sense. How can I make it run one time with your solution. I tried adding empty load function to img and then changing src, that doesnt help.

      Thanks

  9. User Avatar
    franz
    Permalink to comment#

    Thank You Rytis! Very simple, but very effective. Kind of makes sense really ;)

  10. User Avatar
    Mark
    Permalink to comment#

    Thank you Jeebus for the existence of this page. And props to Rytis and Chris too.

  11. User Avatar
    Jet
    Permalink to comment#

    Depending on what you’re doing, this also does the trick:
    $('').load(function() { // }).load();
    So yeah, in other browsers your function might get called twice, but it shouldnt be too hard to check for this one.

  12. User Avatar
    Reinier Kaper
    Permalink to comment#

    Rytis: you saved my life man!
    IE7 was giving me a hard time with this and I didn’t prefer the method of appending a timestamp because of the issues raised before.

    Thanks!

  13. User Avatar
    Rytis Lukoševičius
    Permalink to comment#

    Glad I could help :) it saved my own sanity also :D

  14. User Avatar
    alex lacayo
    Permalink to comment#

    Props to Rytis for that … this worked for me

    
        $('.look-book-wrapper img').each(function() {
    	
    	   var new_image_source = ($(this).attr('src'));	
     
           $(this).load(function() {
        		$(this).fadeIn('slow');
        	})
        	.attr('src', new_image_source); 
        	//.attr({src: $(this).attr('src') + '?time=' + (new Date()).getTime() });
        });
    
  15. User Avatar
    Bjørn T.

    Rytis: Thanks for saving my day, and the little hair I’ve got left from all the frustration.

  16. User Avatar
    Gabriel Oliveira
    Permalink to comment#

    Thank you so much! Its works great!

  17. User Avatar
    Abolfazl Beigi
    Permalink to comment#

    Thanks a lot. useful like always.

  18. User Avatar
    Ian Brown
    Permalink to comment#

    Rytis, you the man!! Thanks.

  19. User Avatar
    Thanos
    Permalink to comment#

    Oooo!! Is there anything you don’t know?
    I prefer the solution of Chris because it fits better to my code.

  20. User Avatar
    John
    Permalink to comment#

    Why are you wrapping it in jQuery twice?

    myImge = $("")
    $(myImge).load(...)
    

    So that is equivalent to $($("<img />"))

  21. User Avatar
    Hank
    Permalink to comment#

    Thanks a lot Nme, check the height instead of using the load was the way to go to solve the problem with the older versions of IE that do not fire the load function a second time.
    You sir just saved my day.

  22. User Avatar
    JR Galia
    Permalink to comment#

    Thanks rytis.

  23. User Avatar
    Nut315
    Permalink to comment#

    Just a note on some of the answers. $("#element").load(function() { }); has been depreciated as of jQuery 1.8 and should be replaced with the following:

    
    $("#element").bind("load", function() { });
    
  24. User Avatar
    Raghav
    Permalink to comment#

    Thanks for the post. I was having exactly the same issue. Fixed it in straight way i used your code

  25. User Avatar
    Lucian Adamson
    Permalink to comment#

    I know browser sniffing is considered bad practice, however on something like this where checking for support isn’t what you need I think it would be rightly justified. As a person commented earlier, why sacrifice the caching of other people and slow their experience for the other users who chose the frowned upon IE route. You could just check if browser is IE and apply this method, if you don’t use CDN that is.

  26. User Avatar
    Patrick

    I think I came up with a better solution that a) Works no matter when you attach the onload handler – before or after setting the src – and b) doesn’t create copies of your images on the server.

    Turns out, you don’t have to add a random query param to the image. Simply do this:

    $("img").attr("src", $("img").attr("src"));
    

    As you can see, the src attribute is set to the same value it was before. That way, IE doesn’t even reload the image, it just fires the onload Event, which is exactly what we want. :-)

  27. User Avatar
    vipul
    Permalink to comment#

    here better solution with jquery.

    $("img").one('load', function() {
    // your code here
    }).each(function() {
    if(this.complete) {
    $(this).load();
    }
    });

  28. User Avatar
    Pete Jones
    Permalink to comment#

    Is there any benefit in using a ‘#’ rather than a ‘?’ in the querystring? I’ve seen instances where a ‘#’ will still use the cached image rather than a cache breaking ‘?’ – such as http://www.post-hipster.com/2008/10/20/using-javascript-to-refresh-an-image-without-a-cache-busting-parameter/

    • User Avatar
      Brad
      Permalink to comment#

      That seems like a valid point. Can’t read the linked article as I’m at work but I would imagine the pound sign might be less disruptive than a param question mark.

  29. User Avatar
    Mark
    Permalink to comment#

    Hi, I need load background image for div.

    <div id="low"></div>
    <div id="high"></div>
    

    When I click on low, so I need show high with background image. In Chrome etc. I have solution, but in IE after click background of div flashes.

    Thank you for your tip.

  30. User Avatar
    thinsoldier
    Permalink to comment#

    It seems Firefox 33 is just as unreliable when it comes to load events for cached images. :(

  31. User Avatar
    Nabi
    Permalink to comment#

    Well, actually there a ways to handle cached images correctly. I wrote tutorials about it:

    Loading images with jQuery and handling of events for showing loading spinners

    And if you want to use native Javascript without any jquery you can check my other tutorial:

    Loading images with native JavaScript and handling of events for showing loading spinners

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag