refactor stream page scroll spy
This commit is contained in:
parent
1ac01cc156
commit
a9288daf19
5 changed files with 103 additions and 133 deletions
|
|
@ -1,8 +1,12 @@
|
|||
//= require_self
|
||||
//= require_tree ./helpers
|
||||
|
||||
//= require ./router
|
||||
//= require ./models
|
||||
|
||||
//= require ./views
|
||||
//= require ./views/infinite_stream_view
|
||||
|
||||
//= require_tree ./models
|
||||
//= require_tree ./pages
|
||||
//= require_tree ./collections
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ app.views.NewStream = app.views.InfScroll.extend({
|
|||
}
|
||||
});
|
||||
|
||||
/*--------------------*/
|
||||
|
||||
app.pages.Stream = app.views.Base.extend({
|
||||
templateName : "stream",
|
||||
|
||||
|
|
@ -23,64 +21,48 @@ app.pages.Stream = app.views.Base.extend({
|
|||
|
||||
initialize : function(){
|
||||
this.stream = this.model = new app.models.Stream()
|
||||
this.stream.preloadOrFetch();
|
||||
this.stream.preloadOrFetch()
|
||||
|
||||
this.streamView = new app.views.NewStream({ model : this.stream })
|
||||
var interactions = this.interactionsView = new app.views.StreamInteractions()
|
||||
|
||||
this.setUpThrottledInteractionScroll();
|
||||
|
||||
this.stream.on("frame:interacted", function(post){
|
||||
interactions.setInteractions(post)
|
||||
})
|
||||
|
||||
this.streamView.on('loadMore', this.updateUrlState, this);
|
||||
this.stream.on("fetched", this.refreshScrollSpy, this)
|
||||
},
|
||||
|
||||
postRenderTemplate : function() {
|
||||
this.$("#header").css("background-image", "url(" + app.currentUser.get("wallpaper") + ")")
|
||||
|
||||
_.defer(function(){$('body').scrollspy({target : '.stream-frame-wrapper', offset : 50})})
|
||||
|
||||
|
||||
this.setUpHashChangeOnStreamLoad()
|
||||
},
|
||||
|
||||
setUpThrottledInteractionScroll : function(){
|
||||
this.focusedPost = undefined;
|
||||
var self = this;
|
||||
this.updateInteractions = _.throttle(function(){
|
||||
console.log("firing for " + self.focusedPost.get('id'));
|
||||
self.interactionsView.setInteractions(self.focusedPost)
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
setUpHashChangeOnStreamLoad : function(){
|
||||
var self = this;
|
||||
this.streamView.on('loadMore', function(){
|
||||
var post = this.stream.items.last();
|
||||
if(post){
|
||||
self.navigateToPost(post)
|
||||
}
|
||||
self.refreshScrollSpy()
|
||||
});
|
||||
updateUrlState : function(){
|
||||
var post = this.stream.items.last();
|
||||
if(post){
|
||||
this.navigateToPost(post)
|
||||
}
|
||||
},
|
||||
|
||||
navigateToPost : function(post){
|
||||
app.router.navigate(location.pathname + "?ex=true&max_time=" + post.createdAt(), {replace: true})
|
||||
},
|
||||
|
||||
|
||||
triggerInteractionLoad : function(evt){
|
||||
var id = $(evt.target).data("id");
|
||||
console.log("calling triggerInteractiosns for: " + id)
|
||||
this.focusedPost = this.stream.items.get(id)
|
||||
this.updateInteractions()
|
||||
|
||||
this._throttledInteractions = this._throttledInteractions || _.bind(_.throttle(this.updateInteractions, 1000), this)
|
||||
this._throttledInteractions()
|
||||
},
|
||||
|
||||
updateInteractions: function () {
|
||||
this.interactionsView.setInteractions(this.focusedPost)
|
||||
},
|
||||
|
||||
//on active guid => this guid
|
||||
// fire interacted from stream collection w/guid
|
||||
refreshScrollSpy : function(){
|
||||
setTimeout(function(){
|
||||
$('body').scrollspy('refresh')
|
||||
}, 2000)
|
||||
_.defer($('body').scrollspy('refresh'))
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -95,81 +95,3 @@ app.views.Base = Backbone.View.extend({
|
|||
}
|
||||
});
|
||||
|
||||
// Mixin to render a collection that fetches more via infinite scroll, for a view that has no template.
|
||||
// Requires:
|
||||
// a stream model, assigned to this.stream
|
||||
// a stream's posts, assigned to this.collection
|
||||
// a postClass to be declared
|
||||
// a #paginate div in the layout
|
||||
// a call to setupInfiniteScroll
|
||||
|
||||
app.views.InfScroll = app.views.Base.extend({
|
||||
setupInfiniteScroll : function() {
|
||||
this.postViews = this.postViews || []
|
||||
|
||||
this.bind("loadMore", this.fetchAndshowLoader, this)
|
||||
this.stream.bind("fetched", this.hideLoader, this)
|
||||
this.stream.bind("allItemsLoaded", this.unbindInfScroll, this)
|
||||
|
||||
this.collection.bind("add", this.addPostView, this);
|
||||
|
||||
var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
|
||||
$(window).scroll(throttledScroll);
|
||||
},
|
||||
|
||||
postRenderTemplate : function() {
|
||||
if(this.stream.isFetching()) { this.showLoader() }
|
||||
},
|
||||
|
||||
createPostView : function(post){
|
||||
var postView = new this.postClass({ model: post, stream: this.stream });
|
||||
this.postViews.push(postView)
|
||||
return postView
|
||||
},
|
||||
|
||||
addPostView : function(post) {
|
||||
var placeInStream = (this.collection.at(0).id == post.id) ? "prepend" : "append";
|
||||
this.$el[placeInStream](this.createPostView(post).render().el);
|
||||
},
|
||||
|
||||
unbindInfScroll : function() {
|
||||
$(window).unbind("scroll");
|
||||
},
|
||||
|
||||
renderTemplate : function(){
|
||||
this.renderInitialPosts()
|
||||
},
|
||||
|
||||
renderInitialPosts : function(){
|
||||
this.$el.empty()
|
||||
this.stream.items.each(_.bind(function(post){
|
||||
this.$el.append(this.createPostView(post).render().el);
|
||||
}, this))
|
||||
},
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
77
app/assets/javascripts/app/views/infinite_stream_view.js
Normal file
77
app/assets/javascripts/app/views/infinite_stream_view.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Abstract Infinite Scroll View Super Class
|
||||
// Requires:
|
||||
// a stream model, assigned to this.stream
|
||||
// a stream's posts, assigned to this.collection
|
||||
// a postClass to be declared
|
||||
// a #paginate div in the layout
|
||||
// a call to setupInfiniteScroll
|
||||
|
||||
app.views.InfScroll = app.views.Base.extend({
|
||||
setupInfiniteScroll : function() {
|
||||
this.postViews = this.postViews || []
|
||||
|
||||
this.bind("loadMore", this.fetchAndshowLoader, this)
|
||||
this.stream.bind("fetched", this.hideLoader, this)
|
||||
this.stream.bind("allItemsLoaded", this.unbindInfScroll, this)
|
||||
|
||||
this.collection.bind("add", this.addPostView, this);
|
||||
|
||||
var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
|
||||
$(window).scroll(throttledScroll);
|
||||
},
|
||||
|
||||
postRenderTemplate : function() {
|
||||
if(this.stream.isFetching()) { this.showLoader() }
|
||||
},
|
||||
|
||||
createPostView : function(post){
|
||||
var postView = new this.postClass({ model: post, stream: this.stream });
|
||||
this.postViews.push(postView)
|
||||
return postView
|
||||
},
|
||||
|
||||
addPostView : function(post) {
|
||||
var placeInStream = (this.collection.at(0).id == post.id) ? "prepend" : "append";
|
||||
this.$el[placeInStream](this.createPostView(post).render().el);
|
||||
},
|
||||
|
||||
unbindInfScroll : function() {
|
||||
$(window).unbind("scroll");
|
||||
},
|
||||
|
||||
renderTemplate : function(){
|
||||
this.renderInitialPosts()
|
||||
},
|
||||
|
||||
renderInitialPosts : function(){
|
||||
this.$el.empty()
|
||||
this.stream.items.each(_.bind(function(post){
|
||||
this.$el.append(this.createPostView(post).render().el);
|
||||
}, this))
|
||||
},
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -6,18 +6,11 @@ describe("app.Pages.Stream", function(){
|
|||
expect(this.post).toBeTruthy()
|
||||
})
|
||||
|
||||
|
||||
describe('postRenderTemplate', function(){
|
||||
it("sets the background-image of #header", function(){
|
||||
this.page.render()
|
||||
expect(this.page.$('#header').css('background-image')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('calls setUpHashChangeOnStreamLoad', function(){
|
||||
spyOn(this.page, 'setUpHashChangeOnStreamLoad')
|
||||
this.page.render();
|
||||
expect(this.page.setUpHashChangeOnStreamLoad).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("rendering", function(){
|
||||
|
|
@ -34,21 +27,13 @@ describe("app.Pages.Stream", function(){
|
|||
})
|
||||
})
|
||||
|
||||
describe("setUpHashChangeOnStreamLoad", function(){
|
||||
it('calls navigateToPost on the loadMore event', function(){
|
||||
spyOn(this.page, 'navigateToPost')
|
||||
this.page.setUpHashChangeOnStreamLoad()
|
||||
this.page.streamView.trigger('loadMore')
|
||||
expect(this.page.navigateToPost).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("navigateToPost", function(){
|
||||
it("sets the max time of the url to the created at time of a post", function(){
|
||||
context("when more posts are loaded", function(){
|
||||
it("navigates to the last post in the stream's max_time", function(){
|
||||
spyOn(app.router, 'navigate')
|
||||
this.page.navigateToPost(this.post)
|
||||
var url = location.pathname + "?ex=true&max_time=" + this.post.createdAt()
|
||||
var options = {replace: true}
|
||||
, options = {replace: true}
|
||||
|
||||
this.page.streamView.trigger('loadMore')
|
||||
expect(app.router.navigate).toHaveBeenCalledWith(url, options)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue