refactored stream and Stream View

streamView no longer abuses render with fetching
moved post collapsing into contentView
subtle nicification.
This commit is contained in:
danielgrippi 2012-04-17 21:05:01 -07:00
parent 27513cf319
commit 3479cb7bdd
7 changed files with 68 additions and 75 deletions

View file

@ -16,7 +16,7 @@ app.models.Stream = Backbone.Collection.extend({
}, },
fetch: function() { fetch: function() {
if(this.deferred && !this.deferred.isResolved()){ return false } if(this.isFetching()){ return false }
var url = this.url() var url = this.url()
this.deferred = this.posts.fetch({ this.deferred = this.posts.fetch({
add : true, add : true,
@ -24,6 +24,10 @@ app.models.Stream = Backbone.Collection.extend({
}).done(_.bind(this.triggerFetchedEvents, this)) }).done(_.bind(this.triggerFetchedEvents, this))
}, },
isFetching : function(){
return this.deferred && this.deferred.state() == "pending"
},
triggerFetchedEvents : function(resp){ triggerFetchedEvents : function(resp){
this.trigger("fetched", this); this.trigger("fetched", this);
// all loaded? // all loaded?

View file

@ -26,6 +26,7 @@ app.Router = Backbone.Router.extend({
stream : function() { stream : function() {
app.stream = new app.models.Stream(); app.stream = new app.models.Stream();
app.stream.fetch();
app.page = new app.views.Stream({model : app.stream}); app.page = new app.views.Stream({model : app.stream});
app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.posts}); app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.posts});

View file

@ -40,8 +40,10 @@ app.views.Base = Backbone.View.extend({
renderTemplate : function(){ renderTemplate : function(){
var presenter = _.isFunction(this.presenter) ? this.presenter() : this.presenter var presenter = _.isFunction(this.presenter) ? this.presenter() : this.presenter
this.template = JST[this.templateName] this.template = JST[this.templateName]
if(!this.template) {console.log("no template for " + this.templateName) } if(!this.template) {
$(this.el) console.log(this.templateName ? ("no template for " + this.templateName) : "no templateName specified")
}
this.$el
.html(this.template(presenter)) .html(this.template(presenter))
.attr("data-template", _.last(this.templateName.split("/"))); .attr("data-template", _.last(this.templateName.split("/")));
this.postRenderTemplate(); this.postRenderTemplate();

View file

@ -52,8 +52,35 @@ app.views.Content = app.views.StreamObject.extend({
el.css('height','auto'); el.css('height','auto');
}); });
$(evt.currentTarget).hide(); $(evt.currentTarget).hide();
} },
collapseOversized : function() {
var collHeight = 200
, elem = this.$(".collapsible")
, oembed = elem.find(".oembed")
, addHeight = 0;
if($.trim(oembed.html()) != "") {
addHeight = oembed.height();
}
// only collapse if height exceeds collHeight+20%
if( elem.height() > ((collHeight*1.2)+addHeight) && !elem.is(".opened") ) {
elem.data("orig-height", elem.height() );
elem
.height( Math.max(collHeight, addHeight) )
.addClass("collapsed")
.append(
$('<div />')
.addClass('expander')
.text( Diaspora.I18n.t("show_more") )
);
}
},
postRenderTemplate : function(){
_.defer(_.bind(this.collapseOversized, this))
}
}); });
app.views.StatusMessage = app.views.Content.extend({ app.views.StatusMessage = app.views.Content.extend({

View file

@ -25,12 +25,12 @@ app.views.StreamPost = app.views.Post.extend({
this.model.bind('remove', this.remove, this); this.model.bind('remove', this.remove, this);
//subviews //subviews
this.commentStreamView = new app.views.CommentStream({ model : this.model}); this.commentStreamView = new app.views.CommentStream({model : this.model});
}, },
likesInfoView : function(){ likesInfoView : function(){
return new app.views.LikesInfo({ model : this.model}); return new app.views.LikesInfo({model : this.model});
}, },
feedbackView : function(){ feedbackView : function(){
@ -39,9 +39,10 @@ app.views.StreamPost = app.views.Post.extend({
}, },
postContentView: function(){ postContentView: function(){
var normalizedClass = this.model.get("post_type").replace(/::/, "__"); var normalizedClass = this.model.get("post_type").replace(/::/, "__")
var postClass = app.views[normalizedClass] || app.views.StatusMessage; , postClass = app.views[normalizedClass] || app.views.StatusMessage;
return new postClass({ model : this.model });
return new postClass({ model : this.model })
}, },
removeNsfwShield: function(evt){ removeNsfwShield: function(evt){

View file

@ -1,9 +1,4 @@
app.views.Stream = Backbone.View.extend({ app.views.Stream = Backbone.View.extend({
events: {
"click #paginate": "render"
},
initialize: function(options) { initialize: function(options) {
this.stream = this.model this.stream = this.model
this.collection = this.model.posts this.collection = this.model.posts
@ -16,71 +11,36 @@ app.views.Stream = Backbone.View.extend({
setupEvents : function(){ setupEvents : function(){
this.stream.bind("fetched", this.removeLoader, this) this.stream.bind("fetched", this.removeLoader, this)
this.stream.bind("fetched", this.postRender, this)
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this) this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
this.collection.bind("add", this.addPost, this); this.collection.bind("add", this.addPost, this);
if(window.app.user()) {
app.user().bind("nsfwChanged", function() { app.currentUser.bind("nsfwChanged", reRenderPostViews, this)
_.map(this.postViews, function(view){ view.render() }) function reRenderPostViews() {
}, this) _.map(this.postViews, function(view){ view.render() })
} }
}, },
addPost : function(post) { addPost : function(post) {
var postView = new app.views.StreamPost({ model: post }); var postView = new app.views.StreamPost({ model: post })
, placeInStream = (this.collection.at(0).id == post.id) ? "prepend" : "append";
$(this.el)[
(this.collection.at(0).id == post.id)
? "prepend"
: "append"
](postView.render().el);
this.$el[placeInStream](postView.render().el);
this.postViews.push(postView) this.postViews.push(postView)
return this;
}, },
unbindInfScroll : function() { unbindInfScroll : function() {
$(window).unbind("scroll"); $(window).unbind("scroll");
}, },
render : function(evt) { render : function() {
if(evt) { evt.preventDefault(); } if(this.stream.isFetching()) { this.appendLoader() }
// fetch more posts from the stream model
if(this.stream.fetch()) {
this.appendLoader()
};
return this; return this;
}, },
postRender : function() { fetchAndAppendLoader : function(){
// collapse long posts if(this.stream.isFetching()) { return false }
var collHeight = 420, this.stream.fetch()
collElem = $(this.el).find(".collapsible"); this.appendLoader()
_.each(collElem, function(elem) {
var elem = $(elem),
oembed = elem.find(".oembed"),
addHeight = 0;
if( $.trim(oembed.html()) != "" ) {
addHeight = oembed.height();
}
// only collapse if height exceeds collHeight+20%
if( elem.height() > ((collHeight*1.2)+addHeight) && !elem.is(".opened") ) {
elem.data("orig-height", elem.height() );
elem
.height( Math.max(collHeight, addHeight) )
.addClass("collapsed")
.append(
$('<div />')
.addClass('expander')
.text( Diaspora.I18n.t("show_more") )
);
}
});
}, },
appendLoader: function(){ appendLoader: function(){
@ -96,24 +56,22 @@ app.views.Stream = Backbone.View.extend({
setupLightbox : function(){ setupLightbox : function(){
this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox"); this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox");
$(this.el).delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked); this.$el.delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked);
}, },
setupInfiniteScroll : function() { setupInfiniteScroll : function() {
var throttledScroll = _.throttle($.proxy(this.infScroll, this), 200); var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
$(window).scroll(throttledScroll); $(window).scroll(throttledScroll);
}, },
infScroll : function() { infScroll : function() {
var $window = $(window); var $window = $(window)
var distFromTop = $window.height() + $window.scrollTop(); , distFromTop = $window.height() + $window.scrollTop()
var distFromBottom = $(document).height() - distFromTop; , distFromBottom = $(document).height() - distFromTop
var bufferPx = 500; , bufferPx = 500;
if(distFromBottom < bufferPx) { if(distFromBottom < bufferPx) {
this.render(); this.fetchAndAppendLoader()
} }
}
return this;
},
}); });

View file

@ -40,13 +40,13 @@ describe("app.views.Stream", function() {
describe("infScroll", function() { describe("infScroll", function() {
// NOTE: inf scroll happens at 500px // NOTE: inf scroll happens at 500px
it("calls render when the user is at the bottom of the page", function() { it("fetches moar when the user is at the bottom of the page", function() {
spyOn($.fn, "height").andReturn(0); spyOn($.fn, "height").andReturn(0);
spyOn($.fn, "scrollTop").andReturn(100); spyOn($.fn, "scrollTop").andReturn(100);
spyOn(this.view, "render"); spyOn(this.view, "fetchAndAppendLoader");
this.view.infScroll(); this.view.infScroll();
expect(this.view.render).toHaveBeenCalled(); expect(this.view.fetchAndAppendLoader).toHaveBeenCalled();
}); });
}); });