Use animation frames for scroll detection

This commit is contained in:
Lance Stout 2013-09-26 01:34:13 -07:00
parent 0f2b4b9ec1
commit 1f910f37d7
5 changed files with 22 additions and 10 deletions

View File

@ -2,11 +2,20 @@
"use strict"; "use strict";
var _ = require('underscore'); var _ = require('underscore');
var raf = require('raf-component');
module.exports = { module.exports = {
initializeScroll: function () { initializeScroll: function () {
$(this.$scrollContainer).scroll(_.bind(_.throttle(this.handleScroll, 300), this)); var check = _.bind(this.handleScroll, this);
var self = this;
function animate() {
self.rafID = raf(animate);
check();
}
animate();
this.pinnedToBottom = true; this.pinnedToBottom = true;
this.lastScrollTop = 0; this.lastScrollTop = 0;
}, },
@ -20,6 +29,7 @@ module.exports = {
scrollPageUnload: function () { scrollPageUnload: function () {
this.savePosition(); this.savePosition();
this.trimOldChats(); this.trimOldChats();
raf.cancel(this.rafID);
}, },
savePosition: function () { savePosition: function () {
this.lastScrollPosition = this.pinnedToBottom ? '' : this.$scrollContainer.scrollTop(); this.lastScrollPosition = this.pinnedToBottom ? '' : this.$scrollContainer.scrollTop();
@ -29,7 +39,7 @@ module.exports = {
var removedIds; var removedIds;
if (this.pinnedToBottom) { if (this.pinnedToBottom) {
_.delay(function () { _.delay(function () {
removedIds = self.collection.trimOlderChats(); removedIds = [];//self.collection.trimOlderChats();
removedIds.forEach(function (id) { removedIds.forEach(function (id) {
self.$('#chat' + id).remove(); self.$('#chat' + id).remove();
}); });
@ -38,7 +48,7 @@ module.exports = {
}, },
handleScroll: function (e) { handleScroll: function (e) {
var scrollTop = this.$scrollContainer[0].scrollTop; var scrollTop = this.$scrollContainer[0].scrollTop;
var direction = scrollTop > this.lastScrollTop ? 'down' : 'up'; var direction = scrollTop >= this.lastScrollTop ? 'down' : 'up';
if (direction === 'up' && !this.isBottom()) { if (direction === 'up' && !this.isBottom()) {
this.pinnedToBottom = false; this.pinnedToBottom = false;
} else if (this.isBottom()) { } else if (this.isBottom()) {
@ -52,6 +62,7 @@ module.exports = {
handleAtBottom: function () { handleAtBottom: function () {
if (this.isVisible()) { if (this.isVisible()) {
this.pinnedToBottom = true; this.pinnedToBottom = true;
this.scrollToBottom();
} }
}, },
isBottom: function () { isBottom: function () {
@ -59,7 +70,7 @@ module.exports = {
var scrollHeight = this.$scrollContainer[0].scrollHeight; var scrollHeight = this.$scrollContainer[0].scrollHeight;
var height = this.$scrollContainer.height(); var height = this.$scrollContainer.height();
var fromBottom = scrollHeight - (scrollTop + height); var fromBottom = scrollHeight - (scrollTop + height);
return fromBottom < 40 || $('body').is(':animated'); return fromBottom < 80;
}, },
resizeInput: function () { resizeInput: function () {
var height; var height;

View File

@ -89,7 +89,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
}, },
handleWindowResize: function () { handleWindowResize: function () {
this.scrollIfPinned(); this.scrollIfPinned();
this.$chatInput.trigger('keyup'); this.resizeInput();
}, },
handleKeyDown: function (e) { handleKeyDown: function (e) {
clearTimeout(this.typingTimer); clearTimeout(this.typingTimer);
@ -142,6 +142,8 @@ module.exports = BasePage.extend(chatHelpers).extend({
var message; var message;
var val = this.$chatInput.val(); var val = this.$chatInput.val();
this.scrollToBottom(true);
if (val) { if (val) {
message = { message = {
to: this.model.lockedResource || this.model.jid, to: this.model.lockedResource || this.model.jid,
@ -175,8 +177,6 @@ module.exports = BasePage.extend(chatHelpers).extend({
}, },
refreshModel: function (model) { refreshModel: function (model) {
var existing = this.$('#chat' + model.cid); var existing = this.$('#chat' + model.cid);
console.log(model);
console.log(model.classList);
existing.replaceWith(model.partialTemplateHtml); existing.replaceWith(model.partialTemplateHtml);
}, },
appendModel: function (model, preload) { appendModel: function (model, preload) {

View File

@ -160,7 +160,7 @@ exports.misc.growlMessage = function anonymous(locals) {
exports.pages.chat = function anonymous(locals) { exports.pages.chat = function anonymous(locals) {
var buf = []; var buf = [];
with (locals || {}) { with (locals || {}) {
buf.push('<section class="page chat"><section class="conversation"><header><img class="avatar"/><h1 class="name"></h1><div class="tzo"></div></header><ul class="messages"></ul><div class="chatBox"><form><textarea name="chatInput" type="text" placeholder="Send a message..." autocomplete="off"></textarea></form></div></section></section>'); buf.push('<section class="page chat"><section class="conversation"><header><img class="avatar"/><h1 class="name"></h1><div class="tzo"></div></header><ul class="messages scroll-container"></ul><div class="chatBox"><form><textarea name="chatInput" type="text" placeholder="Send a message..." autocomplete="off"></textarea></form></div></section></section>');
} }
return buf.join(""); return buf.join("");
}; };

View File

@ -4,7 +4,7 @@ section.page.chat
img.avatar img.avatar
h1.name h1.name
.tzo .tzo
ul.messages ul.messages.scroll-container
.chatBox .chatBox
form form
textarea(name='chatInput', type='text', placeholder='Send a message...', autocomplete='off') textarea(name='chatInput', type='text', placeholder='Send a message...', autocomplete='off')

View File

@ -21,7 +21,8 @@
"human-model": "1.1.3", "human-model": "1.1.3",
"human-view": "1.1.2", "human-view": "1.1.2",
"templatizer": "0.1.2", "templatizer": "0.1.2",
"underscore": "1.5.1" "underscore": "1.5.1",
"raf-component": "1.1.1"
}, },
"devDependencies": { "devDependencies": {
"precommit-hook": "0.3.6" "precommit-hook": "0.3.6"