mowgli
mowgli

Reputation: 2869

Append content to div and scroll/animate to bottom

I'm trying to make a div scroll to the bottom after adding new content (using append)

Here is the main part:

$('#textdiv').append('<p>Lorem ipsum dolor sit amet, solet nostrud concludaturque no eam. Ne quod recteque pri. Porro nulla zril mei eu. Eu nibh rebum pri, eu est maiorum menandri, ridens tamquam abhorreant te eum. Ipsum definiebas ad mel.</p>');

$('#textdiv').animate({scrollTop: $('#textdiv').height()}, 1000);

See/try it in the fiddle: http://jsfiddle.net/5ucD3/7/

Very buggy.. It does not scroll to the bottom (only maybe at first few appends). When I scroll down and add new content, it scrolls up. Sometimes it does not animate at all.

How do I get it to work always? I figure I have to somehow get the correct height, but don't know how

Upvotes: 31

Views: 51010

Answers (3)

pachanka
pachanka

Reputation: 411

I'm late again, but here's my two cents.

Sometimes when measuring dynamic elements using only one reading can be misguiding because the content being appended might be long, or because the request ($.get, $.post, $.ajax, etc...) for content is still in the air. If the string being appended is coming from a request, then you have to use a callback method to append the response.

The best thing you can do is string it together like this, because javascript "should" resolve the functions synchronous fashion:

$("#textdiv").append('The longest string ever parsed goes here.')
.animate({scrollTop: $('#textdiv').prop("scrollHeight")}, 500);

But you're right, this method tends to be buggy, especially while dealing with divs that mutate fast enough.

That's why if you want to be extra sure that the job gets done, you could use an Interval:

var scroll_to_bottom = function(element){
    var tries = 0, old_height = new_height = element.height();
    var intervalId = setInterval(function() {
        if( old_height != new_height ){    
            // Env loaded
            clearInterval(intervalId);
            element.animate({ scrollTop: new_height }, 'slow');
        }else if(tries >= 30){
            // Give up and scroll anyway
            clearInterval(intervalId);
            element.animate({ scrollTop: new_height }, 'slow');
        }else{
            new_height = content.height();
            tries++;
        }
    }, 100);
}

$('#textdiv').append('The longest string ever parsed goes here.');
scroll_to_bottom($('#textdiv'));

This method cant beat a callback or a simple function line up, but it solves the problem if you don't know exactly when the append is going to end.

Upvotes: 7

mowgli
mowgli

Reputation: 2869

I found a way that works:

$('#textdiv').animate({scrollTop: $('#textdiv').prop("scrollHeight")}, 500);

http://jsfiddle.net/5ucD3/13/

Upvotes: 52

Nikita Shekhov
Nikita Shekhov

Reputation: 503

I have edited and tested your code:

var div = $('#textdiv'),
    height = div.height();

$('#add').on('click', function(){
    div.append('<p>Lorem ipsum dolor sit amet, solet nostrud concludaturque no eam. Ne quod recteque pri. Porro nulla zril mei eu. Eu nibh rebum pri, eu est maiorum menandri, ridens tamquam abhorreant te eum. Ipsum definiebas ad mel.</p>');
    div.animate({scrollTop: height}, 500);
    height += div.height();
});

Try it out live in jsFiddle

Upvotes: 4

Related Questions