最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I scroll to the bottom of a div as data is added in Meteor? - Stack Overflow

programmeradmin1浏览0评论

I'm writing a messenger application in Meteor, and I want to set it up such that when either user types a message it scrolls down to the bottom of the div for both of them. I am storing the message in a list called messages in a conversation document in the collection Conversations. I am using cursor.observeChanges, and it seems that the callback fires before the data is rendered on the client side so it doesn't scroll all the way to the bottom.

Here is the html:

<template name="chat">  
    {{> chatBox}}
</template>

<template name="chatBox">
    <div class="chat-box">
        <div id="chat-messages">
            {{#each chatMessages}}
                <div class="individual-message">
                    {{message}}
                </div>
            {{/each}}
        </div>
        <form id="chat-input">
            <input class="add-message" autoplete="off" placeholder="Write something..." name="text" type="text">
      </form>
    </div>
</template>

Here's the relevant css:

#chat-messages {
    overflow-y: scroll;
    width: 250px;
    height: 450px;
    padding: 15px;
    position: absolute;
}

And here's the js:

Tracker.autorun(function(){
    ...
    Conversations.find(conversationId).observeChanges({
      changed: function(id, fields){
         $("#chat-messages").scrollTop($("#chat-messages").prop("scrollHeight"));
      }
    });
});

I'm writing a messenger application in Meteor, and I want to set it up such that when either user types a message it scrolls down to the bottom of the div for both of them. I am storing the message in a list called messages in a conversation document in the collection Conversations. I am using cursor.observeChanges, and it seems that the callback fires before the data is rendered on the client side so it doesn't scroll all the way to the bottom.

Here is the html:

<template name="chat">  
    {{> chatBox}}
</template>

<template name="chatBox">
    <div class="chat-box">
        <div id="chat-messages">
            {{#each chatMessages}}
                <div class="individual-message">
                    {{message}}
                </div>
            {{/each}}
        </div>
        <form id="chat-input">
            <input class="add-message" autoplete="off" placeholder="Write something..." name="text" type="text">
      </form>
    </div>
</template>

Here's the relevant css:

#chat-messages {
    overflow-y: scroll;
    width: 250px;
    height: 450px;
    padding: 15px;
    position: absolute;
}

And here's the js:

Tracker.autorun(function(){
    ...
    Conversations.find(conversationId).observeChanges({
      changed: function(id, fields){
         $("#chat-messages").scrollTop($("#chat-messages").prop("scrollHeight"));
      }
    });
});
Share Improve this question asked Jul 15, 2015 at 16:44 David KleimanDavid Kleiman 6277 silver badges15 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

Whenever I run into an issue where Blaze hasn't had a chance to render something in time for a Javascript function to be evoked on it, I use Tracker.afterFlush. This waits until the render cycle is done before running some code, e.g.:

// Inside a Meteor event callback
Tracker.afterFlush(function () {
  var $someItem = $('....');

  $(window).scrollTop($someItem.offset().top);
});

http://docs.meteor./#/full/tracker_afterflush

Different Approach via tracking of Template helpers:

I took advantage of the Template helper, as it already tracks reactively all changes (and new) messages. Hence, there you can place your scroll-down mand.

I assume you have something like this in your JS file:

chatBox.js

Template.chatBox.helpers({
    chatMessages: function() {
       return Conversations.find({conversationId: conversationId},
      {sort: {d: -1}, limit: 20}).fetch().reverse();
    },
});

(Being chatMessages.d the date of posting and conversationId your reactive variable for the specific chat-room, sorted by date from the end, and displayed by reverse order, so that last chat would appear at the end of your chat-messages div, limited to the last 20 messages)

Just add your scroll-down mand there, hence you would have:

Template.chatBox.helpers({
    chatMessages: function() {
       //scroll down not animated
       $('#chat-messages').scrollTop($('#chat-messages').prop('scrollHeight'));
       return Conversations.find({conversationId: conversationId},
      {sort: {d: -1}, limit: 20}).fetch().reverse();
    }
});

Or make it animated for smooth scrolling:

Template.chatBox.helpers({
    chatMessages: function() {
       //scroll down with animation
       $('#chat-messages').animate({scrollTop: $('#chat-messages').prop('scrollHeight')}, 500);
       return Conversations.find({conversationId: conversationId},
      {sort: {d: -1}, limit: 20}).fetch().reverse();
    }
});

This would trigger your "scroll-down" at any change in your Conversations-Collection.

Hope this helps.

发布评论

评论列表(0)

  1. 暂无评论