0

I am creating a chatbox. When the user key in a msg, it suppose to appear immediately at the chatbox. The scroll bar should always scroll to bottom of the chatbox. The below codes did work, but when i try to scroll the bar to the top to view previous msg, it will always be dragged back to the bottom. I am not sure is it because of the setInterval. Any idea how to solve this?

$(function(){
     $("#textmsg").keypress(function (e) {
        if (((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) && !e.shiftKey){
            $('.post').click();
            return false;
        } else {
            return true;
        }
    });


    $(document).on('submit','#discussionForm',function(){
        var textmsg = $.trim($("#textmsg").val());
        var name = $.trim($("#name").val());
        if(textmsg != "" && name!=""){
                $.post('inc/postMessages.php',  $("#discussionForm").serialize(), function(data){
                    $(".discussionMessages").html(data);
                });
                $("#textmsg").val('');
        }else{
            alert("Please enter some text!");
        }
    });

    setInterval(function(){
        getMessages();
    },800);
});

function getMessages(){
    $.get('inc/getMessages.php', function(data){
    var message = $(".discussionMessages");
    message.html(data);
    message.scrollTop(message[0].scrollHeight);
    });
}

I have checked on this post, AJAX Chat Box Scrolling Up Issue but I not really sure how to apply to my code.

Community
  • 1
  • 1
user4815740
  • 311
  • 2
  • 8
  • 17

1 Answers1

1

It is crazy inefficient to load the entire conversation every 800 ms - you should definetely make sure only new messages are fetched on each load, or even better switch to websockets or similar. However I don't know your use case, and I won't elaborate on this since that is not the question you are asking.

So to answer your question: What you need to do is only scroll when something new is posted, so simply keep track of and compare the previous content to the new content and only do stuff - including the scroll if they're not equal:

var old_content = '';
function getMessages(){
    $.get('inc/getMessages.php', function(data){
        if (data !== old_content) {
            var message = $(".discussionMessages");
            message.html(data);
            message.scrollTop(message[0].scrollHeight);
            old_content = data;
        }
    });
}

If you don't want it to scroll even when a new message comes in when the user has scrolled away from the bottom you could add a check for that too:

var old_content = '';
function getMessages(){
    $.get('inc/getMessages.php', function(data){
        if (data !== old_content) {
            var message = $(".discussionMessages");
            /* scrollTop gives the position from the top, while
             * scrollheight gives the entire content height - so
             * we need to add the innerHeight (ie. height of the
             * scrollable element) to get the bottom of the current
             * view - you actually ought to subtract the innerHeight
             * from the scroll function itself too, it just doesn't
             * matter as long as the value you pass is larger than
             * the scrollHeight it will hit the bottom...
             */
            var do_scroll = (message.scrollTop() + message.innerHeight() >= message[0].scrollHeight);
            message.html(data);
            if (do_scroll) message.scrollTop(message[0].scrollHeight);
            old_content = data;
        }
    });
}
Mikk3lRo
  • 3,477
  • 17
  • 38