Adam Výborný
Adam Výborný

Reputation: 731

Automatically scroll down chat div

I have this code, to load chat

function getMessages(letter) {
  var div = $('#messages');
  $.get('msg_show.php', function (data) {
    div.html(data);
  });
}

setInterval(getMessages, 100);

What I have to add, to automatically scroll down #messages div on page load, and again with every new chat post?

This doesn't work:

function getMessages(letter) {
  var div = $('#messages');
  $.get('msg_show.php', function (data) {
    div.html(data);
    $('#messages').scrollTop($('#messages')[0].scrollHeight);
  });
}

setInterval(getMessages, 100);

Upvotes: 45

Views: 163472

Answers (17)

Phfoxer
Phfoxer

Reputation: 1

You can resolve easily using only css.

.chat-messages { display: flex; flex-direction: column-reverse; }

Now u need to reverse the chat order and works.

Try, See this gits

Upvotes: 0

flaviut
flaviut

Reputation: 2143

You can do this with CSS using overflow-anchor: https://caniuse.com/css-overflow-anchor

const scroller = document.getElementById('scroller')
const anchor = document.getElementById('anchor')
let i = 0;
setInterval(() => {
  const p = document.createElement("p")
  p.textContent = `Message ${i++}`
  scroller.insertBefore(p, anchor)
}, 1000)
#scroller {
  /* begin example styling */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* end example styling */
}
#scroller * {
  /* don't allow the children of the scrollable element to be selected as an anchor node */
  overflow-anchor: none;
}

#anchor {
  /* allow the final child to be selected as an anchor node */
  overflow-anchor: auto;
  /* anchor nodes are required to have non-zero area */
  height: 1px;
  /* begin example styling */
  align-self: stretch;
  /* end example styling */
}
<div id="scroller">
  <!-- append content here -->
  <div id="anchor"></div>
</div>

Note that to activate this, the user must first scroll to the bottom of the page. You can work around this by using javascript to trigger an initial scroll as soon as it is possible.

Upvotes: -1

Martinez
Martinez

Reputation: 450

Supports new messages and sets scrolling down automatically is similar to Twitch chat

function Chat() {
    const [messages, setMessages] = useState<string[]>([])
    const container = useRef<HTMLDivElement>(null)

    const autoScroll = () => {
        const { offsetHeight, scrollHeight, scrollTop } = container.current as HTMLDivElement
        if (scrollHeight <= scrollTop + offsetHeight + 100) {
            container.current?.scrollTo(0, scrollHeight)
        }
    }

    useEffect(() => {
        autoScroll()
    }, [messages])

    return (
        <div ref={container}>
            // messages
        </div>
    )
}

Upvotes: 0

Ronald Jimenez
Ronald Jimenez

Reputation: 11

Simple solution:

1 - Place in the bottom of your message (Inside)

<a href="#" class="d-none" id="focus-bottom"></a>

2 - When new message is received:

function getMessages (letter) {
  var div = $('#messages');
  $.get('msg_show.php', function(data){
    div.html(data);
    $('#focus-bottom').focus();
    $('#focus-box-message').focus(); / * FOCUS YOUR TEXTAREA * /
  });
}

setInterval(getMessages, 100);

Upvotes: 1

ANOL GHOSH
ANOL GHOSH

Reputation: 1

Use This

function getMessages(letter) {
  var div = $('#messages');
  $.get('msg_show.php', function (data) {
    div.html(data).animate({scrollTop: div.prop("scrollHeight")});
    //use append() if msg_show.php returns single unread msg.
  });
}

setInterval(getMessages, 100);

Upvotes: 0

Jean Leon
Jean Leon

Reputation: 2023

I prefer to use Vanilla JS

let chatWrapper = document.querySelector('#chat-messages');
chatWrapper.scrollTo(0, chatWrapper.offsetHeight );

where element.scrollTo(x-coord, y-coord)

Upvotes: 0

Saif Ali
Saif Ali

Reputation: 11

const messages = document.getElementById('messages');

function appendMessage() {
	const message = document.getElementsByClassName('message')[0];
  const newMessage = message.cloneNode(true);
  messages.appendChild(newMessage);
}

