Merge branch 'stream-js-cleanup'
Conflicts: public/javascripts/app/models/stream.js
This commit is contained in:
commit
750e26e8fb
8 changed files with 90 additions and 120 deletions
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
#gs-shim{:title => popover_with_close_html("3. #{t('.stay_updated')}"), 'data-content' => t('.stay_updated_explanation')}
|
||||
|
||||
#main_stream.stream{:data => {:guids => stream.aspect_ids.join(',')}}
|
||||
#main_stream.stream
|
||||
|
||||
#paginate
|
||||
|
||||
- if current_user.contacts.size < 2
|
||||
= render 'aspects/no_contacts_message'
|
||||
|
|
|
|||
|
|
@ -7,19 +7,33 @@ app.models.Stream = Backbone.Collection.extend({
|
|||
return _.any(this.posts.models) ? this.timeFilteredPath() : this.basePath()
|
||||
},
|
||||
|
||||
_fetching : false,
|
||||
|
||||
fetch: function() {
|
||||
var self = this
|
||||
|
||||
// we're fetching the collection... there is probably a better way to do this
|
||||
self._fetching = true;
|
||||
|
||||
this.posts
|
||||
.fetch({
|
||||
add : true,
|
||||
url : self.url()
|
||||
})
|
||||
.done(
|
||||
function(response){
|
||||
self.trigger("fetched", self, response);
|
||||
function(resp){
|
||||
// we're done fetching... there is probably a better way to handle this
|
||||
self._fetching = false;
|
||||
|
||||
self.trigger("fetched", self);
|
||||
|
||||
// all loaded?
|
||||
if(resp.posts && (resp.posts.author || resp.posts.length == 0)) {
|
||||
self.trigger("allPostsLoaded", self);
|
||||
}
|
||||
}
|
||||
)
|
||||
return this;
|
||||
},
|
||||
|
||||
basePath : function(){
|
||||
|
|
|
|||
|
|
@ -14,10 +14,12 @@ app.Router = Backbone.Router.extend({
|
|||
|
||||
stream : function() {
|
||||
app.stream = new app.models.Stream()
|
||||
app.page = new app.views.Stream().render();
|
||||
$("#main_stream").html(app.page.el);
|
||||
app.page = new app.views.Stream({model : app.stream}).render();
|
||||
app.publisher = app.publisher || new app.views.Publisher({collection : app.stream.posts});
|
||||
|
||||
var streamFacesView = new app.views.StreamFaces({collection : app.stream.posts}).render();
|
||||
|
||||
$("#main_stream").html(app.page.el);
|
||||
$('#selected_aspect_contacts .content').html(streamFacesView.el);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ app.views.CommentStream = app.views.Base.extend({
|
|||
|
||||
initialize: function(options) {
|
||||
this.model.comments.bind('add', this.appendComment, this);
|
||||
|
||||
// add autoexpanders to new comment textarea
|
||||
this.$('textarea').autoResize();
|
||||
},
|
||||
|
||||
postRenderTemplate : function() {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ app.views.Publisher = Backbone.View.extend({
|
|||
},
|
||||
|
||||
initialize : function(){
|
||||
this.collection = this.collection || new app.collections.Posts;
|
||||
this.collection = this.collection //takes a Posts collection
|
||||
return this;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -4,16 +4,20 @@ app.views.Stream = Backbone.View.extend({
|
|||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.stream = app.stream || new app.models.Stream()
|
||||
this.collection = this.stream.posts
|
||||
this.publisher = new app.views.Publisher({collection : this.collection});
|
||||
this.stream = this.model
|
||||
this.collection = this.model.posts
|
||||
|
||||
this.stream.bind("fetched", this.collectionFetched, this)
|
||||
this.collection.bind("add", this.addPost, this);
|
||||
this.setupEvents()
|
||||
this.setupInfiniteScroll()
|
||||
this.setupLightbox()
|
||||
},
|
||||
|
||||
setupEvents : function(){
|
||||
this.stream.bind("fetched", this.removeLoader, this)
|
||||
this.stream.bind("allPostsLoaded", this.unbindInfScroll, this)
|
||||
this.collection.bind("add", this.addPost, this);
|
||||
},
|
||||
|
||||
addPost : function(post) {
|
||||
var postView = new app.views.Post({ model: post });
|
||||
|
||||
|
|
@ -26,51 +30,30 @@ app.views.Stream = Backbone.View.extend({
|
|||
return this;
|
||||
},
|
||||
|
||||
isLoading : function(){
|
||||
return this._loading && !this._loading.isResolved();
|
||||
},
|
||||
|
||||
allContentLoaded : false,
|
||||
|
||||
|
||||
collectionFetched: function(collection, response) {
|
||||
this.removeLoader()
|
||||
if(!collection.parse(response).length || collection.parse(response).length == 0) {
|
||||
this.allContentLoaded = true;
|
||||
$(window).unbind('scroll')
|
||||
return
|
||||
}
|
||||
|
||||
$(this.el).append($("<a>", {
|
||||
href: this.stream.url(),
|
||||
id: "paginate"
|
||||
}).text('Load more posts'));
|
||||
unbindInfScroll : function() {
|
||||
$("window").unbind("scroll");
|
||||
},
|
||||
|
||||
render : function(evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
|
||||
this.addLoader();
|
||||
this._loading = this.stream.fetch();
|
||||
// fetch more posts from the stream model
|
||||
if(this.stream.fetch()) {
|
||||
this.appendLoader()
|
||||
};
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addLoader: function(){
|
||||
if(this.$("#paginate").length == 0) {
|
||||
$(this.el).append($("<div>", {
|
||||
"id" : "paginate"
|
||||
}));
|
||||
}
|
||||
|
||||
this.$("#paginate").html($("<img>", {
|
||||
appendLoader: function(){
|
||||
$("#paginate").html($("<img>", {
|
||||
src : "/images/static-loader.png",
|
||||
"class" : "loader"
|
||||
}));
|
||||
},
|
||||
|
||||
removeLoader : function(){
|
||||
this.$("#paginate").remove();
|
||||
removeLoader: function() {
|
||||
$("#paginate").empty();
|
||||
},
|
||||
|
||||
setupLightbox : function(){
|
||||
|
|
@ -80,13 +63,11 @@ app.views.Stream = Backbone.View.extend({
|
|||
|
||||
setupInfiniteScroll : function() {
|
||||
var throttledScroll = _.throttle($.proxy(this.infScroll, this), 200);
|
||||
$(window).scroll(throttledScroll);
|
||||
$("window").scroll(throttledScroll);
|
||||
},
|
||||
|
||||
infScroll : function() {
|
||||
if(this.allContentLoaded || this.isLoading()) { return }
|
||||
|
||||
var $window = $(window);
|
||||
var $window = $("window");
|
||||
var distFromTop = $window.height() + $window.scrollTop();
|
||||
var distFromBottom = $(document).height() - distFromTop;
|
||||
var bufferPx = 500;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,23 @@ describe("app.models.Stream", function() {
|
|||
var fetchedSpy = jasmine.createSpy()
|
||||
this.stream.bind('fetched', fetchedSpy)
|
||||
this.stream.fetch()
|
||||
postFetch.resolve()
|
||||
postFetch.resolve({posts : [1,2,3]})
|
||||
expect(fetchedSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("triggers allPostsLoaded on the stream when zero posts are returned", function(){
|
||||
var fetchedSpy = jasmine.createSpy()
|
||||
this.stream.bind('allPostsLoaded', fetchedSpy)
|
||||
this.stream.fetch()
|
||||
postFetch.resolve({posts : []})
|
||||
expect(fetchedSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("triggers allPostsLoaded on the stream when a Post is returned", function(){
|
||||
var fetchedSpy = jasmine.createSpy()
|
||||
this.stream.bind('allPostsLoaded', fetchedSpy)
|
||||
this.stream.fetch()
|
||||
postFetch.resolve({posts : factory.post().attributes})
|
||||
expect(fetchedSpy).toHaveBeenCalled()
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ describe("app.views.Stream", function(){
|
|||
|
||||
this.posts = $.parseJSON(spec.readFixture("multi_stream_json"))["posts"];
|
||||
|
||||
app.stream = new app.models.Stream()
|
||||
app.stream.add(this.posts);
|
||||
this.stream = new app.models.Stream()
|
||||
this.stream.add(this.posts);
|
||||
|
||||
this.collection = app.stream.posts
|
||||
this.view = new app.views.Stream({collection : this.collection});
|
||||
this.view = new app.views.Stream({model : this.stream});
|
||||
|
||||
app.stream.bind("fetched", this.collectionFetched, this) //untested
|
||||
|
||||
|
|
@ -20,16 +19,15 @@ describe("app.views.Stream", function(){
|
|||
describe("initialize", function(){
|
||||
it("binds an infinite scroll listener", function(){
|
||||
spyOn($.fn, "scroll");
|
||||
|
||||
new app.views.Stream();
|
||||
new app.views.Stream({model : this.stream});
|
||||
expect($.fn.scroll).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("#render", function(){
|
||||
beforeEach(function(){
|
||||
this.statusMessage = this.collection.models[0];
|
||||
this.reshare = this.collection.models[1];
|
||||
this.statusMessage = this.stream.posts.models[0];
|
||||
this.reshare = this.stream.posts.models[1];
|
||||
this.statusElement = $(this.view.$("#" + this.statusMessage.get("guid")));
|
||||
this.reshareElement = $(this.view.$("#" + this.reshare.get("guid")));
|
||||
})
|
||||
|
|
@ -44,77 +42,31 @@ describe("app.views.Stream", function(){
|
|||
describe("infScroll", function(){
|
||||
// NOTE: inf scroll happens at 500px
|
||||
|
||||
beforeEach(function(){
|
||||
spyOn(this.view.collection, "fetch").andReturn($.Deferred())
|
||||
})
|
||||
|
||||
context("when the user is at the bottom of the page", function(){
|
||||
beforeEach(function(){
|
||||
spyOn($.fn, "height").andReturn(0)
|
||||
spyOn($.fn, "scrollTop").andReturn(100)
|
||||
})
|
||||
|
||||
it("calls fetch", function(){
|
||||
spyOn(this.view, "isLoading").andReturn(false)
|
||||
|
||||
this.view.infScroll();
|
||||
expect(this.view.collection.fetch).toHaveBeenCalled();
|
||||
})
|
||||
|
||||
it("does not call fetch if the collection is loading", function(){
|
||||
spyOn(this.view, "isLoading").andReturn(true)
|
||||
|
||||
this.view.infScroll();
|
||||
expect(this.view.collection.fetch).not.toHaveBeenCalled();
|
||||
})
|
||||
|
||||
it("does not call fetch if all content has been fetched", function(){
|
||||
spyOn(this.view, "isLoading").andReturn(false)
|
||||
this.view.allContentLoaded = true;
|
||||
|
||||
this.view.infScroll();
|
||||
expect(this.view.collection.fetch).not.toHaveBeenCalled();
|
||||
})
|
||||
})
|
||||
|
||||
it("does not fetch new content when the user is not at the bottom of the page", function(){
|
||||
spyOn(this.view, "isLoading").andReturn(false)
|
||||
|
||||
spyOn($.fn, "height").andReturn(0);
|
||||
spyOn($.fn, "scrollTop").andReturn(-500);
|
||||
it("calls render when the user is at the bottom of the page", function(){
|
||||
spyOn($.fn, "height").andReturn(0)
|
||||
spyOn($.fn, "scrollTop").andReturn(100)
|
||||
spyOn(this.view, "render")
|
||||
|
||||
this.view.infScroll();
|
||||
expect(this.view.collection.fetch).not.toHaveBeenCalled();
|
||||
expect(this.view.render).toHaveBeenCalled();
|
||||
})
|
||||
})
|
||||
|
||||
describe("collectionFetched", function(){
|
||||
context("unbinding scroll", function(){
|
||||
beforeEach(function(){
|
||||
spyOn($.fn, "unbind")
|
||||
})
|
||||
|
||||
it("unbinds scroll if there are no more posts left to load", function(){
|
||||
this.view.collectionFetched(this.collection, {posts : []})
|
||||
expect($.fn.unbind).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("does not fetch new content when the user is fetching one post", function(){
|
||||
this.view.collectionFetched(this.collection, {posts : {}})
|
||||
expect($.fn.unbind).toHaveBeenCalled()
|
||||
})
|
||||
describe("removeLoader", function() {
|
||||
it("emptys the pagination div when the stream is fetched", function(){
|
||||
$("#jasmine_content").append($('<div id="paginate">OMG</div>'))
|
||||
expect($("#paginate").text()).toBe("OMG")
|
||||
this.view.stream.trigger("fetched")
|
||||
expect($("#paginate")).toBeEmpty()
|
||||
})
|
||||
})
|
||||
|
||||
it("sets this.allContentLoaded if there are no more posts left to load", function(){
|
||||
expect(this.view.allContentLoaded).toBe(false)
|
||||
this.view.collectionFetched(this.collection, {posts : []})
|
||||
expect(this.view.allContentLoaded).toBe(true)
|
||||
})
|
||||
|
||||
it("does not set this.allContentLoaded if there was a non-empty response from the server", function(){
|
||||
expect(this.view.allContentLoaded).toBe(false)
|
||||
this.view.collectionFetched(this.collection, {posts : this.posts})
|
||||
expect(this.view.allContentLoaded).toBe(false)
|
||||
describe("unbindInfScroll", function(){
|
||||
it("unbinds scroll", function() {
|
||||
spyOn($.fn, "unbind")
|
||||
this.view.unbindInfScroll()
|
||||
expect($.fn.unbind.mostRecentCall.object.selector).toBe("window")
|
||||
expect($.fn.unbind).toHaveBeenCalledWith("scroll")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue