47

How can I fire an event when all images in the DOM are loaded? I've googled a lot. I've found this, but it doesn't seem to work:

jQuery event for images loaded

Community
  • 1
  • 1
Dee
  • 2,905
  • 9
  • 31
  • 39
  • possible duplicate of [jQuery event for images loaded](http://stackoverflow.com/questions/910727/jquery-event-for-images-loaded) – Yarin Mar 13 '12 at 00:05

3 Answers3

118

Use the load()(docs) method against the window.

$(window).load(function() {
    // this will fire after the entire page is loaded, including images
});

Note: On newer jQuery versions use $(window).on('load', function(){ ...});

Or just do it directly via window.onload .

window.onload = function() {
    // this will fire after the entire page is loaded, including images
};

If you want a separate event to fire for each image, place a .load() on each image.

$(function() {
    $('img').one('load',function() {
        // fire when image loads
    });
});

Or if there's a chance an image may be cached, do this:

$(function() {
    function imageLoaded() {
       // function to invoke for loaded image
    }
    $('img').each(function() {
        if( this.complete ) {
            imageLoaded.call( this );
        } else {
            $(this).one('load', imageLoaded);
        }
    });
});

EDIT:

In order to perform some action after the last image loads, use a counter set at the total number of images, and decrement each time a load handler is called.

When it reaches 0, run some other code.

$(function() {
    function imageLoaded() {
       // function to invoke for loaded image
       // decrement the counter
       counter--; 
       if( counter === 0 ) {
           // counter is 0 which means the last
           //    one loaded, so do something else
       }
    }
    var images = $('img');
    var counter = images.length;  // initialize the counter

    images.each(function() {
        if( this.complete ) {
            imageLoaded.call( this );
        } else {
            $(this).one('load', imageLoaded);
        }
    });
});
codingsplash
  • 3,616
  • 6
  • 37
  • 76
user113716
  • 299,514
  • 60
  • 431
  • 433
  • this is not exactly what i need... i would fire my js suddenly, i only need to wait until images are laoded to show them and fire other events... – Dee Feb 01 '11 at 01:11
  • @Dee: I don't know what you mean. Are you saying you want to fire a separate handler for each image as it is done loading? If so, see my update. – user113716 Feb 01 '11 at 01:14
  • @patrick dw; thank you I would like to wait all images are loaded and then fire an event, i don't search for single images preloading but all images in my DOM, thank you again – Dee Feb 01 '11 at 01:19
  • @Dee: That is what the first solution does. It will not fire until all images are done loading. – user113716 Feb 01 '11 at 01:21
  • @Reigel - thank you for suggestion, i've marked... however i'm search for a more programmatic way to callback all images loaded – Dee Feb 01 '11 at 01:30
  • 2
    @Dee: If the solutions above don't do what you want, then you need to explain in greater detail. All I can tell is that you want to fire an event after all images have loaded. That's what the solutions at the top of my answer do. If that isn't enough, then please describe what you actually want. – user113716 Feb 01 '11 at 01:37
  • 1
    @patrick-dw That is an awesome solution. May i ask how would you detect when the last image is loaded, i mean using your solution is it possible to detect the last loaded image? E.g Loader keeps showing until the last image is loaded in container. – devjs11 Jul 20 '11 at 10:42
  • @Alex: Sure, implement a counter that starts off at the total number of images, then as each one's load handler is called, decrement the counter. When the counter reaches `0`, run some other function. I'll update with a solution extending the last example in my answer. – user113716 Jul 20 '11 at 12:31
  • smart solution. I will use it on my project. thanx! – norixxx Mar 08 '13 at 05:46
  • 1
    Just as a heads up, the `load` event doesn't seem to bubble up the DOM. In order for it to work for me, I have to attach the event directly on the image. So, no using `$parent.on('load', 'img', doSmthg)` to capture all images under `$parent` using event propagation. – Brandon Jan 24 '14 at 00:04
  • Thanks! I've been looking this for a while :) – Tom Sarduy Jul 24 '15 at 19:30
  • Another heads up: jQuery event aliases like `.load` or `.error` are deprecated since jQuery 1.8, instead use `.on()` to register listeners. For this answer: `$(window).on('load', function(){ ...});` – SND Aug 28 '17 at 07:44
  • @Brandon `$(window).load()` should have worked in any case, it waits till all resources are loaded in the window. Are you sure you didn't use `$(document).load()` - I believe it won't work for images (try hard refresh on page and you will see the difference in both). – Fr0zenFyr May 04 '18 at 10:20
7

Below is what I came up with, using deferred objects and $.when instead of using a counter.

var deferreds = [];
$('img').each(function() {
    if (!this.complete) {
        var deferred = $.Deferred();
        $(this).one('load', deferred.resolve);
        deferreds.push(deferred);
    }
});
$.when.apply($, deferreds).done(function() {
    /* things to do when all images loaded */
});

Let me know if there is any caveats.

holmis83
  • 13,750
  • 3
  • 63
  • 75
5

One issue I ran into with user113716's edited solution is that a broken image will keep the counter from ever reaching 0. This fixed it for me.

.error(function(){
  imageLoaded();
  $(this).hide();
});
jel
  • 1,182
  • 10
  • 8