function getMessages() {
	// Prior to getting your messages.
  shouldScroll = messages.scrollTop + messages.clientHeight === messages.scrollHeight;
  /*
   * Get your messages, we'll just simulate it by appending a new one syncronously.
   */
  appendMessage();
  // After getting your messages.
  if (!shouldScroll) {
    scrollToBottom();
  }
}

function scrollToBottom() {
  messages.scrollTop = messages.scrollHeight;
}

scrollToBottom();

setInterval(getMessages, 100);
#messages {
  height: 200px;
  overflow-y: auto;
}
<div id="messages">
  <div class="message">
    Hello world
  </div>
</div>

Upvotes: 1

Bhagyesh Patel
Bhagyesh Patel

Reputation: 21

to scroll till particular element from the message box top checkout the following demo:

https://jsfiddle.net/6smajv0t/

function scrollToBottom(){
	const messages = document.getElementById('messages');
	const messagesid = document.getElementById('messagesid');  
	messages.scrollTop = messagesid.offsetTop - 10;
}

scrollToBottom();
setInterval(scrollToBottom, 1000);
#messages {
  height: 200px;
  overflow-y: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="messages">
  <div class="message">
    Hello world1
  </div>
  <div class="message">
    Hello world2
  </div>
  <div class="message">
    Hello world3
  </div>
  <div class="message">
    Hello world4
  </div>
  <div class="message">
    Hello world5
  </div>
  <div class="message">
    Hello world7
  </div>
  <div class="message">
    Hello world8
  </div>
  <div class="message">
    Hello world9
  </div>
  <div class="message" >
    Hello world10
  </div>
  <div class="message">
    Hello world11
  </div>
  <div class="message">
    Hello world12
  </div>
  <div class="message">
    Hello world13
  </div>
  <div class="message">
    Hello world14
  </div>
  <div class="message">
    Hello world15
  </div>
  <div class="message" id="messagesid">
    Hello world16 here
  </div>
  <div class="message">
    Hello world17
  </div>
  <div class="message">
    Hello world18
  </div>
  <div class="message">
    Hello world19
  </div>
  <div class="message">
    Hello world20
  </div>
  <div class="message">
    Hello world21
  </div>
  <div class="message">
    Hello world22
  </div>
  <div class="message">
    Hello world23
  </div>
  <div class="message">
    Hello world24
  </div>
  <div class="message">
    Hello world25
  </div>
  <div class="message">
    Hello world26
  </div>
  <div class="message">
    Hello world27
  </div>
  <div class="message">
    Hello world28
  </div>
  <div class="message">
    Hello world29
  </div>
  <div class="message">
    Hello world30
  </div>
</div>

Upvotes: 2

zurfyx
zurfyx

Reputation: 32757

Let's review a few useful concepts about scrolling first:

When should you scroll?

  • User has loaded messages for the first time.
  • New messages have arrived and you are at the bottom of the scroll (you don't want to force scroll when the user is scrolling up to read previous messages).

Programmatically that is:

if (firstTime) {
  container.scrollTop = container.scrollHeight;
  firstTime = false;
} else if (container.scrollTop + container.clientHeight === container.scrollHeight) {
  container.scrollTop = container.scrollHeight;
}

Full chat simulator (with JavaScript):

https://jsfiddle.net/apvtL9xa/

const messages = document.getElementById('messages');

function appendMessage() {
	const message = document.getElementsByClassName('message')[0];
  const newMessage = message.cloneNode(true);
  messages.appendChild(newMessage);
}

function getMessages() {
	// Prior to getting your messages.
  shouldScroll = messages.scrollTop + messages.clientHeight === messages.scrollHeight;
  /*
   * Get your messages, we'll just simulate it by appending a new one syncronously.
   */
  appendMessage();
  // After getting your messages.
  if (!shouldScroll) {
    scrollToBottom();
  }
}

function scrollToBottom() {
  messages.scrollTop = messages.scrollHeight;
}

scrollToBottom();

setInterval(getMessages, 100);
#messages {
  height: 200px;
  overflow-y: auto;
}
<div id="messages">
  <div class="message">
    Hello world
  </div>
