jQuery callback on image load (even when the image is cached)

JqueryImageJquery EventsJquery Load

Jquery Problem Overview


I want to do:

$("img").bind('load', function() {
  // do stuff
});

But the load event doesn't fire when the image is loaded from cache. The jQuery docs suggest a plugin to fix this, but it doesn't work

Jquery Solutions


Solution 1 - Jquery

If the src is already set, then the event is firing in the cached case, before you even get the event handler bound. To fix this, you can loop through checking and triggering the event based off .complete, like this:

$("img").one("load", function() {
  // do stuff
}).each(function() {
  if(this.complete) {
      $(this).load(); // For jQuery < 3.0 
      // $(this).trigger('load'); // For jQuery >= 3.0 
  }
});

Note the change from .bind() to .one() so the event handler doesn't run twice.

Solution 2 - Jquery

Can I suggest that you reload it into a non-DOM image object? If it's cached, this will take no time at all, and the onload will still fire. If it isn't cached, it will fire the onload when the image is loaded, which should be the same time as the DOM version of the image finishes loading.

Javascript:

$(document).ready(function() {
	var tmpImg = new Image() ;
	tmpImg.src = $('#img').attr('src') ;
	tmpImg.onload = function() {
		// Run onload code.
	} ;
}) ;

Updated (to handle multiple images and with correctly ordered onload attachment):

$(document).ready(function() {
	var imageLoaded = function() {
		// Run onload code.
	}
	$('#img').each(function() {
		var tmpImg = new Image() ;
		tmpImg.onload = imageLoaded ;
		tmpImg.src = $(this).attr('src') ;
	}) ;
}) ;

Solution 3 - Jquery

My simple solution, it doesn't need any external plugin and for common cases should be enough:

/**
 * Trigger a callback when the selected images are loaded:
 * @param {String} selector
 * @param {Function} callback
  */
var onImgLoad = function(selector, callback){
    $(selector).each(function(){
        if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
            callback.apply(this);
        }
        else {
            $(this).on('load', function(){
                callback.apply(this);
            });
        }
    });
};

use it like this:

onImgLoad('img', function(){
    // do stuff
});

for example, to fade in your images on load you can do:

$('img').hide();
onImgLoad('img', function(){
    $(this).fadeIn(700);
});

Or as alternative, if you prefer a jquery plugin-like approach:

/**
 * Trigger a callback when 'this' image is loaded:
 * @param {Function} callback
 */
(function($){
    $.fn.imgLoad = function(callback) {
        return this.each(function() {
            if (callback) {
                if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
                    callback.apply(this);
                }
                else {
                    $(this).on('load', function(){
                        callback.apply(this);
                    });
                }
            }
        });
    };
})(jQuery);

and use it in this way:

$('img').imgLoad(function(){
    // do stuff
});

for example:

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});

Solution 4 - Jquery

Do you really have to do it with jQuery? You can attach the onload event directly to your image as well;

<img src="/path/to/image.jpg" onload="doStuff(this);" />

It will fire every time the image has loaded, from cache or not.

Solution 5 - Jquery

You can also use this code with support for loading error:

$("img").on('load', function() {
  // do stuff on success
})
.on('error', function() {
  // do stuff on smth wrong (error 404, etc.)
})
.each(function() {
    if(this.complete) {
      $(this).load();
    } else if(this.error) {
      $(this).error();
    }
});

Solution 6 - Jquery

I just had this problem myself, searched everywhere for a solution that didn't involve killing my cache or downloading a plugin.

I didn't see this thread immediately so I found something else instead which is an interesting fix and (I think) worthy of posting here:

$('.image').load(function(){
    // stuff
}).attr('src', 'new_src');

I actually got this idea from the comments here: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

I have no idea why it works but I have tested this on IE7 and where it broke before it now works.

Hope it helps,

Edit

The accepted answer actually explains why:

> If the src is already set then the event is firing in the cache cased before you get the event handler bound.

