4

All I need to do is locate image at the center of its parent div.
First, I tried this.

$(document).ready(function() { 
    $('#image1').css({
    'top': 50%, 'left': 50%,
    'margin-top': (-$('#image1').height()/2) + 'px',
    'margin-left': (-$('#image1').width()/2) + 'px'
    }); 
});

It failed cause $('#image1').height() and width() gives 0 before it is fully downloaded.
So I tried to keep inspecting size of the image until it has specific width and height.
like,

function inspectSize() { return ($('#image1').width() != 0); }
function setPosition() {
    if(!inspectSize()) {
        setTimeout(setPosition, 1000);
        return;
    }
    $('#image1').css({
        'top': 50%, 'left': 50%,
        'margin-top': (-$('#image1').height()/2) + 'px',
        'margin-left': (-$('#image1').width()/2) + 'px'
    }); 
}
$(document).ready(setPosition);

Still it doesn't work.
because $('#image').width() returns 28px before it is downloaded in IE8 (by the way, IE7 was fine)

So I finally tried waitForImages jQuery plugin like this,

$(document).ready(function() {
    $('#image1').waitForImages(function() {
         setPosition(); // without inspectSize() 
    });
});

It works fine with cached images, but doesn't work with non-cached images.
The function is called before Image1 has width and height.

What should I do?

alex
  • 479,566
  • 201
  • 878
  • 984
Sang
  • 2,790
  • 2
  • 20
  • 17

3 Answers3

6

You should be able to just bind your repositioning callback to the load event handler.

So in your last example:

$('#image1').load(function() {
     setPosition(); // without inspectSize() 
});

Where #image1 points to your image tag. Alternatively, as you mention the #image1 might just be a container then:-

$('#image1 img').load(function() {
     setPosition();
});

Update jfriend00 makes a good point below, in that 'load' will only fire when an image is added to the DOM, not if it already exists on the page at the time your JavaScript is run.

To cover both scenarios, you can do this:

var img = $('#image1');

if (img.prop('complete')) {
     setPosition();
} else {
     img.load(function() { setPosition(); });
}

The prop('complete') check will return true if the image already exists, and if it doesn't we bind the 'load' event handler.

isNaN1247
  • 17,793
  • 12
  • 71
  • 118
  • thanx :) by the way is it cross-browser solution? – Sang Dec 23 '11 at 08:16
  • Yes `load` will be supported by at least IE6+ as per [jQuery Browser Compatibility](http://docs.jquery.com/Browser_Compatibility). PS, don't forget to mark this as the answer if it did actually answer your question :) – isNaN1247 Dec 23 '11 at 08:19
  • @Sang - A problem with using .load() after the image has already started loading is that it may have already completed and then you won't get the load event. So, if you're going to do it this way, you have to first check to see if it's already loaded and, only if not already loaded, you can then attach the load event. Remember, images in the browser cache may load very quickly (much quicker than images coming from a web server). So, this answer (and all the others that just recommend .load() is not a complete solution). – jfriend00 Dec 23 '11 at 08:20
  • @jfriend00 now I can get it! thanx! btw, do you know why IE gives 28px when I call width() or height() before it loaded? I want to know it has been loaded or not through ($('img').width() == 0 || 28) but what if somebody uses 28px sized image? – Sang Dec 23 '11 at 08:29
  • 28px could be the size of the placeholder image that IE displays before the real image is known. I don't know for sure. Would have to see a demo of your code. As beardtwizzle has illustrated, you can check the `.complete` property. – jfriend00 Dec 23 '11 at 08:55
1

a simple example is to bind the load event to the image. I always do the following

<img data-src="image.jpg" />

note that i don't set the src attribute yet

$(function() {
    $("img").each(function() {
        $(this).load(function() {
            alert('ready to call $(this).width()');
        }).prop("src", $(this).prop("data-src"));
    });
});

the .prop("src", $(this).prop("data-src")); set's the new src after the load event is binded

Manuel van Rijn
  • 10,170
  • 1
  • 29
  • 52
  • what is the difference between your answer and beardtwizzle's answer? is there any reason that set 'src' attribute after I attach the load event? – Sang Dec 23 '11 at 08:19
  • You will never miss the `.load()` event if the event handler is attached before the `.src` is set. – jfriend00 Dec 23 '11 at 08:53
1

Try writing the same code inside.

$('window').load(function() {
    // Your code here..
});
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
Shiv Kumar Ganesh
  • 3,799
  • 10
  • 46
  • 85