image.onload event and browser cache
Asked Answered
B

6

153

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");
}
Burge answered 10/9, 2012 at 15:31 Comment(1)
possible duplicate of jQuery callback on image load (even when the image is cached)Hainaut
N
208

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

Noria answered 10/9, 2012 at 15:41 Comment(14)
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.Korwin
@Korwin 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.Hainaut
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.Korwin
Alright, thanks for the heads up, updated the answer to reflect your reasoning =]. Also @Korwin could you check if the image loads in IE? Wondering if it's an issue with my network or with IE and the image.Hainaut
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.Korwin
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.Hainaut
Also today I found that webkit needs img.src = '' before assigning new src if it was used before.Fabrication
@Fabrication Your comment is an important aspect that no one else mentioned and the exact solution to my related issue.Novara
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.Aubade
@FabrícioMatté I am not using JavaScript to load the image here, <img onload="JS CODE" src="URL 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.Aubade
@Aubade 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. =]Hainaut
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.Stonewort
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?Soddy
In the modern way of developing using React, Angular, or Vue, this answer is outdated.Desdee
B
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();
});
Biotype answered 24/7, 2015 at 19:52 Comment(0)
M
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

Motionless answered 10/9, 2012 at 15:36 Comment(5)
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.Korwin
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 needsMotionless
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.Wheaten
The only solution that worked for me in latest version Chrome.Shedevil
Fixed my problem when the picture has the same name, but in fact changedRadiotelephone
B
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).

Benzedrine answered 3/1, 2013 at 6:5 Comment(2)
This is also a good answer for the situation where browser has image cached, works ok with window loadCabal
exactly the issue I was facing. changing $(document).ready to $(window).load solved my problem.Birdhouse
P
2

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>
Priestcraft answered 7/4, 2023 at 20:58 Comment(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.Spirt
S
-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.

Sanitary answered 1/2, 2017 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.