Fernker
Fernker

Reputation: 2288

jQuery get img width after src change and before fadeIn

I've got quite the problem with jQuery and a custom photo gallery I am building. I've searched high and low and tried endlessly different solutions but nothing is working perfectly. So let me present the information:

This photo gallery has thumbnails on the left side and a big image in the center. Every thumbnail can be clicked which calls a function passing in its' ID. What I want it to do is, AJAX POST to server to get image comment and image name. Fadeout the current big picture div, switch the src in the img tag, get the new image's width, set the width of an overlaying comment div, fadeIn the big picture div.

The problem is that I can't get the width of the new image after it has loaded (even using the a form of .load() to wait for the image to finish loading). Now I can get it to work when I fadeIn the new image and then get the width but that isn't what I need. I need to get the width and set the div's width before I fadeIn.

Any ideas or corrections would be great, hopefully I have provided enough information.

Here is the code I am wrestling with:

function thumbClick(val) {
    $.post('ajax.php', {
        photo_in: val
    }, function (data) {
        $('div#picture').fadeOut('slow', function () {

            //$('img#big-picture').load(function(){
            $('img#big-picture').one('load', function () {

                //alert($('img#big-picture').width());
                //will alert 0
                $('div#picture').fadeIn('slow', function () {
                    $('div#comment-box').width($('img#big-picture').width());
                    //set comment to what I want
                    $('p#comment').html("");
                    //alert($('img#big-picture').width());
                    //will alert new image width after FadeIN
                    $('p#comment').html(data.comment);
                });

            }); //end of one(load)
            $('img#big-picture').attr("src", data.newImage);


        }); //end of fadeout
    }, "json"); //end of post
}

Upvotes: 0

Views: 3544

Answers (3)

Matt Ball
Matt Ball

Reputation: 359816

The width is zero because hidden elements (elements with display: none have, by definition, zero height and width). After fadeOut(), jQuery hides the element(s). A few different solutions:

Use .fadeTo(), not .fadeOut():

$('#picture').fadeTo('slow', 0, function () {
    var $pic = $(this);

    $('#big-picture').one('load', function () {

        var $bigPic = $(this);

        $pic.fadeIn('slow', function () {
            $('#comment-box').width($bigPic.width());
            $('#comment').html(data.comment);
        });

    }).attr('src', data.newImage);
});

Use a separage <img> element:

$('#picture').fadeOut('slow', function () {
    var $pic = $(this);

    $('#big-picture').one('load', function () {

        var img = new Image(),
            width;

        img.src = this.src;
        width = img.width;

        $pic.fadeIn('slow', function () {
            $('#comment-box').width(width);
            $('#comment').html(data.comment);
        });

    }).attr('src', data.newImage);
});

Use the "off-left" technique:

CSS

.off-left {
    position: absolute;
    left: -99999px;
}

JavaScript

$('#picture').fadeOut('slow', function () {
    var $pic = $(this);

    $('#big-picture').one('load', function () {

        var $this = $(this),
            width = $this.addClass('off-left').show().width();

        $this.removeClass('off-left').hide();

        $('#picture').fadeIn('slow', function () {
            $('#comment-box').width(width);
            $('#comment').html(data.comment);
        });

    }).attr('src', data.newImage);
});

Notes

  • When using an ID selector, there's no point in qualifying the selector further, since element IDs must be unique.
  • Pick a quote style and use it consistently. Avoid mixing single- and double-quotes as string delimiters.

Upvotes: 1

Dereleased
Dereleased

Reputation: 10087

You should be able to set the CSS property visibility to hidden and then get the width, as visibility doesn't take it out of the document flow (like display: none), but simply makes it invisible. Just make sure you set the visibility property back to visible when you fade in.

Upvotes: 0

Thomas Shields
Thomas Shields

Reputation: 8942

I've encountered this before; what seems to be the easiest solution is to quickly show the image, grab it's width, and hide it again. This operation occurs so quickly users will never notice. In your case, i believe the code would be:

$("#big-picture").show();
alert($('#big-picture').width()); //this should be the real width, now
$("#big-picture").hide();

Upvotes: 1

Related Questions