views:

124

answers:

5

I use a Json call to get a list of image addresses, then I add them individually to a div like this. Unfortunately the image dimension is not part of the Json information.

<div id="container">
   <img src="A.jpg" alt="" />
   <img src="B.jpg" alt="" />
   ...
</div>

Do any of you JQuery geniuses know of a code that would flawlessly and dynamically add the true Width and Height to each img element in the container as soon as each individual one is rendered?

I was thinking maybe the code could do a image width check width > 0 to evaluate when the image has actually been rendered, then fire. But I wouldn't know how to go about that and make it work stably. How is the best way of going about this?

Thank you so much!

Update, As the answers point out, adding Width or Height to the elements is pretty routine. The problem here is actually writing a code that would know when to do that. And evaluate that condition for each image not the page as a whole.

Update 2
I found a very nice working answer here

+1  A: 

try this:

$('#container img').css('height', function(index, value){
    return $(this).height()+ 'px';
})
$('#container img').css('width', function(index, value){
    return $(this).width() + 'px';
})

EDITED

ok, I have tried something like this and when I inspect the elements using firebug, height and width attribute is there withe right values....

$(document).ready(function(){

  $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&amp;tagmode=any&amp;format=json&amp;jsoncallback=?",
        function(data){
          $.each(data.items, function(i,item){
            $("<img/>").attr("src", item.media.m).appendTo("body");
            if ( i == 999 ) return false;
          });
          $('img').css('height', function(index, value){
              return $(this).height()+ 'px';
          });
          $('img').css('width', function(index, value){
              return $(this).width()+ 'px';
          });
  });
})

demo

Reigel
But wouldn't this execute too early? Like as the images are loading on the page, (there are quite a few) wouldn't this only be able to work for the images that are already cached and rendered?
Mohammad
I see that you are using ajax call, so just call that lines of codes on the callback... the part after your code added all the images...
Reigel
True, but I would need it to fire for each individual image after it has rendered. Not when the DOM has been updated with the new img elements. If that code fires too early it will not be able to find the image dimensions since the image is not there yet. Lets say for 100 images, and only the first 20 have been rendered. The other 80 will have 0 x 0 dimensions with this code right?
Mohammad
please see edited above...
Reigel
Reigel: But you're still waiting until all images have been loaded, aren't you?
codethief
@codethief: No actually the code is not waiting for the images to load. @Reigel: The code worked for me the first time I used it but the second and third time I received this: http://27.media.tumblr.com/tumblr_l1bt1rdUIp1qzee9jo1_500.png I don't understand why it worked the first time since theoretically it should always return the height and width value of the element when the code fires and I would guess that is just as the images are being http requested. Thus returning all zeros. Thank you for all your effort though, really appreciated.
Mohammad
+1  A: 

Yes, you can, you can use the width() and height() methods to get the dimensions of the images. Thanks to JQuery.

More Info:

Update Baded On Comment:

The load even is fired when all images and external resources have loaded into the page along with the DOM, so you can use that and use the width() and height() methods to get the dimensions of the images. Example:

$(window).load(function(){
  // your code to get dimensions, manipulate images, etc
})
Sarfraz
you will need to wait for the images to finish loading though, before this information will be correct.
rikh
True, that's actually what this question is about, how to know when the images are loaded then have a code fire right afterwards. But I'm looking for the most foolproof way of doing it. :)
Mohammad
@Mohammad: Please see my updated answer.
Sarfraz
Thank you, could we add the same functionality to the individual <img> elements after the dom has been updated so the function would be fired individually, <img> number of times instead of once and for all of them?
Mohammad
@Mohammad: You can put any code you want in load event when dealing with images.
Sarfraz
A: 

Use $(document).ready() to wait for the images to be completely loaded.

ready (handler)

handler - A function to execute after the DOM is ready.

While JavaScript provides the load event for executing code when a page is rendered, this event does not get triggered until all assets such as images have been completely received.

Reigel's solution, now with the use of $(document).ready():

$(document).ready(function() {
    $('#container img').css('height', function(index, value){
        return $(this).height()+ 'px';
    });
    $('#container img').css('width', function(index, value){
        return $(this).width() + 'px';
    });
});

[EDIT]: Just realized that this may not work when you insert the images after the page has loaded but I guess it's worth a try:

$('#mydiv').html('<img .../><script language="javascript" type="text/javascript">$(document).ready(...)</script>');
codethief
Thank you but like the question mentions it has to be a dynamic event that checks the rendered state for **each** image and fires for each image as soon as it has been rendered. Not when everything has loaded.
Mohammad
Oops, must have missed that.
codethief
@ [EDIT] That wouldn't work either, since it would introduce a race condition. A working code would need to be aware of each individual image's state and fire individually for each of them. But thanks!
Mohammad
A: 

Another suggestion:

Load the images via AJAX in the background and hope for the browser to cache them, so that they are instantly there when you add the elements to your div (and you can retrieve width() and height() immediately). ;)

If you have any access to the webserver which sends those images: Make sure you set the appropriate cache headers.

[EDIT]: Instead of relying on the cache you could also put the image data, which you just loaded via AJAX, directly into your source code. Unfortunately, this apparently doesn't work in IE.

<img src="data:<mimetype>;base64,<data>" />

To encode the data use a function like this one.

codethief
I don't have access to the web server at all but counting on the cache on the browser side to be enabled could be counter productive. I still think there should be a way to do this by checking for the img element's width.
Mohammad
@codethief next time, just edit your answer if you have another suggestions... don't use more than one... thanks!
Reigel
@Reigel: And this is why you voted it down? Let alone, it's a completely different approach so it deserves another entry.
codethief
@codethief yeah... did happen to me too the first time i was here... :)
Reigel
@Reigel First of all, it not the first time I'm here. Besides, it IS a different and separate approach. See http://meta.stackoverflow.com/questions/25209/what-is-the-official-etiquette-on-answering-a-question-twice
codethief
A: 
$('#container img').each(function(){
var pic_real_width;
var pic_real_height;

$(img).load(function() {
    // Remove attributes in case img-element has set width and height
    $(this).removeAttr("width")
           .removeAttr("height")
           .css({ width: "", height: "" }); // Remove css dimensions as well

    pic_real_width = this.width;
    pic_real_height = this.height;
});

var src = img.src;
img.src = "";
img.src = src; // Triggers onload if image is cached
});

Credit goes to Xavi

Mohammad