jquery - Dynamically adding HTML with Javascript which has <img> tags. How do I tell when the images are loaded -

Lets say I have a div, and want to inject into that div some HTML. The HTML will include 1 or more imag

Lets say I have a div, and want to inject into that div some HTML. The HTML will include 1 or more images.

Is there any way with plain JavaScript or jQuery to determine when the images have loaded?

So if I do the following, can you place an event listener onto a single element to tell when the contents, including images, is ready?:

var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
$("div.output").html(html);

The images will be different every time so I cannot preload using JavaScript image object.

One method I'm thinking of doing is running through the HTML with regular expressions or jQuery, finding all image URLs, loop through them and preload each with the image object. When all have been preloaded, then inject the HTML into the output div.

Lets say I have a div, and want to inject into that div some HTML. The HTML will include 1 or more images.

Is there any way with plain JavaScript or jQuery to determine when the images have loaded?

So if I do the following, can you place an event listener onto a single element to tell when the contents, including images, is ready?:

var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
$("div.output").html(html);

The images will be different every time so I cannot preload using JavaScript image object.

One method I'm thinking of doing is running through the HTML with regular expressions or jQuery, finding all image URLs, loop through them and preload each with the image object. When all have been preloaded, then inject the HTML into the output div.

Share Improve this question asked May 7, 2012 at 18:49 FergalFergal 2,4744 gold badges36 silver badges49 bronze badges 1
  • Don't use REGEX: stackoverflow./questions/1732348/… – Diodeus - James MacFarlane Commented May 7, 2012 at 18:54
Add a ment  | 

7 Answers 7

Reset to default 2

Unless you hook up an onload event to each image before it loads and count them up, there's no easy way to tell when they're all loaded.

Here's a relatively bulletproof method (demo) that uses Deferreds, tested and working in IE 6-9, Chrome 19, and Firefox 3.6-10, Opera 10.10-11.52, Android 4, and iOS 5.

First, we'll write a small jQuery plugin that returns an array of Deferreds for each element in the jQuery collection. Each Deferred will be resolved when the element loads; or rejected if the element fails to load or (optionally) takes longer than timeout seconds.

$.fn.loaded = function(opts) {
    var o = $.extend({timeout:10000}, opts) // Merge default options with supplied options
        , r = []; // Return value

    this.each(function() {
        var dfd = new $.Deferred(), el = $(this), to;
        if (o.timeout) to = setTimeout(function() {
            done();
            dfd.reject();
        }, o.timeout);
        el.bind('load.dfdl', function() {
            done();
            dfd.resolve();
        }).bind('error.dfdl', function() {
            done();
            dfd.reject();
        });

        function done() { // internal clean-up
            clearTimeout(to);
            el.unbind('.dfdl');
        }
        r.push(dfd.promise());
    });
    return r;
};

The timeout will guard against cases where the browser never actually fires any events. I've set the default timeout to 10 seconds here; in the real world you might want to reduce that.

Now we'll generate 10 randomly-sized placekittens to use as images in the example.

var imgs=[];
for (var i = 0; i < 10; i++) imgs.push('<img src="http://placekitten./' + rnd() + '/' + rnd() + '"> ');
$('#imgs').html(imgs.join());

Finally, we'll put everything together with some magic:

$.when.apply($, $('#imgs img').loaded({timeout:10000}) ).done(function() {
    alert('loaded successfully');
}).fail(function() {
    alert('load failed or timed out');
});

$.when creates a master Deferred that gets resolved only when all of its child Deferreds resolve, or rejects when a child rejects. It normally expects you to pass each Deferred as an argument (it does not support passing in an array of Deferreds), so we have to apply our array. (I might do $.whenall = function(dfds) { $.when.apply($,dfds); }; so that your app code has a cleaner $.whenall( $('#imgs img').loaded() )...)

Try this:

$("#preload_div").html(
    '<img src="image.png" alt="preload" class="preload" width="0" height="0">'
);

The event handler can be bound to the image:

$('preload').load(function () {
    var html = "<p>Some text <img src='image.jpg' /></p><p>Some more text <img src='image2.jpg' /></p>";
    $("div.output").html(html);
});

Of course, you would have to incorporate an .each() for each image to loop through all images.

EDIT: On one of my AJAX websites, I preload the next image I need, so when a user clicks the 'next' button, the image that the new content needs is already cached. See http://funl.es/p/1

One method I'm thinking of doing is running through the HTML with regular expressions or jQuery, finding all image URLs, loop through them and preload each with the image object. When all have been preloaded, then inject the HTML into the output div.

var imagesLoaded = [];
var imagesErrored = [];

$('img').each(function() {
     $(this).load(function() {
         imagesLoaded.push($(this).attr("src"));
         if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
             displayResults(imagesLoaded, imagesErrored);

         } 
     });
     $(this).error(function() {
         imagesErrored.push($(this).attr("src"));
         if( (imagesLoaded.length + imagesErrored.length) == $('img').length ) {
             displayResults(imagesLoaded, imagesErrored);
         } 

});

function displayResults(imagesLoaded, imagesErrored) {
    for(var i = 0; i < imagesLoaded.length; i++) {
        alert(imagesLoaded[i] + " has loaded successfully.");
        $('#myDiv').append("<img src='" + imagesLoaded[i] + "' />");
    }
    for(var i = 0; i < imagesErrored.length; i++) {
        alert(imagesLoaded[i] + " did NOT load successfully.");
    }
}

The above loops through all images and checks whether or not they loaded, using the load event. Using the error event, we also get a collection of all images that for whatever reason did not load correctly. After all images have been preloaded, we can then inject them onto the page in the "displayResults" function. This is based loosely on the last paragraph in your question.

However, it doesn't use regular expressions, as they are not the right tool for manipulating the DOM. Fortunately, JavaScript and jQuery provide us with the tools we need to perform DOM manipulations and parsing activities.

Finally, from your question, it sounded like you may have been interested in knowing what images loaded successfully. The above collections that are built from the load and error events will provide you with those details, should you need them.

I think you should bind the load handler after you insert the images into the html.

DEMO

    //Add image
    $('#result').append('<img src= "<Your_Image_URL>" width="300" height="300"/>');

    //Bind handler also add condition to not bind images that was not added before.
    $('#result').find('img').not('.loaded').on('load', function () {
        alert('Image Loaded');
        //Add code that you want to do after the image is added
    }).addClass('loaded');

Also please be aware of Caveats of the load event when used with images

A mon challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have pletely loaded. There are several known caveats with this that should be noted. These are:

  1. It doesn't work consistently nor reliably cross-browser
  2. It doesn't fire correctly in WebKit if the image src is set to the same src as before
  3. It doesn't correctly bubble up the DOM tree
  4. Can cease to fire for images that already live in the browser's cache

Reference: http://api.jquery./load-event/

Have you considered using the jQuery 'on' event mechanism? Using 'on' should allow you to automatically bind 'load' handlers to each image as it gets dynamically added to the container and DOM.

Link: jQuery docs for'on' function

If you're using pre 1.7 jQuery, you'll need to use the 'live' function since 'on' was added with the 1.7 release.

Link: jQuery docs for 'live' function (deprecated)

I think that there is no easy way to do that. The thing that you could do is to load all the images on a div that is hidden ( display: none ).

When you want to show the pictures you can do:

$("#myDiv").show();

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745429258a4627317.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信