0

I need to get width and height of images with display:none and I'm getting both width and height 0. here's my code:

for (i = 0; i <= slideCount; ++i) {
            imgPath = slideshow.eq(i).attr("src");
            imgEle = new Image();
            imgEle.src = imgPath;

            imgEle.addEventListener("load", function () {
                imgSize = [imgEle.width, imgEle.height];
                if ((imgSize[0]/imgSize[1]) > (boxSize[0]/boxSize[1])) {
                    slideshow.eq(i).css("height", "100%");
                }
                else {
                    slideshow.eq(i).css("width", "100%");
                }
            });
        }

I tried onload = funcion() {} approach as well as not checking if image is loaded, yet still I'm getting width and height as 0. What's more when i launched console on Chrome and referred to those fields I got proper values.

Chen-Tsu Lin
  • 22,876
  • 16
  • 53
  • 63
Shanner
  • 3
  • 1
  • 2
  • You have to add it into DOM before the dimensions are available. – Derek 朕會功夫 Feb 09 '14 at 09:43
  • 1
    `display: none` removes the element from the DOM flow so it doesn't have dimensions. You have to add it to an element that isn't display none (usually visibility: hidden) and then read the dimensions. It's not straightforward to solve. – Andy Ray Feb 09 '14 at 09:44

2 Answers2

1

It is because of the wrong use of closure variable in a loop, when the load handler is executed the variable imgEle refers to the last image object reference, not the one on which the load event was called, so when the first element is loaded the last element might not have been loaded so imgEle.width/imgEle.height will return 0

Instead you can use this which will refer to the element on which the load event was called inside the load event handler

From what I can see, what you need is

slideshow.each(function () {
    var $this = $(this);
    var imgPath = $this.attr("src");
    var imgEle = new Image();
    imgEle.src = imgPath;

    imgEle.addEventListener("load", function () {
        var imgSize = [this.width, this.height];
        if ((imgSize[0] / imgSize[1]) > (boxSize[0] / boxSize[1])) {
            $this.css("height", "100%");
        } else {
            $this.css("width", "100%");
        }
    });
})

Note: the array index runs from 0...length-1 so your loop condition <= slideCount; might have to be relooked at

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
1

imgEle is overwritten each time your loop runs. Wrap an anonymous function around it to prevent this issue.

for(var i = 0; i <= slideCount; ++i) {
    (function(i){
        var imgPath = slideshow.eq(i).attr("src");
        var imgEle = new Image();
        imgEle.src = imgPath;

        imgEle.addEventListener("load", function () {
            imgSize = [imgEle.width, imgEle.height];
            if ((imgSize[0]/imgSize[1]) > (boxSize[0]/boxSize[1])) {
                slideshow.eq(i).css("height", "100%");
            }
            else {
                slideshow.eq(i).css("width", "100%");
            }
        });
    })(i);
}
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247