Haroldo
Haroldo

Reputation: 37377

jquery event once all images are loaded (including cached images)?

I have the following function which is for ajaxing in a page and the showing it only once all the images are loaded:

$.get('target-page.php', function(data){    
    var $live = $('#preview_temp_holder').html(data);
    var imgCount = $live.find('img').length;
    $('img',$live).load(function(){ 
        imgCount--;
        if (imgCount==0){
            //DO STUFF HERE ONCE ALL IMAGES ARE LOADED
            $('#preview_pane').html($live.children()).fadeIn(800);
            $live.children().remove();            
        }
    });                
});

The problem comes with cached images not firing the .load() event and thus not decrementing the imgCount.

I know i need to implement Nick Craver's solution but am not sure how. Can anyone help me?

Upvotes: 2

Views: 2644

Answers (3)

Ben Foster
Ben Foster

Reputation: 34800

I spent a long time looking for solutions for this. The plugin suggested on the jQuery API page (https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js) did not work in firefox.

My solution was to loop through each image and only add the load event if it was not already loaded (i.e. cached by the browser). The code below includes a counter that I was using to check that load events were only firing for images not already in the cache:

$(document).ready(function () {

    var images = $("img.lazy");
    $(".image-wrapper").addClass("loading");

    var loadedCount = 0;
    images
        .hide()
        .each(function () {
            if (!this.complete) {
                $(this).load(function () {
                    loadedCount++;
                    console.log(loadedCount);
                    displayImage(this);
                });
            }
            else {
                displayImage(this);
            }
        });
});

function displayImage(img) {
    $(img).fadeIn(300, function () {
        $(this).parents(".image_wrapper").removeClass("loading");
    });
}

I'm no javascript expert so if you spot any problems with this solution please do let me know. As I say, it works in IE8, Chrome and Firefox (not sure about older versions of IE).

Upvotes: 3

Haroldo
Haroldo

Reputation: 37377

Ok, managed to get them merged:

$.get('target-page.php', function(data){    
    var $live =         $('#preview_temp_holder').html(data);
    var $imgs =         $live.find('img')
    var imgCount =      $imgs.length;            

    $imgs.one('load', function() {        
        imgCount--;
        if (imgCount==0){
            //DO STUFF HERE
            //ALL IMAGES ARE LOADED
            $('#preview_pane').html($live.children()).fadeIn(800);

        }        
    })
    .each(function() {
        if(this.complete){
            $(this).load();
        }
    });
});  

note: a 404-ing image would break this.

Upvotes: 2

gertas
gertas

Reputation: 17145

Change:

$('img',$live).one('load', function(){
  ...
});

And after above append:

$live.find('img').each(function() {
  if(this.complete) $(this).load();
});

Generally I suggest to reuse $live.find('img') from previous count statement.

Upvotes: 0

Related Questions