7

I'm trying to implement something like a photo carousel in jQuery. This carousel could be filled with images using an array of image sources (I make an ajax request that returns a json with this data) and, once is filled, you can call a couple of methods, previous() and next() to move the carousel backward and forward respectively.

The thing is that this functionallity is already implemented and working, but I can't solve an issue on resizing process. For avoid that the images exceed the boundaries of the container, I have a method for creating and resizing the images, if needed.

this.getImageResized = function(imageSrc) {

    var image = $('<img />', {src : imageSrc});

    // Container ratio
    var ratio = this.itemMaxWidth / this.itemMaxHeight;

    // Target image ratio is WIDER than container ratio
    if((image[0].width / image[0].height) > ratio) {
        if(image[0].width > this.itemMaxWidth) {
            image.css('width', this.itemMaxWidth + 'px');
            image.css('height', 'auto');
        }
    // HIGHER
    } else {
        if(image[0].height > this.itemMaxHeight) {
            image.css('width', 'auto');
            image.css('height', this.itemMaxHeight + 'px');
        }
    }

    // Embeds image into a wrapper with item's width and height
    var wrapper = $('<span style="display : block; float : left; width : ' + this.itemMaxWidth + 'px; height : ' + this.itemMaxHeight + 'px"></span>');

    image.appendTo(wrapper);

    return wrapper;
};

Testing this function, I've found that sometimes, images are not resized as expected. I've used firebug console.log() to log the image[0].width just below jQuery element creation, finding out that sometimes the value is 0.

I'm not an expert on jQuery, but I suppose that when this happens (value is 0) is because the element is not ready.

How can I assure that the element is already loaded when I ask for its width and height values?

Is something like this possible?

var image = $('<img />', {src : imageSrc}).ready(function() {
    // But image[0].width it's not available here!
});

Thank you for your help!

Roberto Adarve
  • 167
  • 2
  • 8
  • possible duplicate of [jQuery event for images loaded](http://stackoverflow.com/questions/910727/jquery-event-for-images-loaded) – spender Jun 22 '10 at 21:42
  • @spender - Please see my comments to Sarfraz's answer...this isn't the same question, and that's not the appropriate answer either, this shouldn't be closed as a duplicate...because, well, it's a different question. – Nick Craver Jun 22 '10 at 21:50
  • @Nick, I can only think that you didn't spot that Sarfaz is using the window load event, yet the answer in the linked question uses the image load event. I'll post an answer to demonstrate, but it really shouldn't be necessary. – spender Jun 22 '10 at 22:51
  • @spender - One answer uses it...incorrectly as well, you need to attach the load handler *before* the `src` setting, and even then with cache it doesn't work cross-browser...see my answer below for how to handle this appropriately. Don't take my word for it, look at the documentation for [`.load()`](http://api.jquery.com/load-event/): "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 test the value of the image's `.complete` property." – Nick Craver Jun 22 '10 at 23:30
  • possible duplicate: http://stackoverflow.com/questions/2349137/jquery-form-focus-following-element-creation – cregox Mar 21 '11 at 22:41

3 Answers3

4

You want to use the load event in this case, like this:

var image = $('<img />', {src : imageSrc}).one('load', function() {
  // use this.width, etc
}).each(function() {
  if(this.complete) $(this).load();
});

The last bit triggers the load event in case it didn't get triggered already...which doesn't happen in some browsers when loading the image from cache, using .one() to one fire it only once and .complete to check if it's loaded.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
1

There's no platform compatible ways to see if a DOM object is "ready", see https://developer.mozilla.org/en/DOM_Events for gecko specific events

azatoth
  • 2,379
  • 15
  • 18
0

As per the answer provided here, I knocked together a working demo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
  <script type="text/javascript">
   //<![CDATA[
    $(window).load(function(){
     //window load already fired
     setTimeout(function(){ 
      var img=$('<img />'); 
      img.appendTo($("body"));
      img.load(function(){alert("img is "+$(this).width()+"px wide.")});
     },5000) //5 secs delay. definitely adding "dinamically" 
      img.attr("src","http://sstatic.net/so/img/sprites.png");
    });
   //]]>
  </script>
 </head>
 <body>

 </body>
</html>
Community
  • 1
  • 1
spender
  • 117,338
  • 33
  • 229
  • 351
  • A few things to fix here, this doesn't handle the cached case (which doesn't fire `load` in all browsers, see my answer), it should just be `img.appendTo("body"),` and you should attach the `load` handler before setting the source if doing it this way, otherwise it'll definitely not fire your load handler from cache in *any* browser, the event could fire before there's a handler for it. – Nick Craver Jun 22 '10 at 23:27
  • Fixed the order... I'd be reimplementing your answer for the rest! ;) – spender Jun 22 '10 at 23:45