DC DG extract infininte scroll to a mixin
This commit is contained in:
parent
7361b8f305
commit
a307b60dd2
3 changed files with 85 additions and 62 deletions
|
|
@ -21,7 +21,8 @@ app.views.Base = Backbone.View.extend({
|
|||
},
|
||||
|
||||
defaultPresenter : function(){
|
||||
var modelJson = this.model ? _.clone(this.model.attributes) : {}
|
||||
var modelJson = this.model && this.model.attributes ? _.clone(this.model.attributes) : {}
|
||||
|
||||
return _.extend(modelJson, {
|
||||
current_user : app.currentUser.attributes,
|
||||
loggedIn : app.currentUser.authenticated()
|
||||
|
|
@ -71,3 +72,66 @@ app.views.Base = Backbone.View.extend({
|
|||
$(".tooltip").remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Mixin to render a collection that fetches more via infinite scroll, for a view that has no template.
|
||||
// Requires:
|
||||
// a stream model, bound as this.stream
|
||||
// a stream's posts, bound as this.collection
|
||||
// a postClass to be declared
|
||||
// a #paginate div in the layout
|
||||
// a call to setupInfiniteScroll
|
||||
|
||||
app.views.infiniteScrollMixin = {
|
||||
setupInfiniteScroll : function() {
|
||||
this.postViews = this.postViews || []
|
||||
|
||||
this.bind("loadMore", this.fetchAndshowLoader, this)
|
||||
this.stream.bind("fetched", this.hideLoader, this)
|
||||
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
|
||||
this.collection.bind("add", this.addPost, this);
|
||||
|
||||
var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
|
||||
$(window).scroll(throttledScroll);
|
||||
},
|
||||
|
||||
renderTemplate : function() {
|
||||
if(this.stream.isFetching()) { this.showLoader() }
|
||||
},
|
||||
|
||||
addPost : function(post) {
|
||||
var postView = new this.postClass({ model: post })
|
||||
, placeInStream = (this.collection.at(0).id == post.id) ? "prepend" : "append";
|
||||
|
||||
this.$el[placeInStream](postView.render().el);
|
||||
this.postViews.push(postView)
|
||||
},
|
||||
|
||||
unbindInfScroll : function() {
|
||||
$(window).unbind("scroll");
|
||||
},
|
||||
|
||||
fetchAndshowLoader : function(){
|
||||
if(this.stream.isFetching()) { return false }
|
||||
this.stream.fetch()
|
||||
this.showLoader()
|
||||
},
|
||||
|
||||
showLoader: function(){
|
||||
$("#paginate .loader").removeClass("hidden")
|
||||
},
|
||||
|
||||
hideLoader: function() {
|
||||
$("#paginate .loader").addClass("hidden")
|
||||
},
|
||||
|
||||
infScroll : function() {
|
||||
var $window = $(window)
|
||||
, distFromTop = $window.height() + $window.scrollTop()
|
||||
, distFromBottom = $(document).height() - distFromTop
|
||||
, bufferPx = 500;
|
||||
|
||||
if(distFromBottom < bufferPx) {
|
||||
this.trigger("loadMore")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,74 +1,26 @@
|
|||
app.views.Stream = Backbone.View.extend({
|
||||
app.views.Stream = Backbone.View.extend(_.extend({
|
||||
initialize: function(options) {
|
||||
this.stream = this.model
|
||||
this.collection = this.model.posts
|
||||
|
||||
this.setupEvents()
|
||||
this.setupInfiniteScroll()
|
||||
this.setupLightbox()
|
||||
this.postViews = []
|
||||
|
||||
this.setupNSFW()
|
||||
this.setupLightbox()
|
||||
this.setupInfiniteScroll()
|
||||
},
|
||||
|
||||
setupEvents : function(){
|
||||
this.stream.bind("fetched", this.removeLoader, this)
|
||||
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
|
||||
this.collection.bind("add", this.addPost, this);
|
||||
|
||||
app.currentUser.bind("nsfwChanged", reRenderPostViews, this)
|
||||
function reRenderPostViews() {
|
||||
_.map(this.postViews, function(view){ view.render() })
|
||||
}
|
||||
},
|
||||
|
||||
addPost : function(post) {
|
||||
var postView = new app.views.StreamPost({ model: post })
|
||||
, placeInStream = (this.collection.at(0).id == post.id) ? "prepend" : "append";
|
||||
|
||||
this.$el[placeInStream](postView.render().el);
|
||||
this.postViews.push(postView)
|
||||
},
|
||||
|
||||
unbindInfScroll : function() {
|
||||
$(window).unbind("scroll");
|
||||
},
|
||||
|
||||
render : function() {
|
||||
if(this.stream.isFetching()) { this.appendLoader() }
|
||||
return this;
|
||||
},
|
||||
|
||||
fetchAndAppendLoader : function(){
|
||||
if(this.stream.isFetching()) { return false }
|
||||
this.stream.fetch()
|
||||
this.appendLoader()
|
||||
},
|
||||
|
||||
appendLoader: function(){
|
||||
$("#paginate .loader").removeClass("hidden")
|
||||
},
|
||||
|
||||
removeLoader: function() {
|
||||
$("#paginate .loader").addClass("hidden")
|
||||
},
|
||||
postClass : app.views.StreamPost,
|
||||
|
||||
setupLightbox : function(){
|
||||
this.lightbox = Diaspora.BaseWidget.instantiate("Lightbox");
|
||||
this.$el.delegate("a.stream-photo-link", "click", this.lightbox.lightboxImageClicked);
|
||||
},
|
||||
|
||||
setupInfiniteScroll : function() {
|
||||
var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
|
||||
$(window).scroll(throttledScroll);
|
||||
},
|
||||
setupNSFW : function(){
|
||||
app.currentUser.bind("nsfwChanged", reRenderPostViews, this)
|
||||
|
||||
infScroll : function() {
|
||||
var $window = $(window)
|
||||
, distFromTop = $window.height() + $window.scrollTop()
|
||||
, distFromBottom = $(document).height() - distFromTop
|
||||
, bufferPx = 500;
|
||||
|
||||
if(distFromBottom < bufferPx) {
|
||||
this.fetchAndAppendLoader()
|
||||
function reRenderPostViews() {
|
||||
_.map(this.postViews, function(view){ view.render() })
|
||||
}
|
||||
}
|
||||
});
|
||||
}, app.views.infiniteScrollMixin));
|
||||
|
|
|
|||
|
|
@ -43,10 +43,17 @@ describe("app.views.Stream", function() {
|
|||
it("fetches moar when the user is at the bottom of the page", function() {
|
||||
spyOn($.fn, "height").andReturn(0);
|
||||
spyOn($.fn, "scrollTop").andReturn(100);
|
||||
spyOn(this.view, "fetchAndAppendLoader");
|
||||
spyOn(this.view.model, "fetch");
|
||||
|
||||
this.view.infScroll();
|
||||
expect(this.view.fetchAndAppendLoader).toHaveBeenCalled();
|
||||
|
||||
waitsFor(function(){
|
||||
return this.view.model.fetch.wasCalled
|
||||
}, "the infinite scroll function didn't fetch the stream")
|
||||
|
||||
runs(function(){
|
||||
expect(this.view.model.fetch).toHaveBeenCalled()
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue