tags:

views:

54

answers:

3

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!

+1  A: 

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
Thank you very much Nick! This works just fine!!!
A: 

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
A: 

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"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
 <head>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"&gt;&lt;/script&gt;
  <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>
spender
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
Fixed the order... I'd be reimplementing your answer for the rest! ;)
spender