Skip to content

Instantly share code, notes, and snippets.

@letanure
Forked from bmsterling/collections_tags.js
Created January 20, 2012 07:30
Show Gist options
  • Save letanure/1645999 to your computer and use it in GitHub Desktop.
Save letanure/1645999 to your computer and use it in GitHub Desktop.
Pagination of a large set of models. The full story can be found at http://benjaminsterling.com/pagination-and-backbone-js/
(function (collections, pagination, model) {
collections.Tags = Backbone.Collection.extend({
model : model,
url : 'tags_all.php',
/**
* @param resp the response returned by the server
* @returns (Array) tags
*/
parse : function (resp) {
var tags = resp.tags;
return tags;
}
});
_.extend(collections.Tags.prototype, pagination);
})(App.collections, App.mixins.Pagination, App.models.Tag);
// Folder structure being used
assets/
app/
collections/
tags.js
mixins/
pagination.js
models/
tag.js
views/
pagination.js
tags.js
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script src="jquery-1.7.1.min.js"></script>
<script src="underscore.js"></script>
<script src="json2.js"></script>
<script src="backbone.js"></script>
<script type="text/javascript">
var App = {
collections : {},
models : {},
views : {},
mixins : {},
init : function () {
var collection = new App.collections.Tags();
App.views.tags = new App.views.Tags({collection:collection});
new App.views.Pagination({collection:collection});
}
};
</script>
<script src="assets/app/mixins/pagination.js"></script>
<script src="assets/app/models/tag.js"></script>
<script src="assets/app/collections/tags.js"></script>
<script src="assets/app/views/tags.js"></script>
<script src="assets/app/views/pagination.js"></script>
<script type="text/javascript">
$(App.init);
</script>
</head>
<body>
<script type="text/html" id="tmpPagination">
<span class="cell last pages">
<% if (page != 1) { %>
<a href="#" class="first">First</a>
<a href="#" class="prev">Previous</a>
<% } %>
<% _.each (pageSet, function (p) { %>
<% if (page == p) { %>
<span class="page selected"><%= p %></span>
<% } else { %>
<a href="#" class="page"><%= p %></a>
<% } %>
<% }); %>
<% if (lastPage != page) { %>
<a href="#" class="next">Next</a>
<a href="#" class="last">Last</a>
<% } %>
</span>
<span class="cell howmany">
Show
<a href="#" class="selected">20</a>
|
<a href="#" class="">50</a>
|
<a href="#" class="">100</a>
</span>
<span class="cell first records">
<span class="current"><%= startRecord %></span>
-
<span class="perpage"><%= endRecord %></span>
of
<span class="total"><%= totalRecords %></span>
shown
</span>
</script>
</body>
</html>
(function (mixins) {
/**
* @class
* Pagination
*/
mixins.Pagination = {
/** how many items to show per page */
perPage : 20,
/** page to start off on */
page : 1,
/**
*
*/
nextPage : function () {
var self = this;
self.page = ++self.page;
self.pager();
},
previousPage : function () {
var self = this;
self.page = --self.page || 1;
self.pager();
},
goTo : function (page) {
var self = this;
self.page = parseInt(page,10);
self.pager();
},
howManyPer : function (perPage) {
var self = this;
self.page = 1;
self.perPage = perPage;
self.pager();
},
setSort : function (column, direction) {
var self = this;
self.pager(column, direction);
},
pager : function (sort, direction) {
var self = this,
start = (self.page-1)*this.perPage,
stop = start+self.perPage;
if (self.orgmodels === undefined) {
self.orgmodels = self.models;
}
self.models = self.orgmodels;
if (sort) {
self.models = self._sort(self.models, sort);
}
self.reset(
self.models.slice(start,stop)
);
},
_sort : function (models, sort) {
models = models.sort(function(a,b) {
var a = a.get(sort),
b = b.get(sort);
if (direction === 'desc') {
if (a > b) {
return -1;
}
if (a < b) {
return 1;
}
}
else {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
}
return 0;
});
return models;
},
info : function () {
var self = this,
info = {},
totalRecords = (self.orgmodels) ? self.orgmodels.length : self.length,
totalPages = Math.ceil(totalRecords/self.perPage);
info = {
totalRecords : totalRecords,
page : self.page,
perPage : self.perPage,
totalPages : totalPages,
lastPage : totalPages,
lastPagem1 : totalPages-1,
previous : false,
next : false,
page_set : [],
startRecord : (self.page - 1) * self.perPage + 1,
endRecord : Math.min(totalRecords, self.page * self.perPage)
};
if (self.page > 1) {
info.prev = self.page - 1;
}
if (self.page < info.totalPages) {
info.next = self.page + 1;
}
info.pageSet = self.setPagination(info);
self.information = info;
return info;
},
setPagination : function (info) {
var pages = [];
// How many adjacent pages should be shown on each side?
var ADJACENT = 3;
var ADJACENTx2 = ADJACENT*2;
var LASTPAGE = Math.ceil(info.totalRecords/info.perPage);
var LPM1 = -1;
if (LASTPAGE > 1) {
//not enough pages to bother breaking it up
if (LASTPAGE < (7 + ADJACENTx2)) {
for (var i=1,l=LASTPAGE; i <= l; i++) {
pages.push(i);
}
}
// enough pages to hide some
else if (LASTPAGE > (5 + ADJACENTx2)) {
//close to beginning; only hide later pages
if (info.page < (1 + ADJACENTx2)) {
for (var i=1, l=4+ADJACENTx2; i < l; i++) {
pages.push(i);
}
}
//in middle; hide some front and some back
else if(LASTPAGE - ADJACENTx2 > info.page && info.page > ADJACENTx2) {
for (var i = info.page - ADJACENT; i <= info.page + ADJACENT; i++) {
pages.push(i);
}
}
//close to end; only hide early pages
else{
for (var i = LASTPAGE - (2 + ADJACENTx2); i <= LASTPAGE; i++) {
pages.push(i);
}
}
}
}
return pages;
}
};
})(App.mixins);
(function (models) {
models.Tag = Backbone.Model.extend({});
})(App.models);
{
"status":true,
"tags":[
{
"id":1,
"name":"A"
},...
]
}
(function (views) {
views.Pagination = Backbone.View.extend({
events : {
'click a.first' : 'gotoFirst',
'click a.prev' : 'gotoPrev',
'click a.next' : 'gotoNext',
'click a.last' : 'gotoLast',
'click a.page' : 'gotoPage',
'click .howmany a' : 'changeCount'
},
tagName : 'aside',
initialize : function () {
_.bindAll (this, 'render');
var self = this;
self.tmpl = _.template($('#tmpPagination').html());
self.collection.bind('reset', this.render);
$(self.el).appendTo('body');
},
render : function () {
var self;
self = this;
var html = this.tmpl(self.collection.info());
$(this.el).html(html);
},
gotoFirst : function (e) {
e.preventDefault();
var self = this;
self.collection.goTo(1);
},
gotoPrev : function (e) {
e.preventDefault();
var self = this;
self.collection.previousPage();
},
gotoNext : function (e) {
e.preventDefault();
var self = this;
self.collection.nextPage();
},
gotoLast : function (e) {
e.preventDefault();
var self = this;
self.collection.goTo(self.collection.information.lastPage);
},
gotoPage : function (e) {
e.preventDefault();
var self = this;
var page = $(e.target).text();
self.collection.goTo(page);
},
changeCount : function (e) {
e.preventDefault();
var self = this;
var per = $(e.target).text();
self.collection.howManyPer(per);
}
});
})(App.views);
(function (views) {
views.Tags = Backbone.View.extend({
tagName : 'ul',
initialize : function () {
_.bindAll (this, 'render', 'addAll', 'addOne');
var self = this;
self.collection.fetch({
success : function () {
self.collection.pager();
},
silent:true
});
self.collection.bind('reset', self.addAll);
$(self.el).appendTo('body');
},
addAll : function () {
var self = this;
$(self.el).empty();
self.collection.each (self.addOne);
},
addOne : function (model) {
var self = this;
var view = new Tag({model:model});
view.render();
$(self.el).append(view.el);
}
});
var Tag = Backbone.View.extend({
tagName : 'li',
render : function () {
$(this.el).html(this.model.get('name'));
}
});
})(App.views);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment