2

I have a chat box where people will beable to add there own message to it but my problem is that when new messages are added it does not scroll down to reveal the new message. I fixed this by using this code

 $('.panel-body').scrollTop($('.panel-body').height()*$('.panel-body').height());

(panel-body is the class of my scrolling div)

But the problem with this is that if a user wants to scroll back up at previous messages he or she will be forced back down to the bottom. What would be the best way to stop "auto scrolling" when the user scrolls but when the user scrolls back down or just loads the page it would start up again.

 function addMsg(is_admin, name, mes, time) {

    var newDiv = document.createElement("div");
    newDiv.className = "row";
    var p = document.createElement("p");
    p.className = "text-muted name";
    var p2 = document.createElement("p");
    var text = document.getElementById("start");
    var hr = document.createElement("hr");
    var times = document.createElement("p")
    text.appendChild(newDiv);
    newDiv.appendChild(p);
    p.innerHTML = name + ":";
    newDiv.appendChild(p2);
    newDiv.appendChild(times)
    times.className = "time";



    if (is_admin) {
        p.style = "color: red;";
        p2.innerHTML = mes;
        times.innerHTML = "time: " + time;


    } else {


        p2.innerHTML = mes;
        times.innerHTML = time;

    }
    newDiv.appendChild(hr);

This is my addMsg Function that i have already created

Jon Uleis
  • 17,693
  • 2
  • 33
  • 42
ThatPurpleGuy
  • 426
  • 7
  • 20

1 Answers1

3

Here's a quick attempt I threw together.

By subtracting the element's height() (jQuery) from its scrollHeight (JS) and comparing that to the user's scrollTop (jQuery scroll position), we can determine if we're currently at the bottom of the scrollable container before the new message appears.

If we are at the bottom, then keep the user down there by setting the new scrollTop. Otherwise, don't change anything. Hope this helps!

Live demonstration:

function newMsg() {
  // FOR DEMO (naming each message)
  var count = $('.msg').length;

  // shouldScroll will be true if we're at the bottom of the
  // scrollable container before the new message appears
  var $panel = $('.panel-body');
  var shouldScroll = $panel[0].scrollHeight - $panel.height() <= $panel.scrollTop(); 

  // this is where you append a new message to the container
  $panel.append('<div class="msg">Message ' + count + '</div>');

  // if we were at the bottom before the new message,
  // then scroll to the new bottom of the container
  if (shouldScroll) {
    $panel.scrollTop($panel[0].scrollHeight);
  }
}

// FOR DEMO (new message every .5 seconds)
setInterval(newMsg, 500);
.panel-body {
  border: 1px solid #000;
  overflow: auto;
  width: 200px;
  height: 200px;
}

.msg {
  border-bottom: 1px solid #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="panel-body"></div>
Jon Uleis
  • 17,693
  • 2
  • 33
  • 42
  • I already have a addmsg function where should i put this to make it work? @JonUleis – ThatPurpleGuy Sep 17 '17 at 23:07
  • @ThatPurpleGuy You haven't shown us your code, so there's no way to answer that - but this was meant to help you see how to implement what you asked for in a minimal and functional example. Are you having trouble understanding any of the code and adapting it? – Jon Uleis Sep 17 '17 at 23:10
  • Oh i thought i added it. My bad added now. Also my question is you are repeating through the function multiple times would i have to do that for it to work in my situation. Sorry, i am more familiar with java than javascript and i am trying to learn. – ThatPurpleGuy Sep 17 '17 at 23:12
  • @ThatPurpleGuy Your function is already occurring every time you get a new message, right? Mine is just on a repeating interval for demonstration purposes so you can see what happens when messages come in. – Jon Uleis Sep 17 '17 at 23:15
  • I created a function without the append or count and i call this function in my add message function but it does not work. I have added what i have done above @JonUleis There are also no errors in console – ThatPurpleGuy Sep 17 '17 at 23:24
  • @ThatPurpleGuy The order of what's happening in my function is essential. While the count variable is irrelevant, the placement of where you're appending new messages is not. Here's a JSFiddle showing how to implement the scroll check into your function: https://jsfiddle.net/9yaq04rL/ – Jon Uleis Sep 17 '17 at 23:32
  • This does not work i think the reason is that shouldscroll is never a true statment. @JonUleis – ThatPurpleGuy Sep 17 '17 at 23:44
  • @ThatPurpleGuy As you've seen here, shouldScroll will evaluate to true under the correct conditions. If you can reproduce your functional code in a JSFiddle I can tell you why it's not working, but otherwise I don't know how to help you any further - this has been a lot of back-and-forth over a very simple task. – Jon Uleis Sep 17 '17 at 23:47
  • @ThatPurpleGuy It looks like it's working perfectly on that link. It's only difficult to tell because every message looks the same (which is why mine were numbered) - but you can see the scrollbar position. – Jon Uleis Sep 18 '17 at 00:00
  • That really od when i do it on a local host it does not work at all. As seen here https://gyazo.com/1c8483072f35c05b5afd37df16bcd6b6 @JonUleis – ThatPurpleGuy Sep 18 '17 at 00:03
  • @ThatPurpleGuy I wish I could debug based off a screen capture, but I'd need to see the problem being reproduced. Not sure why it's working in your JSFiddle but not your local server. – Jon Uleis Sep 18 '17 at 00:08
  • I added a code snippet within the stackoverflow post – ThatPurpleGuy Sep 18 '17 at 00:18
  • @ThatPurpleGuy Thanks, that helped. Turned out the padding inside `.panel-body` wasn't being accounted for: there's 15px on top and bottom throwing off the height calculation math. I reproduced the problem on JSFiddle and by subtracting 30px for padding when doing the math, fixed the issue: https://jsfiddle.net/1u3r82sL/2/ – Jon Uleis Sep 18 '17 at 00:27