</div>

Upvotes: 69

Gaurav Saini
Gaurav Saini

Reputation: 21

As I am not master in js but I myself write code which check if user is at bottom. If user is at bottom then chat page will automatically scroll with new message. and if user scroll up then page will not auto scroll to bottom..

JS code -

var checkbottom;
jQuery(function($) {
$('.chat_screen').on('scroll', function() {
    var check = $(this).scrollTop() + $(this).innerHeight() >= $(this) 
[0].scrollHeight;
    if(check) {
       checkbottom = "bottom";
    }
    else {
    checkbottom = "nobottom";
    }
})
});
window.setInterval(function(){
if (checkbottom=="bottom") {
var objDiv = document.getElementById("chat_con");
objDiv.scrollTop = objDiv.scrollHeight;
}
}, 500);

html code -

<div id="chat_con" class="chat_screen">
</div>

Upvotes: 0

Sayed Khan Prince
Sayed Khan Prince

Reputation: 31

if you just scrollheight it will make a problem when user will want to see his previous message. so you need to make something that when new message come only then the code. use jquery latest version. 1.here I checked the height before message loaded. 2. again check the new height. 3. if the height is different only that time it will scroll otherwise it will not scroll. 4. not in the if condition you can put any ringtone or any other feature that you need. that will play when new message will come. thanks

var oldscrollHeight = $("#messages").prop("scrollHeight");
$.get('msg_show.php', function(data) {
    div.html(data);
    var newscrollHeight = $("#messages").prop("scrollHeight"); //Scroll height after the request
    if (newscrollHeight > oldscrollHeight) {
        $("#messages").animate({
            scrollTop: newscrollHeight
        }, 'normal'); //Autoscroll to bottom of div
    }

Upvotes: 2

Govan
Govan

Reputation: 1379

after append in JQuery,just add this line

<script>
    $("#messages").animate({ scrollTop: 20000000 }, "slow");
</script>

Upvotes: 9

user7151151
user7151151

Reputation:

    var l = document.getElementsByClassName("chatMessages").length;
    document.getElementsByClassName("chatMessages")[l-1].scrollIntoView();

this should work

Upvotes: 0

aravk33
aravk33

Reputation: 489

I found out this very simple method while experimenting: set the scrollTo to the height of the div.

var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);

Upvotes: 1

aqez
aqez

Reputation: 315

What you need to do is divide it into two divs. One with overflow set to scroll, and an inner one to hold the text so you can get it's outersize.

<div id="chatdiv">
    <div id="textdiv"/>
</div>

textdiv.html("");
$.each(chatMessages, function (i, e) {
    textdiv.append("<span>" + e + "</span><br/>");
});
chatdiv.scrollTop(textdiv.outerHeight());

You can check out a jsfiddle here: http://jsfiddle.net/xj5c3jcn/1/

Obviously you don't want to rebuild the whole text div each time, so take that with a grain of salt - just an example.

Upvotes: 1

UweB
UweB

Reputation: 4110

It's hard to tell without knowing the HTML code, but I'd assume your div doesn't have a height set and/or doesn't allow overflow (e.g. through CSS height: 200px; overflow: auto).

I've made a working sample on jsfiddle: http://jsfiddle.net/hu4zqq4x/

I created some dummy HTML markup inside a div that is a) overflowing and b) has a set height. Scrolling is done through calling the function

function getMessages(letter) {
    var div = $("#messages");
    div.scrollTop(div.prop('scrollHeight'));
}

, in this case once on 'documentReady'.

prop('scrollHeight') will access the value of the property on the first element in the set of matched elements.

Upvotes: 15

Anoop Joshi P
Anoop Joshi P

Reputation: 25527

Dont have to mix jquery and javascript. Use like this,

function getMessages(letter) {
    var message=$('#messages');
    $.get('msg_show.php', function(data) {
        message.html(data);
        message.scrollTop(message[0].scrollHeight);
    });
}

setInterval(function() {
    getMessages("letter");
}, 100)

Put the scrollTop() inside get() method.

Also you missed a parameter in the getMessage method call..

Upvotes: 0

Related Questions