1

I have read countless of answers of this issue and I came up with the following, but it doesn't work either.

function fitToParent(objsParent, tagName) {
    var parent, imgs, imgsCant, a, loadImg;
    //Select images
    parent = document.getElementById(objsParent);
    imgs = parent.getElementsByTagName(tagName);
    imgsCant = imgs.length;
    
    function scaleImgs(a) {
        "use strict";
        var w, h, ratioI, wP, hP, ratioP, imgsParent;
        
        //Get image dimensions
        w = imgs[a].naturalWidth;
        h = imgs[a].naturalHeight;
        ratioI = w / h;

        //Get parent dimensions
        imgsParent = imgs[a].parentNode;
        wP = imgsParent.clientWidth;
        hP = imgsParent.clientHeight;
        ratioP = wP / hP;

        //I left this as a test, all this returns 0 and false, and they shouldn't be 
        console.log(w);
        console.log(h);
        console.log(ratioI);
        console.log(imgs[a].complete);

        if (ratioP > ratioI) {
            imgs[a].style.width = "100%";
        } else {
            imgs[a].style.height = "100%";
        }
    }

    //Loop through images and resize them
    var imgCache = [];
    for (a = 0; a < imgsCant; a += 1) {
        imgCache[a] = new Image();
        imgCache[a].onload = function () {
            scaleImgs(a);

            //Another test, this returns empty, for some reason the function fires before aplying a src to imgCache
            console.log(imgCache[a].src);
            
        }(a);
        imgCache[a].src = imgs[a].getAttribute('src');
    }

}
fitToParent("noticias", "img");

To summarise, the problem is the event onload triggers before the images are loaded (or that is how I understand it).

Another things to add:

  • I don't know at first the dimensions of the parent nor the child, because they varied depending of their position on the page.
  • I don't want to use jQuery.
  • I tried with another function, changing the onload event to window, and it worked, but it takes a lot of time to resize because it waits for everything to load, making the page appear slower, that's how I came to the conclusion the problem has something to do with the onload event.

EDIT:

I made a fiddle, easier to look at the problem this way https://jsfiddle.net/whn5cycf/

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Leia
  • 357
  • 3
  • 17

1 Answers1

0

for some reason the function fires before aplying a src to imgCache

Well, the reason is that you are calling the function immedeatly:

  imgCache[a].onload = function () {

  }(a);
// ^^^ calls the function

You call the function and assign undefined (the return value of that function) to .onload.

If you want to use an IIFE to capture the current value of a, you have to make it return a function and accept a parameter to which the current value of a is assigned to:

imgCache[a].onload = function (a) {
  return function() {
    scaleImgs(a);
  };
}(a);

Have a look again at JavaScript closure inside loops – simple practical example .

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • I modified it and there's still a problem. Give me a minute, I'll do fiddle of it. – Leia Nov 18 '15 at 16:39
  • I assume the problem may be with your `scaleImgs` functions. You probably want to access the element in `imgCache`, not `imgs`. But not really sure. – Felix Kling Nov 18 '15 at 16:44
  • I added the fiddle with your changes – Leia Nov 18 '15 at 16:50
  • Two issues with your changes: 1) The IIFE still executes immediately, that's its purpose. The `console.log` will still log `undefined` since you are calling it before you set the `src`. You have to move that call inside the inner function. 2) You forgot to add `a` as parameter to the outer function. Please have a look at the link to understand how IIFE's work. – Felix Kling Nov 18 '15 at 16:53
  • I got it working, thanks! I still don't fully grasp the concept of closures but I'll keep reading about the subject. – Leia Nov 18 '15 at 18:49