2

I'm think I'm going mad.

All I want to do is get the dimensions of data loaded via AJAX regardless of how many times the call is made. It works fine the first time, but I always get a value of 0 with each subsequent call - despite the fact that it appears on the page, as one would expect.

// The AJAX part
function getDetails(request){
    $placehold.empty();
    return jQ.get(request);
};

// Filter & render AJAX data
function renderData(data){
    var endResult = $(data).find('#productDetails');
    endResult.fadeTo(0,0).appendTo($placehold);
    $placehold.removeClass('loading');
    endResult.fadeTo(300,1); // <- Added as per request
    // Console log previously uncalled data works fine
    // Called again, I get zero every single time
    console.log( jQ('#anyElementInAJAXData').outerHeight(false) );
};

// Click handler
jQ('#slides').on('click', '.slideLink', function(e){
    e.preventDefault();
    var target = jQ(this).attr("href");
    $placehold.fadeIn(360).addClass('loading');
    getDetails(target)
        .done( function(result) {
            renderData(result);
        })
});

What am I doing wrong?

verism
  • 1,106
  • 1
  • 12
  • 35
  • 1
    What's the result of `console.log(jQ('#anyElementInAJAXData').length)` in subsequent calls? – Matt Apr 18 '13 at 17:50
  • Why are you fading out the `endResult` but never making it appear again? – m90 Apr 18 '13 at 17:52
  • @Matt it returns "1" every time – verism Apr 18 '13 at 17:53
  • @m90 I actually do make it appear after some conditional stuff - but I wanted to keep the question as succinct as possible. – verism Apr 18 '13 at 17:54
  • Could you add that part too? Your code looks like it should be working so it might be that there is something wrong going on in there. Maybe your fadeIn is async and therefore the outerHeight is taken when the element is still hidden. – m90 Apr 18 '13 at 18:02
  • @m90 - I've edited as requested. I'm still getting the same results though. What I'm tying to do is get the dimensions before the data is displayed, so I can apply some conditional CSS and then fade in. – verism Apr 18 '13 at 18:09
  • But you won't be able to get the dimensions of children of an element that is set to `display: none;` : http://jsfiddle.net/urcnc/1/ You'll either have to fake the `display: none;` using `opacity` or wait for your element to fade in. – m90 Apr 18 '13 at 18:18
  • @m90 Yes, you're right up to a point, but `fadeTo(0,0)` gives it an opacity of 0, rather than a display of none, so it can be measured. The fact I can read the height on the first AJAX call proves this. http://jsfiddle.net/urcnc/2/ – verism Apr 18 '13 at 18:21

1 Answers1

0

Your problem seems to lie in the endResult.fadeTo(0,0).appendTo($placehold); method. The appendTo will only occur after the fadeTo is complete, but the rest of your method is executed while the fadeTo has just started. This 'might' solve it:

var endResult = $(data).find('#productDetails');
endResult.fadeTo(0,0, function() {
  $(this).appendTo($placehold);
  $placehold.removeClass('loading');
  $(this).fadeTo(300,1); // <- Added as per request
  // Console log previously uncalled data works fine
  // Called again, I get zero every single time
  console.log( jQ('#anyElementInAJAXData').outerHeight(false) );
});
Toverbal
  • 256
  • 3
  • 14
  • Thanks for your suggestion, but this isn't the issue. The `append()` method is synchronous - meaning it finishes before any following code is executed. All I'm doing is making sure `endResult` has an opacity of 0 before inserting it. Then once it's hidden, (theoretically) measurable and in the right place, the rest executes. – verism Apr 18 '13 at 21:37
  • The append method is certainly not synchronous (it will be executed after the fadeTo, but the code after that chain will be executed directly after the fadeTo has initiated). It can, however, look synchronous, because you use a duration of 0. Check out this fiddle to see what I mean: http://jsfiddle.net/UM4Ed/ (it uses console log and you see 'check 1' and after one second 'check 2'). The fiddle does show the correct height though, but... Maybe you should change the line `endResult.fadeTo(0.0).appendTo(...)` to `endResult.css({opacity: 0}).appendTo(...)`. That way it will be synchronous. – Toverbal Apr 19 '13 at 05:59
  • ...also, height seems to be only correct when the element is (slightly) visible, maybe change the opacity value to 0.1 will help. I am convinced the problem is something like this. – Toverbal Apr 19 '13 at 06:02
  • Everything else I've read - posts like [this](http://stackoverflow.com/questions/5085228/does-jquery-append-behave-asynchronously) for example - indicates `append()` is synchronous. Perhaps I misunderstand what you're saying - if so, can you clarify? I also thought that the element might need to be slightly opaque too, but it had no affect whatsoever; which correlates with what the docs say... `display:none` means you can't measure, whereas `visibility:hidden` or `opacity:0` (which is what `fadeTo(0,0)` and/or `css({'opacity':'0'})` yield) means you can. – verism Apr 19 '13 at 12:01
  • You are right about the opacity and display properties, I can't say what is causing your problem, though I still think it has something to do with the execution of the code. The append *IS* synchronous, but the fadeTo is not, so although you add appendTo after the fadeTo, it still is only executed AFTER the fade is done, as my fiddle demonstrates. – Toverbal Apr 19 '13 at 20:08