0

This is not a duplicate question. I have been working on loading images after the complete page load. I want to pass variable i value to the onload function of img but somehow that's not working.

var imgs = document.getElementsByTagName('img');
var totalImages = imgs.length;
for(var i=0; i<totalImages; i++)
{
    if(imgs[i].hasAttribute('data-src'))
    {
        var img = new Image();
        img.onload = function()
        {
            imgs[x].src = imgs[x].getAttribute('data-src');
            imgs[x].setAttribute('srcLoaded','true');
            //where x is i value from for loop
        };
        img.src = imgs[i].getAttribute('data-src');
    }
}

I tried following onload function

img.onload = (function(x)
{
    imgs[x].src = imgs[x].getAttribute('data-src');
    imgs[x].setAttribute('srcLoaded','true');
    //where x is i value from for loop
})(i);

but in this way, I saw that function is executed immediately even the image is not completely loaded may be because this is somehow working as anonymous function.

I also tried by setting attribute to my img object and getting its value inside function like this

img.setAttribute('idi',i);
img.onload = function()
{
    var x = img.getAttribute('idi');
    imgs[x].src = imgs[x].getAttribute('data-src');
    imgs[x].setAttribute('srcLoaded','true');
    //where x is i value from for loop
};

but that's not working as well. How can I pass variable i value to my onload function?

Airy
  • 5,484
  • 7
  • 53
  • 78
  • The IIFE has to return a function like `img.onload = (function(x) { return function() { imgs[x].src = imgs[x].getAttribute('data-src'); imgs[x].setAttribute('srcLoaded', 'true'); //where x is i value from for loop } })(i);` – Arun P Johny Mar 01 '16 at 12:14
  • But it still be only one function, as it's overwritten in each iteration. – u_mulder Mar 01 '16 at 12:15
  • @ArunPJohny I already mentioned that your suggested way is not working. – Airy Mar 01 '16 at 12:55

2 Answers2

1

You can bind the variable on your callback function:

var imgs = document.getElementsByTagName('img');
var totalImages = imgs.length;
for (var i = 0; i < totalImages; i++) {
    if (imgs[i].hasAttribute('data-src')) {
        var img = new Image();
        img.onload = (function (x) {
            imgs[x].src = imgs[x].getAttribute('data-src');
            imgs[x].setAttribute('srcLoaded', 'true');
            //where x is i value from for loop
        }).bind(img, i);
        img.src = imgs[i].getAttribute('data-src');
    }
}
Adam
  • 4,985
  • 2
  • 29
  • 61
  • I have about 250 images on my page and when I run with your suggested way, it stops and hangs for a while which is kinda bad impression – Airy Mar 01 '16 at 12:57
  • Can you show the jsfiddle example? I'm pretty sure, the delay caused by this code. – Adam Mar 01 '16 at 12:59
  • @AbdulJabbarWebBestow I've commented out a line. Pls try like this. – Adam Mar 01 '16 at 13:03
  • No that line is important. Actually that is the important thing to do. – Airy Mar 01 '16 at 13:07
  • because imgs[x] is the real image and img which I set is the only temporary object which loads the actual image and fires the onload function which in turn loads the cached image into real image imgs[x] – Airy Mar 01 '16 at 13:10
  • I see now. I've missed the `s` in `imgs`. – Adam Mar 01 '16 at 13:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/105010/discussion-between-adam-and-abdul-jabbar-webbestow). – Adam Mar 01 '16 at 13:12
0

Call the function when the page has initialized, once, and let it be done.

Instead of calling onload on your images 250+ times (slowing down your page, as per your comment on Adam's answer, which is the opposite of what you want), maybe see what the tutorial has in store for you.

Re-inventing the wheel, but following this tutorial gives you a simple and straight-forward way to do it https://varvy.com/pagespeed/defer-images.html (and it looks like your code might be derived from it)

Hope this helps

zerohero
  • 593
  • 4
  • 15
  • I already read that article. What if I want to show a default image until the actual image is loaded? – Airy Mar 01 '16 at 13:13
  • In the article it shows you the following: img src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" data-src="your-image-here" The data:image/png is the default image in src= (which is a placeholder) until the code processes data-src, you can change this to anything you want. – zerohero Mar 01 '16 at 13:17
  • the data:image/png can be set using CSS as well, so you can default all images on the page using CSS once (smaller footprint) and have the JS kick in as soon as the page is loaded fully. – zerohero Mar 01 '16 at 13:18