0

I have a framework (vue.js) inserting some images on a page change (with a router, not a real page refresh). When loaded directly, I can make the page display a loading screen:

loading = true;
$(window).on( 'load', function(){
    loading = false;
});

However, the $(window).on('load') doesn't trigger if the page has been navigated via the framework. This (I assume) is because the window is already loaded, and the loading of the new images isn't tied to the window anymore. So, the loading = false never triggers because the window already loaded.

Here's an extremely simplified example, but it illustrates the same point:

//Loading the initial image, it works fine because it runs on window load.
console.log('Loading first image...')
$(window).on('load',function(){
    console.log('First image loaded');
});


$('button').on('click',function(){
  $('div').append('<img src="https://placekitten.com/200/300">');
  console.log('Loading extra image...');

  //This never triggers because the window is already loaded. 
  //I need something to trigger while the appended images are loading
  $(window).on('load',function(){
    console.log('Extra image loaded.');
  });

});

HTML:

<img src="https://placekitten.com/200/300">
<button>Click to load extra</button>
<div></div>

Here's a codepen.

Aaa
  • 900
  • 3
  • 9
  • 22
  • No idea if this works, but have you tried: `$(window).trigger('load');`? (I don't believe you can trigger an event with `on`) Though, I have to ask, why do you need to do this? You can listen for the loading of new images separately. – DBS Jun 19 '16 at 22:55
  • Loading the image before adding it to the page, also allows you to run any code once loaded: http://stackoverflow.com/questions/10863658/load-image-with-jquery-and-append-it-to-the-dom – DBS Jun 19 '16 at 23:00
  • @DBS Wouldn't trigger just trigger the load event, regardless of whether the image is actually loaded? How would I set this up? You also mentioned listening for the loading separately. Also not sure what you mean by this. As for your second comment, sadly that isn't really an option with the framework I'm using. Not without much difficulty, anyways. – Aaa Jun 19 '16 at 23:09
  • What I would do is set up your "load" handler to also handle your own special "new-content" event: `$(window).on("load new-content", ... )`. Then you can trigger a "new-content" event any time you want. – Pointy Jun 20 '16 at 20:32

2 Answers2

1

You can add a .load() listener to each new image with a unique identifier, and track them with an array which you can use to run a function once ALL images are loaded:

var loadingImages = [];
$('button').on('click',function(){

  //Get unique identifier + add to 'loading'
  var n = $('div').find("img").length;
  loadingImages.push(n);

  //Add image with unique classname
  $('div').append('<img data-n="'+n+'" src="https://placekitten.com/200/300">');

  //Attach load listener to new image
  $('div').find("img[data-n="+n+"]").load(function(){
    var n = $(this).attr('data-n');

    //Remove from 'loading'
    var index = loadingImages.indexOf(n);
    loadingImages.splice(index, 1);

    //if 'loading' empty, run function
    if(loadingImages.length==0){
        alert("Loaded All Images");
    }
  });
});

Example: JSFiddle

hakJav
  • 301
  • 1
  • 5
  • Wow, this is pretty close -- Looks like its almost there. However, my problem is a bit more complicated than the example. The `last()` image doesn't necessarily load last. Can you think of a way to modify this so that ALL the ``'s are loaded before the function triggers? I'm stuck. – Aaa Jun 19 '16 at 23:51
  • Hmm... I think I got it - see edits above - I added a unique identifier to each IMG, and tracked each loading image in an array, which when empty runs your code (in this case a simple alert). – hakJav Jun 20 '16 at 01:06
  • Hah, awesome solution! I'll give it a try and see how it runs. – Aaa Jun 20 '16 at 01:19
  • Your code set me on the right track, but I had to rewrite it to fit my specific circumstance (there were several things that your code didn't cover). If you're interested, I posted a more detailed response as another answer. Thanks for the help! – Aaa Jun 20 '16 at 04:22
0

@hakJav 's solution was on the right track, but I needed to make some edits. They were major enough that I decided to post my own answer. Although his answer didn't necessarily solve my problem, it's good code, and could be a solution to someone else's. Definitely check both answers.

Here's my JS function (goes with the HTML from my original post):

$('button').on('click',function(){
        $('div').html('<img src="https://placekitten.com/200/400"><img src="https://placekitten.com/100/300">');
        var loadingImages = [];
        //Array of existing images
        var arrayOfImages = $('div').find('img');
        //Loops through array
        for(var i=0; i < arrayOfImages.length; i++){
            //Creates numerical value for each image, puts it in an array of images that are currently loading
            loadingImages.push(i);

            //For each image, add a load listener. Pass in i from the for loop so that it gets recorded in the event listener.
            $(arrayOfImages[i]).on('load', { currentImage: i }, function(event){
                //On load, removes the value from the array. Display which image loaded, for debugging.
                var index = loadingImages.indexOf(event.data.currentImage);
                loadingImages.splice(index, 1);
                console.log('image '+event.data.currentImage+' loaded');

                //Checks if the array is empty (last image loaded). If so, log all.
                if(loadingImages.length === 0){
                    console.log('all loaded');
                }
            });

        }

});

This has the advantage of being able to loop through all the images already in a container, and not necessarily rely on being able to specify a data attribute in the html being appended. Also can deal with "groups" of images, i.e. multiple images in the same string of HTML. So probably more extensible.

This has the disadvantage of not being able to load additional images after the first set has been walked through, for example if the .html() was replaced with .append(). The original images would still exist, fully loaded, so their values would stay in the array. This could probably be fixed with some doing, if needed (I only had to load one set of images at a time).

Here's a codepen demonstrating this: http://codepen.io/Blue_Dragon360/pen/GqjyGJ?editors=1010

Aaa
  • 900
  • 3
  • 9
  • 22