ccdavies ccdavies - 6 months ago 14
HTML Question

Check that AJAX retreived 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).

});

Answer

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); 
    });

});
Comments