Home > Software design >  Scroll to bottom when new message added
Scroll to bottom when new message added

Time:06-16

I am making a chatbot. I want to scroll to the bottom of the chat box when a new input is given by the user or the Data is sent through API.

It doesn't scroll and scroll just stays in the same position but the data is being added in the chat box

I Have tried the code from other chat bot but it didn't work either

var outputArea = $('#chat-output');
$('#user-input-form').on('submit', function (e) {
  e.preventDefault();

  var message = $('#user-input').val();

  outputArea.append(`
    <div class='bot-message'>
      <div class='message'>
        ${message}
      </div>
    </div>
  `);



  const req = https.request(options, (res) => {
    res.setEncoding('utf8');
    res.on('data', (d) => {
      const myobj = JSON.parse(d);
      if ('narrative' in myobj.conversationalResponse.responses[0]) {
        const temp = myobj.conversationalResponse.responses[0].narrative.text;
        outputArea.append(`
      <div class='user-message'>
        <div class='message'>
          ${temp}
        </div>
      </div>
    `);
      } else if ('imageUrl' in myobj.conversationalResponse.responses[0]) {
        const img = myobj.conversationalResponse.responses[0].imageUrl;
        if ('narrative' in myobj.conversationalResponse.responses[1]) {
          const text_r = myobj.conversationalResponse.responses[1].narrative.text;
          outputArea.append(`
      <div class='user-message'>
      <div class ="message">
      ${text_r}
      <a href=""></a>
      </div>
      </div>
    `);
        } else {
          outputArea.append(`
      <div class='user-message'>
        <div class='message'>
         <img src="" width="300" height="200">
        </div>
      </div>
    `);
        }
      }
    });
  });

  req.on('error', (error) => {
    console.error(error);
  });

  req.write(data);
  req.end();

  $('#user-input').val('');
.form-container {
  width: 400px;
  height: 450px;
  padding: 10px;
  background-color: white;
  overflow: scroll;
  position: relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div  id="myForm">
<div >

  <div  id="chat-output">
    <div >
      <div >Hi! I'm Bot, what's up?</div>
    </div>
  </div>
  <div >
    <form action="#0" id="user-input-form" autocomplete="off">
      <input type="text" id="user-input"  placeholder="Talk to the bot.">
    </form>
  </div>
  </br></br>
  <button type="button"  onclick="closeForm()">Close</button>
</div>
</div>

CodePudding user response:

outputArea[0].scrollTop = 9e9; worked for me

CodePudding user response:

You can use scrollTop to achieve it.

I simply wrote an example for your reference, you will find that there are two ways to implement scrollTop, one is to use the animation wrapper, the other is to use it directly, you can compare the difference between the two methods.

const sendMessage = (selector, isAnimate = true) => {
  const text = $(selector).val();
  const $container = $('.form-container');
  $container.append(`<p>${text}</p>`);
  if (isAnimate) {
    $container.animate({
      scrollTop: $container.prop('scrollHeight')
    }, 1000);
  } else {
    $container.scrollTop($container.prop('scrollHeight'));
  }
  $(selector).val('');
};

$('button:eq(0)').on('click', function() {
  sendMessage('input[type=text]');
});

$('button:eq(1)').on('click', function() {
  sendMessage('input[type=text]', false);
});
.form-container {
  width: 400px;
  height: 100px;
  padding: 10px;
  background-color: white;
  overflow: scroll;
  position: relative;
}
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<div class='form-container'>
  <p>This is line 1 of text</p>
  <p>This is line 2 of text</p>
</div>
<div>
  <input type='text' placeholder="Type a message.">
  <button type='button'>Use animation</button>
  <button type='button'>Don't use animation</button>
</div>

CodePudding user response:

Another interesting method is by using pure CSS, using the flex-direction method, which works by creating a wrapper for the content inside the scrolling element.

I've whipped up a quick demo below (with a button and some JavaScript for adding new items).

The trick then lies in reversing the content direction using column-reverse in the scroller. Because the items are in another container, they don't get 'flipped' but instead always line up to the bottom. This, in fact, makes the scroller scrolled to the bottom whenever stuff is added.

Added bonus: keeps scroll position

Also, and this is something I really like about the method; whenever the user has started scrolling (up), the scroller will not lose its scroll position when stuff is being added. So, it will only 'stick' tot the bottom if it was already scrolled (by default, or by the user) to the bottom. This makes sure there's no annoying content jumping, offering a better user experience.

Demo

let scrollerContent = document.getElementById('scrollerContent');

document.getElementById('addItems').addEventListener('click', function() {
  let newChild = scrollerContent.lastElementChild.cloneNode(true);
  newChild.innerHTML = "Item "   (scrollerContent.children.length   1);
  scrollerContent.appendChild(newChild);
});
.scroller {
overflow: auto;
height: 100px;
display: flex;
flex-direction: column-reverse;
}

.scroller .scroller-content .item {
  height: 20px;
}
<div >
  <div  id="scrollerContent">
    <div >Item 1</div>
    <div >Item 2</div>
    <div >Item 3</div>
    <div >Item 4</div>
    <div >Item 5</div>
    <div >Item 6</div>
    <div >Item 7</div>
    <div >Item 8</div>
    <div >Item 9</div>
    <div >Item 10</div>
  </div>
</div>
<br/><br/>
<button id="addItems">Add more items</button>

  • Related