Use Fritzy's StayDown lib. ^5

This commit is contained in:
Lance Stout 2014-01-01 12:34:38 -08:00
parent e68856929f
commit a61ef801bb
7 changed files with 64 additions and 167 deletions

View File

@ -1,108 +0,0 @@
/*global app, $*/
"use strict";
var _ = require('underscore');
module.exports = {
initializeScroll: function () {
var self = this;
this.pinnedToBottom = true;
this.lastScrollTop = 0;
this.$scrollContainer.on('scroll', this.handleScroll.bind(this));
},
scrollPageLoad: function () {
if (typeof this.lastScrollPosition === 'number') {
this.scrollTo(this.lastScrollPosition);
} else {
this.scrollToBottom();
}
},
scrollPageUnload: function () {
this.savePosition();
this.trimOldChats();
},
savePosition: function () {
this.lastScrollPosition = this.pinnedToBottom ? '' : this.$scrollContainer.scrollTop();
},
trimOldChats: function () {
var self = this;
var removedIds;
if (this.pinnedToBottom) {
_.delay(function () {
removedIds = [];//self.collection.trimOlderChats();
removedIds.forEach(function (id) {
self.$('#chat' + id).remove();
});
}, 500);
}
},
handleScroll: _.debounce(function (e) {
var scrollTop = this.$scrollContainer[0].scrollTop;
var direction = scrollTop >= this.lastScrollTop ? 'down' : 'up';
if (direction === 'up' && !this.isBottom()) {
this.pinnedToBottom = false;
} else if (this.isBottom()) {
this.handleAtBottom();
}
this.lastScrollTop = scrollTop;
}, 500),
scrollIfPinned: function (animate) {
if (this.pinnedToBottom) this.scrollToBottom(animate);
},
handleAtBottom: function () {
if (this.isVisible()) {
this.pinnedToBottom = true;
}
},
isBottom: function () {
var scrollTop = this.$scrollContainer[0].scrollTop;
var scrollHeight = this.$scrollContainer[0].scrollHeight;
var height = this.$scrollContainer.height();
var fromBottom = scrollHeight - (scrollTop + height);
return fromBottom < 80;
},
resizeInput: function () {
var height;
var scrollHeight;
var newHeight;
var newPadding;
var paddingDelta;
var maxHeight = 102;
this.$chatInput.removeAttr('style');
height = this.$chatInput.height() + 10,
scrollHeight = this.$chatInput.get(0).scrollHeight,
newHeight = scrollHeight + 2;
if (newHeight > maxHeight) newHeight = maxHeight;
if (newHeight > height) {
this.$chatInput.css('height', newHeight);
newPadding = newHeight + 21;
paddingDelta = newPadding - parseInt(this.$messageList.css('paddingBottom'), 10);
if (!!paddingDelta) {
this.$messageList.css('paddingBottom', newPadding);
}
}
},
scrollTo: function (height, animate) {
if (animate) {
this.$scrollContainer.animate({
scrollTop: height
}, {
duration: 500,
queue: false
});
} else {
this.$scrollContainer[0].scrollTop = height;
}
},
scrollToBottom: function (animate) {
if (!this.isVisible()) return;
var height = this.$scrollContainer[0].scrollHeight;
this.scrollTo(height, animate);
},
isVisible: function () {
return app.currentPage === this;
}
};

View File

