0

I have the following code:

function fn_get_natural_dim(){
    var width = this.width;
    var height = this.height;

    var ratiow = width/600;
    var ratioh = height/300;
    $("#output").append(img_name,",");

    if(ratiow>=ratioh)
        {
        height = height/ratiow;
        $(slide_image).css("width","600px");
        $(slide_image).css("height",height);
        var margin = (300-height)/2;
        $(slide_image).css("margin-top",margin);
        }
    else
        {
        width = width/ratioh;
        $(slide_image).css("width",width);
        $(slide_image).css("height","300px");
        var margin = (600-width)/2;
        $(slide_image).css("margin-left",margin);
        }
}
var max_count = $(".slider").children().length;
for(var count=1;count<=max_count;count++)
    {
    var count_string = count.toString();
    var img_name = "img" + count_string;
    var slide_image = document.getElementById(img_name);

    var img = new Image();
    img.onload = fn_get_natural_dim;
    img.src = $(slide_image).attr("src");
    }
});

For each image (i have three at the moment), im getting its natural dimensions so that i can calculate the margin necessary to fit a 600x300 div.

but i only works for the very last one, ie the third one. in other words, in the #output, it shows "img3,img3,img3," (called by $("#output").append(img_name,",");) how do i make it show "img1,img2,img3,"??

  • possible duplicate of [function inside for loop (js/jquery)](http://stackoverflow.com/questions/17832506/function-inside-for-loop-js-jquery) – Barmar Jul 24 '13 at 12:04
  • You asked the exact same question less than an hour ago. – Barmar Jul 24 '13 at 12:05
  • @Barmar it's not the exact same question - this code is (somewhat) fixed with the answer I gave to the previous question. Now the OP has a different problem. – Alnitak Jul 24 '13 at 12:08
  • @Alnitak Yeah, I jumped the gun a little. – Barmar Jul 24 '13 at 12:11

2 Answers2

2

You can do this:

    img.onload = (function(img_name, slide_image) {
        return function() {fn_get_natural_dim(img_name, slide_image); };
    })(img_name, slide_image);

and change fn_get_natural_dim to take the image name as a parameter:

function fn_get_natural_dim(img_name, slide_image) {

The above code captures each successive value of img_name in a closure variable.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • by "change fn_get_natural_dim to take the image name as a parameter." do you mean make it to fn_get_natural_dim(img_name) ? – quasicoherent_drunk Jul 24 '13 at 14:07
  • Yes, that's exactly what I mean. – Barmar Jul 24 '13 at 14:08
  • hmm it doesn't seem to work. first of all, for some reason, the #output shows "#img1,#img3,#img2" and the margins for #img1 and #img2 are not changed, and #img3 becomes too big for some reason – quasicoherent_drunk Jul 24 '13 at 14:15
  • You're running this in the `onload` handler, and images won't necessarily finish loading in the same order that you started them. They'll be displayed in whatever order they loaded. – Barmar Jul 24 '13 at 14:20
  • i see. well, i guess that's not too big of a problem. but the margins do not seem to work properly – quasicoherent_drunk Jul 24 '13 at 14:23
  • I didn't see that you were also using `slide_image` similarly to `img_name`. You need to do the same thing with that variable as was done with `img_name`. – Barmar Jul 24 '13 at 14:30
  • and i guess i do have to ask: why exactly do i have to set img_name and slide_image as parameters? and what exactly does return function() {function_name(parameter);} do? – quasicoherent_drunk Jul 24 '13 at 14:37
  • Sigh, this is one of the most common questions that comes up. I thought I just did one of these a couple of days ago, and I was trying to find it to link to, but I couldn't. Search some of the questions about javascript closures. – Barmar Jul 24 '13 at 14:41
-1

Edit

As Barmar pointed out, this solution isn't exactly correct. I'll leave it up as it's a fairly common mistake and is important to note the difference between his solution and my own.


Pass img_name into your fn_get_natural_dim function:

function fn_get_natural_dim( img_name ) { ... }

Then call it like:

img.onload = function() { fn_get_natural_dim(img_name); };
André Dion
  • 21,269
  • 7
  • 56
  • 60
  • 1
    That won't work because `img_name` isn't a closure variable. You need a wrapper function to close it. – Barmar Jul 24 '13 at 12:12
  • @Barmar: Why not? The function has access to img_name from my point of view, since it is defined inside the loop. – zkar Jul 24 '13 at 12:17
  • 1
    But the loop is not a variable scope in JS. So each iteration references the same `img_name` variable. – Barmar Jul 24 '13 at 12:17
  • Then you can create a new scope to bind the value, if needed with a new function. – zkar Jul 24 '13 at 12:19
  • @zkar Barmar is correct. See http://stackoverflow.com/questions/643542/doesnt-javascript-support-closures-with-local-variables – André Dion Jul 24 '13 at 12:22