jqueryhtmlajaximagesloaded

Check that AJAX retrieved images are all loaded first


When loading in html with AJAX, how can I check that all images within that HTML are fully loaded before doing "something" (like showing them).

I have tried a selection of ways, including the 'imagesloaded' plugin.

var page = 'P40',
    path = 'http://www.domain.com/gallery/embed-items/'+page;

$.get(path, function(data) {

    $(data).imagesLoaded( function() {

    $('#gallery-masonry').append($.parseHTML(data));

        $galleryContainer.masonry("reloadItems");
        $galleryContainer.masonry();

    });

});

The html that is set into 'data' is around 20 like the following:

<div class="grid col-12 bp1-col-6 bp2-col-4 bp3-col-3 item gallery-item half-divide">

    <img srcset="http://www.domain.com/images/uploads/gallery/Venice_Lagoon_Sunrise_2_Jan_2016-1550.jpg, http://www.domain.com/images/uploads/gallery/Venice_Lagoon_Sunrise_2_Jan_2016-1550.jpg 2x" title="Venice Lagoon Sunrise" alt="Venice Lagoon Sunrise">

</div>

NEW

$.get(path, function(data) {

    var doc = document.implementation.createHTMLDocument(""); // you could also use DOMParser, but parsing HTML is supported only in modern browsers.
    doc.body.innerHTML = data; // write the data to document

    var images = doc.querySelectorAll("img"), // get all images, you can specify only some though by particular selector
        amount = images.length; // inital length

    [].forEach.call(images, function(img) { // loop over images
        img.onload = function() { // bind the listener

            amount--; // ok one item was loaded, we decrease the amount

            if (amount === 0) { // if amount is equal to 0, it means the images are loaded

                $('#gallery-masonry').append(body);

                $galleryContainer.masonry("reloadItems");
                $galleryContainer.masonry();

            }

        };

    });

    var body = $('body')[0].appendParent(doc.querySelector("body")); // attach the content of body (the data you received).

});

Solution

  • There is an event fired when the image is loaded - it's called "load". You can use it and attach it to all the images you receive. You should bind that event listener before the images are added to DOM (it means before their download isn't run yet).

    Example:

    var page = 'P40',
    path = '/';
    
    $.get(path, function(data) {
      var doc = document.implementation.createHTMLDocument(""); // you could also use DOMParser, but parsing HTML is supported only in modern browsers.
      doc.body.innerHTML = data; // write the data to document
    
      var images = doc.querySelectorAll("img"), // get all images, you can specify only some though by particular selector
          amount = images.length; // inital length
    
      [].forEach.call(images, function(img) { // loop over images
        img.onload = function() { // bind the listener
          amount--; // ok one item was loaded, we decrease the amount
          if (amount === 0) { // if amount is equal to 0, it means the images are loaded
            // images loaded
          }
        };
      });
    
     // loop over the content of body (it wraps your content) and add each child of it
      [].forEach.call(doc.body.children, function(child) {
        document.body.appendChild(child); 
      });
    });
    

    Rework of your code

    $.get(path, function(data) {
        var container = $('#gallery-masonry')[0]; // container for images
    
        var doc = document.implementation.createHTMLDocument(""); // you could also use DOMParser, but parsing HTML is supported only in modern browsers.
        doc.body.innerHTML = data; // write the data to document
    
        var images = doc.querySelectorAll("img"), // get all images, you can specify only some though by particular selector
            amount = images.length; // inital length
    
        [].forEach.call(images, function(img) { // loop over images
            img.onload = function() { // bind the listener
    
                amount--; // ok one item was loaded, we decrease the amount
    
                if (amount === 0) { // if amount is equal to 0, it means the images are loaded    
                    container.style.display = "";
                    $galleryContainer.masonry("reloadItems");
                    $galleryContainer.masonry();
    
                }
    
            };
    
        });
    
        container.style.display = "none";
        [].forEach.call(doc.body.children, function(child) {
           container.appendChild(child); 
        });
    
    });