Solution 7 - Jquery

By using jQuery to generate a new image with the image's src, and assigning the load method directly to that, the load method is successfully called when jQuery finishes generating the new image. This is working for me in IE 8, 9 and 10

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});

Solution 8 - Jquery

A solution I found https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (This code taken directly from the comment)

var photo = document.getElementById('image_id');
var img = new Image();
img.addEventListener('load', myFunction, false);
img.src = 'http://newimgsource.jpg';
photo.src = img.src;

Solution 9 - Jquery

A modification to GUS's example:

$(document).ready(function() {
    var tmpImg = new Image() ;
    tmpImg.onload = function() {
        // Run onload code.
    } ;

tmpImg.src = $('#img').attr('src');
})

Set the source before and after the onload.

Solution 10 - Jquery

Just re-add the src argument on a separate line after the img oject is defined. This will trick IE into triggering the lad-event. It is ugly, but it is the simplest workaround I've found so far.

jQuery('<img/>', {
	src: url,
	id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE

Solution 11 - Jquery

I can give you a little tip if you want do like this:

<div style="position:relative;width:100px;height:100px">
     <img src="loading.jpg" style='position:absolute;width:100px;height:100px;z-index:0'/>
     <img onLoad="$(this).fadeIn('normal').siblings('img').fadeOut('normal')" src="picture.jpg" style="display:none;position:absolute;width:100px;height:100px;z-index:1"/>
</div>

If you do that when the browser caches pictures, it's no problem always img shown but loading img under real picture.

Solution 12 - Jquery

I had this problem with IE where the e.target.width would be undefined. The load event would fire but I couldn't get the dimensions of the image in IE (chrome + FF worked).

Turns out you need to look for e.currentTarget.naturalWidth & e.currentTarget.naturalHeight.

Once again, IE does things it's own (more complicated) way.

Solution 13 - Jquery

You can solve your problem using JAIL plugin that also allows you to lazy load images (improving the page performance) and passing the callback as parameter

$('img').asynchImageLoader({callback : function(){...}});

The HTML should look like

<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />

Solution 14 - Jquery

If you want a pure CSS solution, this trick works very well - use the transform object. This also works with images when they're cached or not:

CSS:

.main_container{
    position: relative;
    width: 500px;
    height: 300px;
    background-color: #cccccc;
}

.center_horizontally{
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: green;
  left: 50%;
  top: 0;
  transform: translate(-50%,0);
}

.center_vertically{
  position: absolute;
  top: 50%;
  left: 0;
  width: 100px;
  height: 100px;
  background-color: blue;
  transform: translate(0,-50%);
}

.center{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  background-color: red;
  transform: translate(-50%,-50%);
}

HTML:

<div class="main_container">
  <div class="center_horizontally"></div>
  <div class="center_vertically"></div>
  <div class="center"></div>
  </div>
</div

Codepen example

Codepen LESS example

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTom LehmanView Question on Stackoverflow
Solution 1 - JqueryNick CraverView Answer on Stackoverflow
Solution 2 - JqueryGusView Answer on Stackoverflow
Solution 3 - JqueryguariView Answer on Stackoverflow
Solution 4 - JqueryBjörnView Answer on Stackoverflow
Solution 5 - JqueryPiotrView Answer on Stackoverflow
Solution 6 - JquerySammayeView Answer on Stackoverflow
Solution 7 - JquerynickView Answer on Stackoverflow
Solution 8 - JqueryAllisonCView Answer on Stackoverflow
Solution 9 - JqueryChuck ConwayView Answer on Stackoverflow
Solution 10 - JqueryBjørn T. DahlView Answer on Stackoverflow
Solution 11 - JqueryJosephy BesimView Answer on Stackoverflow
Solution 12 - JqueryAliView Answer on Stackoverflow
Solution 13 - JquerysebarmeliView Answer on Stackoverflow
Solution 14 - JqueryneoRileyView Answer on Stackoverflow