views:

3942

answers:

7

I'm writing some Javascript to resize the large image to fit into the user's browser window. (I don't control the size of the source images unfortunately.)

So something like this would be in the HTML:

<img id="photo"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Is there a way for me to determine if the src image in an img tag has been downloaded?

I need this because I'm running into a problem if $(document).ready() is executed before the browser has loaded the image. $("#photo").width() and $("#photo").height() will return the size of the placeholder (the alt text). In my case this is something like 134 x 20.

Right now I'm just checking if the photo's height is less than 150, and assuming that if so it is just alt text. But this is quite a hack, and it would break if a photo is less than 150 pixels tall (not likely in my particular case), or if the alt text is more than 150 pixels tall (could possibly happen on a small browser window).


Edit: For anyone wanting to see the code:

$(function()
{
  var REAL_WIDTH = $("#photo").width();
  var REAL_HEIGHT = $("#photo").height();

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(REAL_HEIGHT < 150)
    {
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
      if(REAL_HEIGHT < 150)
      {
        //image not loaded.. try again in a quarter-second
        setTimeout(adjust_photo_size, 250);
        return;
      }
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});


Update: Thanks for the suggestions. There is a risk of the event not being fired if I set a callback for the $("#photo").load event, so I have defined an onLoad event directly on the image tag. For the record, here is the code I ended up going with:

<img id="photo"
     onload="photoLoaded();"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

Then in Javascript:

//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
{
  isPhotoLoaded = true;
}

$(function()
{
  //Hides scrollbars, so we can resize properly.  Set with JS instead of
  //  CSS so that page doesn't break with JS disabled.
  $("body").css("overflow", "hidden");

  var REAL_WIDTH = -1;
  var REAL_HEIGHT = -1;

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(!isPhotoLoaded)
    {
      //image not loaded.. try again in a quarter-second
      setTimeout(adjust_photo_size, 250);
      return;
    }
    else if(REAL_WIDTH < 0)
    {
      //first time in this function since photo loaded
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});
+5  A: 

Either add an event listener, or have the image announce itself with onload. Then figure out the dimensions from there.

<img id="photo"
     onload='loaded(this.id)'
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />
Diodeus
According to spec, onload is only an event for the body and frameset elements; that said, I think this works in IE, but I don't know that it works in any other browsers or that it is something you can assume...I was just looking into this a couple of weeks ago...
Jason Bunting
I have tested it in IE6, IE7, FF3, Opera9, Safair (Windows Beta), and Chrome (Windows Beta).
Kip
+1  A: 

Try something like:

$("#photo").load(function() {
    alert("Hello from Image");
});
Allain Lalonde
Thanks. However, there is a possibility that the image has already been loaded before this happens, in which case the load event wouldn't be fired.
Kip
How about a script tag setting this event right after the image tag? The reason to use ready is to make sure the entire document is loaded, which is unnecessary in this case, right?
Jason Goemaat
+4  A: 

You want to do what Allain said, however be aware that sometimes the image loads before dom ready, which means your load handler won't fire. The best way is to do as Allain says, but set the src of the image with javascript after attaching the load hander. This way you can guarantee that it fires.

In terms of accessibility, will your site still work for people without javascript? You may want to give the img tag the correct src, attach you dom ready handler to run your js: clear the image src (give it a fixed with and height with css to prevent the page flickering), then set your img load handler, then reset the src to the correct file. This way you cover all bases :)

Andrew Bullock
The site still works for people without Javascript, they just have to scroll to see all of the image.
Kip
+1  A: 

Here you have an example of adding a callback after the image has finished loading.

Elzo Valugi
A: 

"But set the src of the image with javascript after attaching the load hander. This way you can guarantee that it fires."

Example of this?

Per G
A: 

Hi!

Any comments on this one?

... doShow = function(){ if($('#img_id').attr('complete')){ alert('Image is loaded!'); } else { window.setTimeout('doShow()',100); } };

$('#img_id').attr('src','image.jpg');

doShow(); ... Seems like works everywhere...

Jay
+1  A: 

The right answer, is to use event.special.load

It is possible that the load event will not be triggered if the image is loaded from the browser cache. To account for this possibility, we can use a special load event that fires immediately if the image is ready. event.special.load is currently available as a plugin.

Per the docs on .load()

Evan Carroll