Most websites offer some form of pagination. There is a limit how many records can be displayed on a single page and breaking the record set up in pages makes a lot of sense. This pagination sample displays 9 well-known paintings per page. There are 3 pages total.
Like the previous examples this one uses Backbone, underscore templating (with changed template token markers), in-page templates (using <script> tags), and a Mock server. The two script templates are named pictures-template and picture-template respectively.
Here is the pagination code:
var Patterns = {
// ** namespace pattern
namespace: function (name) {
// ** single var pattern
var parts = name.split(".");
var ns = this;
// ** iterator pattern
for (var i = 0, len = parts.length; i < len; i++) {
// ** || idiomT
ns[parts[i]] = ns[parts[i]] || {};
ns = ns[parts[i]];
}
return ns;
}
};
// ** namespace pattern
// ** revealing module pattern
// ** singleton pattern
Patterns.namespace("InAction").Pagination = (function () {
// ** namespace pattern
var Models = {};
var Views = {};
var Routers = {};
// Change template token markers to {{ and }}
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g,
evaluate: /\{\{(.+?)\}\}/g
};
// ** extend pattern
Routers.Router = Backbone.Router.extend({
// ** init pattern
initialize: function (options) {
this.el = options.el;
},
routes: {
"": "paginate",
":page": "paginate"
},
paginate: function (page) {
// ** truthy/falsy idiom
var p = page ? parseInt(page, 10) : 1;
// ** chaining pattern
this.el.html(new Views.Pagination({ page: p }).el);
this.el.append(new Views.Pictures({ page: p }).el);
this.el.append(new Views.Pagination({ page: p }).el);
}
});
// ** extend pattern
// ** option hash idiom
Models.Picture = Backbone.Model.extend({
});
// ** extend pattern
// ** option hash idiom
Models.Pictures = Backbone.Collection.extend({
model: Models.Picture,
url: "pagination"
});
// ** extend pattern
// ** option hash idiom
Views.Pictures = Backbone.View.extend({
tagName: "ul",
className: "thumbnails",
// ** init pattern
initialize: function (options) {
this.page = options.page;
this.collection = new Models.Pictures();
this.collection.bind("reset", this.render, this);
this.collection.fetch({ data: { page: this.page } });
},
render: function () {
// ** iterator pattern
this.collection.each(function (picture) {
var view = new Views.Picture({ model: picture });
this.$el.append(view.render().el);
}, this);
return this;
}
});
// ** extend pattern
// ** option hash idiom
Views.Picture = Backbone.View.extend({
tagName: "li",
template: _.template($('#picture-template').html()),
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
// ** extend pattern
// ** option hash idiom
Views.Pagination = Backbone.View.extend({
tagName: "div", // this is default
className: "pagination pagination-centered",
// ** init pattern
initialize: function (options) {
this.page = options.page;
this.render();
},
render: function () {
var pageCount = Math.ceil(pictures.length / 9);
this.$el.css("padding-right", "100px");
this.$el.append("The idioms and patterns used in this example are:
Each page makes a mocked Ajax server call and gets a number of pictures returned. Depending on how users use the app, you may consider caching the pictures already returned to the client. This could be implemented using the Lazy Load pattern. To keep things simple this is not implemented in this example but wouldn't be hard to add.