Skip to content

Instantly share code, notes, and snippets.

@io41
Forked from zerowidth/paginated_collection.js
Created February 22, 2011 10:10
Show Gist options
  • Save io41/838460 to your computer and use it in GitHub Desktop.
Save io41/838460 to your computer and use it in GitHub Desktop.
Pagination with Backbone.js
// includes bindings for fetching/fetched
var PaginatedCollection = Backbone.Collection.extend({
initialize: function() {
_.bindAll(this, 'parse', 'url', 'pageInfo', 'nextPage', 'previousPage');
typeof(options) != 'undefined' || (options = {});
this.page = 1;
typeof(this.perPage) != 'undefined' || (this.perPage = 10);
},
fetch: function(options) {
typeof(options) != 'undefined' || (options = {});
this.trigger("fetching");
var self = this;
var success = options.success;
options.success = function(resp) {
self.trigger("fetched");
if(success) { success(self, resp); }
};
return Backbone.Collection.prototype.fetch.call(this, options);
},
parse: function(resp) {
this.page = resp.page;
this.perPage = resp.perPage;
this.total = resp.total;
return resp.models;
},
url: function() {
return this.baseUrl + '?' + $.param({page: this.page, perPage: this.perPage});
},
pageInfo: function() {
var info = {
total: this.total,
page: this.page,
perPage: this.perPage,
pages: Math.ceil(this.total / this.perPage),
prev: false,
next: false
};
var max = Math.min(this.total, this.page * this.perPage);
if (this.total == this.pages * this.perPage) {
max = this.total;
}
info.range = [(this.page - 1) * this.perPage + 1, max];
if (this.page > 1) {
info.prev = this.page - 1;
}
if (this.page < info.pages) {
info.next = this.page + 1;
}
return info;
},
nextPage: function() {
if (!this.pageInfo().next) {
return false;
}
this.page = this.page + 1;
return this.fetch();
},
previousPage: function() {
if (!this.pageInfo().prev) {
return false;
}
this.page = this.page - 1;
return this.fetch();
}
});
PaginatedView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'previous', 'next', 'render');
this.collection.bind('refresh', this.render);
},
events: {
'click a.prev': 'previous',
'click a.next': 'next'
},
render: function() {
this.el.html(app.templates.pagination(this.collection.pageInfo()));
},
previous: function() {
this.collection.previousPage();
return false;
},
next: function() {
this.collection.nextPage();
return false;
}
});
<% if(pages > 1) { %>
<% if(prev) { %>
<a href="#" class="prev">previous</a>
<% } else { %>
<span>previous</span>
<% } %>
<%= range[0] %>..<%= range[1] %> of <%= total %>
<% if(next) { %>
<a href="#" class="next">next</a>
<% } else { %>
<span>next</span>
<% } %>
<% } %>
@bweston92
Copy link

How can this be used to display the results as well?
Thanks.

@dtudury
Copy link

dtudury commented Aug 20, 2013

good stuff, ty!

@alejomongua
Copy link

Thank you, this helped me a lot.

@Moverr
Copy link

Moverr commented Oct 21, 2016

thanks boss

@seanCodes
Copy link

Awesome, thanks for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment