Created
December 29, 2011 03:54
-
-
Save bmsterling/1531733 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/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Folder structure being used | |
assets/ | |
app/ | |
collections/ | |
tags.js | |
mixins/ | |
pagination.js | |
models/ | |
tag.js | |
views/ | |
pagination.js | |
tags.js |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (models) { | |
models.Tag = Backbone.Model.extend({}); | |
})(App.models); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment