151

I want to create an alert box after an image is loaded, but if the image is saved in the browser cache, the .onload event will not be fired.

How do I trigger an alert when an image has been loaded regardless of whether the image has been cached or not?

var img = new Image();
img.src = "img.jpg";
img.onload = function () {
   alert("image is loaded");
}
kmgdev
  • 2,607
  • 28
  • 41
Oto Shavadze
  • 40,603
  • 55
  • 152
  • 236
  • 6
    possible duplicate of [jQuery callback on image load (even when the image is cached)](http://stackoverflow.com/questions/3877027/jquery-callback-on-image-load-even-when-the-image-is-cached) – Fabrício Matté Sep 10 '12 at 15:31

6 Answers6

205

As you're generating the image dynamically, set the onload property before the src.

var img = new Image();
img.onload = function () {
   alert("image is loaded");
}
img.src = "img.jpg";

Fiddle - tested on latest Firefox and Chrome releases.

You can also use the answer in this post, which I adapted for a single dynamically generated image:

var img = new Image();
// 'load' event
$(img).on('load', function() {
  alert("image is loaded");
});
img.src = "img.jpg";

Fiddle

Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • Wait. Why does your second code example do the wrong thing and set `.src` before setting .onload? You had it right in the first code example, but messed up the second one. The second one will not work properly in some versions of IE. – jfriend00 Sep 10 '12 at 16:42
  • 1
    @jfriend00 Nope, not a mess up. The back up code (2nd one) is exactly for in case the first one somehow stops working. `=]` It utilizes a `.complete` check in case the image was already cached, hence the code was demonstrating it. Of course, for the best practice, you can always set the `src` after all handlers binding. – Fabrício Matté Sep 10 '12 at 17:21
  • 4
    There's just NO reason to rely on `.complete` in this case. Just set your load handler first before setting `.src` and it is NEVER needed. I've written a slideshow that is used by thousands of sites in every conceivable browser and the first technique works every time. There is no need to ever check `.complete` when create a new image from scratch like this. – jfriend00 Sep 10 '12 at 17:24
  • Alright, thanks for the heads up, updated the answer to reflect your reasoning `=]`. Also @jfriend00 could you check if the image loads in IE? Wondering if it's an issue with my network or with IE and the image. – Fabrício Matté Sep 10 '12 at 17:29
  • Both jsFiddles work for me in IE9 and IE7 when the image is cached and when it's not cached. The image shows. If the image is not cached, it displays after the alert. FYI, the jQuery in the 2nd example isn't helping you in any way other. – jfriend00 Sep 10 '12 at 17:40
  • Thanks. `=]` Yeah, I've made the second example adding a listener so it doesn't overwrite an existing `onload` property, but in this case as OP is creating a new image for scratch, it won't make any difference. – Fabrício Matté Sep 10 '12 at 18:45
  • 9
    Also today I found that webkit needs `img.src = ''` before assigning new src if it was used before. – quux May 24 '14 at 10:53
  • @quux Your comment is an important aspect that no one else mentioned and the exact solution to my related issue. – Isius Jul 31 '14 at 21:06
  • Does image onload attribute doesnt fire at all for the cached images? I have a HTML IMG tag with onload and it fires only once.subequently it fires after doing ctrl +F5 only. – techie_28 Sep 30 '14 at 14:54
  • @FabrícioMatté I am not using JavaScript to load the image here, JS code is having an alert which fires only once,actually I did not understood this line in the comment "src is already set then the event is firing in the cache cased before". thanks. – techie_28 Sep 30 '14 at 16:38
  • @techie_28 the `onload` HTML attribute *should* fire even for cached images IIRC. Maybe ask a new question, you will get more attention from the community then. `=]` – Fabrício Matté Sep 30 '14 at 17:19
  • The event was still not working for me. Then I changed from `img.setAttribute("src", "{url}");` to `img.src = "{url}";` and it worked. Hope it helps someone. – Rehmat Jul 16 '20 at 07:26
  • Why is important to set onload before src ? As I understand onload event will activate after image get src. I would like to understand why is important this order: first onload then src? How this change/affect caching process? – Predrag Davidovic Mar 08 '21 at 08:18
  • In the modern way of developing using React, Angular, or Vue, this answer is outdated. – John Miller Aug 24 '21 at 00:58
16

If the src is already set then the event is firing in the cached case before you even get the event handler bound. So, you should trigger the event based off .complete also.

code sample:

$("img").one("load", function() {
   //do stuff
}).each(function() {
   if(this.complete || /*for IE 10-*/ $(this).height() > 0)
     $(this).load();
});
Tomas Ramirez Sarduy
  • 17,294
  • 8
  • 69
  • 85
6

There are two possible solutions for these kind of situations:

  1. Use the solution suggested on this post
  2. Add a unique suffix to the image src to force browser downloading it again, like this:

    var img = new Image();
    img.src = "img.jpg?_="+(new Date().getTime());
    img.onload = function () {
        alert("image is loaded");
    }
    

In this code every time adding current timestamp to the end of the image URL you make it unique and browser will download the image again

Community
  • 1
  • 1
haynar
  • 5,961
  • 7
  • 33
  • 53
  • 60
    All this does is defeat caching. It is the WRONG way to solve this problem. The right way is in Fabricio's answer. Just set the `.onload` handler before setting the `.src` value and you won't miss the onload event in some versions of IE. – jfriend00 Sep 10 '12 at 16:41
  • 2
    yes you are right, but it is not always desirable to cache, sometimes images should not be cached. of course in this particular situation it depends on the needs – haynar Sep 10 '12 at 18:19
  • 1
    In my angular app I tried everything that other answers says, but didn't help. But forcing not to cache like this answer says did work for me. So plus one from me. – Thanu Jan 06 '16 at 00:21
  • The only solution that worked for me in latest version Chrome. – Young Bob Feb 28 '18 at 18:24
  • Fixed my problem when the picture has the same name, but in fact changed – Martin Müsli Jun 05 '23 at 07:27
3

I have met the same issue today. After trying various method, I realize that just put the code of sizing inside $(window).load(function() {}) instead of document.ready would solve part of issue (if you are not ajaxing the page).

akjoshi
  • 15,374
  • 13
  • 103
  • 121
user9319
  • 31
  • 1
1

My improvement:

document.addEventListener("DOMContentLoaded", function () {
  let el = document.getElementsByTagName("img")
  Object.values(el).forEach(function (el) {
    var img = new Image();
    img.onload = function () {
      el.style.opacity = 1;
    }
    img.src = el.src
  })
});

.

<style>
  img {
    opacity: 0;
    transition: opacity .4s cubic-bezier(.25, .45, .45, .95);
  }
</style>
Oreo
  • 21
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 12 '23 at 13:46
-1

I found that you can just do this in Chrome:

  $('.onload-fadein').each(function (k, v) {
    v.onload = function () {
        $(this).animate({opacity: 1}, 2000);
    };
    v.src = v.src;
});

Setting the .src to itself will trigger the onload event.

Noah Ellman
  • 179
  • 1
  • 4