@ -2,15 +2,15 @@
"use strict";
var _ = require('underscore');
var StayDown = require('staydown');
var BasePage = require('./base');
var templates = require('../templates');
var Message = require('../views/message');
var MessageModel = require('../models/message');
var chatHelpers = require('../helpers/chatHelpers');
var attachMediaStream = require('attachmediastream');
module.exports = BasePage.extend(chatHelpers).extend({
module.exports = BasePage.extend({
template: templates.pages.chat,
initialize: function (spec) {
this.editMode = false;
@ -61,6 +61,8 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
render: function () {
if (this.rendered) return this;
var self = this;
this.rendered = true;
this.renderAndBind();
@ -68,16 +70,14 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.$chatInput = this.$('.chatBox textarea');
this.$chatBox = this.$('.chatBox');
this.$messageList = this.$('.messages');
this.$scrollContainer = this.$messageList;
this.staydown = new StayDown(this.$messageList[0], 500);
this.renderCollection();
this.listenTo(this.model.messages, 'add', this.handleChatAdded);
this.listenToAndRun(this.model, 'change:jingleResources', this.handleJingleResourcesChanged);
this.renderCollection();
$(window).on('resize', _.bind(this.handleWindowResize, this));
this.initializeScroll();
$(window).on('resize', _.bind(this.resizeInput, this));
this.registerBindings(me, {
srcBindings: {
@ -88,11 +88,8 @@ module.exports = BasePage.extend(chatHelpers).extend({
return this;
},
handlePageLoaded: function () {
this.scrollPageLoad();
this.handleWindowResize();
},
handlePageUnloaded: function () {
this.scrollPageUnload();
this.staydown.checkdown();
this.resizeInput();
},
handleCallClick: function (e) {
e.preventDefault();
@ -101,17 +98,11 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
renderCollection: function () {
var self = this;
var previous;
var bottom = this.isBottom() || this.$messageList.is(':empty');
this.model.messages.each(function (model, i) {
self.appendModel(model);
});
this.scrollIfPinned();
this.staydown.checkdown();
},
handleWindowResize: _.debounce(function () {
this.scrollIfPinned();
this.resizeInput();
}),
handleKeyDown: function (e) {
if (e.which === 13 && !e.shiftKey) {
this.sendChat();
@ -166,9 +157,9 @@ module.exports = BasePage.extend(chatHelpers).extend({
var message;
var val = this.$chatInput.val();
this.scrollToBottom(true);
if (val) {
this.staydown.intend_down = true;
message = {
to: this.model.lockedResource || this.model.jid,
type: 'chat',
@ -221,11 +212,9 @@ module.exports = BasePage.extend(chatHelpers).extend({
last.addClass('chatGroup');
} else {
newEl = $(model.templateHtml);
this.$messageList.append(newEl);
this.staydown.append(newEl[0]);
}
this.lastModel = model;
this.scrollIfPinned();
},
handleEndClick: function (e) {
e.preventDefault();
@ -236,5 +225,28 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
handleMuteClick: function (e) {
return false;
}
},
resizeInput: _.throttle(function () {
var height;
var scrollHeight;
var newHeight;
var newPadding;
var paddingDelta;
var maxHeight = 102;
this.$chatInput.removeAttr('style');
height = this.$chatInput.height() + 10;
scrollHeight = this.$chatInput.get(0).scrollHeight;
newHeight = scrollHeight + 2;
if (newHeight > maxHeight) newHeight = maxHeight;
if (newHeight > height) {
this.$chatInput.css('height', newHeight);
newPadding = newHeight + 21;
paddingDelta = newPadding - parseInt(this.$messageList.css('paddingBottom'), 10);
if (!!paddingDelta) {
this.$messageList.css('paddingBottom', newPadding);
}
}
}, 300)
});

View File

@ -2,15 +2,15 @@
"use strict";
var _ = require('underscore');
var StayDown = require('staydown');
var BasePage = require('./base');
var templates = require('../templates');
var MUCRosterItem = require('../views/mucRosterItem');
var Message = require('../views/mucMessage');
var MessageModel = require('../models/message');
var chatHelpers = require('../helpers/chatHelpers');
module.exports = BasePage.extend(chatHelpers).extend({
module.exports = BasePage.extend({
template: templates.pages.groupchat,
initialize: function (spec) {
this.editMode = false;
@ -59,16 +59,15 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.$chatInput = this.$('.chatBox textarea');
this.$chatBox = this.$('.chatBox');
this.$messageList = this.$('.messages');
this.$scrollContainer = this.$messageList;
this.listenTo(this.model.messages, 'add', this.handleChatAdded);
this.staydown = new StayDown(this.$messageList[0], 500);
this.renderMessages();
this.renderCollection(this.model.resources, MUCRosterItem, this.$('.groupRoster'));
$(window).on('resize', _.bind(this.handleWindowResize, this));
this.listenTo(this.model.messages, 'add', this.handleChatAdded);
this.initializeScroll();
$(window).on('resize', _.bind(this.resizeInput, this));
this.registerBindings();
@ -76,25 +75,16 @@ module.exports = BasePage.extend(chatHelpers).extend({
},
renderMessages: function () {
var self = this;
var previous;
var bottom = this.isBottom() || this.$messageList.is(':empty');
this.model.messages.each(function (model, i) {
self.appendModel(model);
});
this.scrollIfPinned();
this.staydown.checkdown();
},
handleChatAdded: function (model) {
this.appendModel(model, true);
},
handlePageLoaded: function () {
this.scrollPageLoad();
this.handleWindowResize();
},
handlePageUnloaded: function () {
this.scrollPageUnload();
},
handleWindowResize: function () {
this.scrollIfPinned();
this.staydown.checkdown();
this.resizeInput();
},
handleKeyDown: function (e) {
@ -139,7 +129,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.pausedTyping();
}
},
resizeInput: function () {
resizeInput: _.throttle(function () {
var height;
var scrollHeight;
var newHeight;
@ -161,7 +151,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.$messageList.css('paddingBottom', newPadding);
}
}
},
}, 300),
pausedTyping: _.debounce(function () {
if (this.typing && !this.paused) {
this.paused = true;
@ -177,6 +167,8 @@ module.exports = BasePage.extend(chatHelpers).extend({
var val = this.$chatInput.val();
if (val) {
this.staydown.intend_down = true;
message = {
to: this.model.jid,
type: 'groupchat',
@ -223,11 +215,9 @@ module.exports = BasePage.extend(chatHelpers).extend({
last.addClass('chatGroup');
} else {
newEl = $(model.templateHtml);
this.$messageList.append(newEl);
this.staydown.append(newEl[0]);
}
this.lastModel = model;
this.scrollIfPinned();
},
refreshModel: function (model) {
var existing = this.$('#chat' + model.cid);

View File

@ -7,7 +7,7 @@
"url": "git@github.com:andyet/otalk.git"
},
"dependencies": {
"bows": "",
"bows": "0.3.0",
"async": "0.2.9",
"backbone": "1.0.0",
"express": "3.3.7",
@ -28,7 +28,8 @@
"attachmediastream": "1.0.1",
"getusermedia": "0.2.1",
"crypto-browserify": "1.0.3",
"browserify": "2.25.1"
"browserify": "2.25.1",
"staydown": "1.0.2"
},
"devDependencies": {
"precommit-hook": "0.3.6"

View File

@ -1211,11 +1211,15 @@ button.secondary:hover:not(:disabled) {
right: 0px;
left: 201px;
z-index: 200;
transition: none;
-webkit-transition: none;
}
.chatBox form {
border-top: 1px solid #eee;
background: #f7f7f7;
padding: 11px;
transition: none;
-webkit-transition: none;
}
.chatBox .formwrap {
-moz-box-sizing: border-box;
@ -1228,9 +1232,6 @@ button.secondary:hover:not(:disabled) {
.chatBox textarea {
height: 30px;
padding: 6px 10px;
}
.chatBox textarea.typing:focus,
.chatBox textarea.editing:focus {
transition: none;
-webkit-transition: none;
}

View File

@ -316,11 +316,15 @@
right: 0px
left: 201px
z-index: 200
transition: none
-webkit-transition: none
form
border-top: 1px solid #eee
background: lighten($gray-light, 93%)
padding: 11px
transition: none
-webkit-transition: none
.formwrap
borderbox()
@ -331,11 +335,8 @@
textarea
height: 30px
padding: 6px 10px
&.typing:focus,
&.editing:focus
transition: none
-webkit-transition: none
transition: none
-webkit-transition: none
&.editing
background-color: #fffcea

View File

@ -1,5 +1,5 @@
CACHE MANIFEST
# 0.0.1 1388604898350
# 0.0.1 1388608474826
CACHE:
/app.js