3

I have this tiny script:

var $totalHeight;

$(document).ready(function() {
    $totalHeight = $('#sidebar-container').innerHeight();
    $('.sidebar-heading').each(function() {
        $totalHeight = ($totalHeight - $(this).outerHeight());
    });

    $('.sidebar-contents').each(function() { 
        if ($(this).hasClass('active')) {
            $(this).css('height',$totalHeight);
        }
    });

    $('.sidebar-heading').click(function() {
        $('.sidebar-contents').slideUp().removeClass('active').addClass('inactive')/*.css('height','').removeAttr('style')*/;
        $('.sidebar-heading').removeClass('active')/*.next().slideUp()*/;
        $(this).addClass('active').next().addClass('active').removeClass('inactive').css('height',$totalHeight).slideDown();
    });
});

I am pretty sure it's obvious what it is supposed to do.

My problem is: The first click on a ('.sidebar-heading') does not apply the desired $totalHeight to its sibling. The following clicks, it does. What am I doing wrong?

I have a draft-HTML with this code in action. I commented out those parts above to check, where the bug is, but couldn't figure it out anyway.

9
  • Seems to work fine for me. Maybe you do need to be a little more explicit in what you expect it to do and what it is actually doing. Commented Jan 18, 2013 at 17:45
  • Check out this FIDDLE .. the first click doesn't expand the full height.. but every other one does Commented Jan 18, 2013 at 17:47
  • 1
    the content-area should always be at full height. "Inactive" heading elements are supposed to either be at top or at bottom. not in between. With the first click, the following heading-elements are somewhere in the middle, not at the bottom of the container. Commented Jan 18, 2013 at 17:47
  • Any reason to name an integer variable $totalHeight? This is not PHP Commented Jan 18, 2013 at 17:49
  • I'm unable to reproduce this behavior using Chrome (v24). What browser are you seeing this behavior in? Commented Jan 18, 2013 at 17:50

2 Answers 2

3

The slideUp() animation takes a while to run and cleans up all the heights and display styles after it gets done. This erases the setting you made in the next two lines.

Try waiting until slideUp() is done to do the other ones.

   $('.sidebar-heading').click(function() {
        var self = this;
        $('.sidebar-contents').slideUp(undefined, function() {
            $('.sidebar-heading').removeClass('active')/*.next().slideUp()*/;
            $(self).addClass('active')
                .next().addClass('active').removeClass('inactive')
                .css('height',$totalHeight).slideDown();
        }).removeClass('active').addClass('inactive')
        /*.css('height','').removeAttr('style')*/;
    });

I figured this out by running in Chrome with the debugger and noticing that the styles were changing in a wierd way. The first click on the 2nd heading would leave the height set on the 1st heading even though the code was clearing it. That means something was, maybe, setting it wrong. So I tried the above code on the jsFiddle someone set up. Lo and behold ...

Sign up to request clarification or add additional context in comments.

8 Comments

Probably copied something wrong from the fiddle. Too many lines copied. Ill fix it.
I guess I was just confused by the lack of indentation. FTFY.
Can you provide the fixed fiddle? I would like to see your fix live.
Oh. The first animation was removing the height. I was trying to catch the second one red-handed.
Fixed fiddle showing the code change and thanks @JanDvorak for the reformatting.
|
2

You can also let the fx function set the height by itself to avoid conflict mentioned in @LeeMeador's answer.

Since the slideDown() doesn't accept any css value, we can use the animate() function directly instead.

$('.sidebar-heading').click(function () {
    $('.sidebar-heading').removeClass('active');
    $('.sidebar-contents').removeClass('active').addClass('inactive').stop().animate({ height: '0px' });
    $(this).addClass('active').next().addClass('active').removeClass('inactive').stop().animate({ height: $totalHeight + 'px' });
});

In addition, use stop() before perform any animation to prevent weird behavior if you click the heading again while the previous animation haven't finished.

Modified jsfiddle: http://jsfiddle.net/z62tr/4/

1 Comment

I also thought about an approach using animate(). Thanks for this solution. On the first glance, it works for me :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.