115 lines
3.3 KiB
JavaScript
Executable File
115 lines
3.3 KiB
JavaScript
Executable File
var Backbone = require('backbone');
|
|
var _ = require('underscore');
|
|
|
|
/**
|
|
* View model intended to be responsible for pagination logic, and to be used in conjunction with a Pagination view.
|
|
*/
|
|
module.exports = Backbone.Model.extend({
|
|
defaults: {
|
|
total_count: 0,
|
|
per_page: 10,
|
|
current_page: 1,
|
|
display_count: 5,
|
|
extras_display_count: 1,
|
|
url_to: undefined
|
|
},
|
|
|
|
pagesCount: function () {
|
|
return Math.max(
|
|
Math.ceil(
|
|
this.get('total_count') / this.get('per_page')
|
|
), 1);
|
|
},
|
|
|
|
isCurrentPage: function (page) {
|
|
return this.get('current_page') === page;
|
|
},
|
|
|
|
shouldBeVisible: function () {
|
|
var pagesCount = this.pagesCount();
|
|
return this.get('total_count') > 0 && pagesCount > 1 && this.get('current_page') <= pagesCount;
|
|
},
|
|
|
|
urlTo: function (page) {
|
|
if (this.hasUrl()) {
|
|
return this.get('url_to')(page);
|
|
}
|
|
},
|
|
|
|
hasUrl: function () {
|
|
return typeof this.get('url_to') === 'function';
|
|
},
|
|
|
|
/**
|
|
* Get the pages that are expected to be displayed.
|
|
* The current page will be in the middle of the returned sequence.
|
|
*
|
|
* @returns {number[]} a sequence of Numbers
|
|
*/
|
|
pagesToDisplay: function () {
|
|
var rangeStart;
|
|
|
|
if (this._inLowRange()) {
|
|
rangeStart = 1;
|
|
} else if (this._inHighRange()) {
|
|
rangeStart = this.get('current_page') - this._startOffset();
|
|
} else {
|
|
// Somewhere between the low and high boundary
|
|
rangeStart = this.pagesCount() - this.get('display_count') + 1;
|
|
}
|
|
rangeStart = Math.max(rangeStart, 1);
|
|
|
|
return this._withExtraPages(
|
|
_.range(rangeStart, this._rangeEnd(rangeStart))
|
|
);
|
|
},
|
|
|
|
_withExtraPages: function (pagesRelativeToCurrentPage) {
|
|
var lastPage = this.pagesCount();
|
|
var extraCount = this.get('extras_display_count');
|
|
var extraStartPages = _.range(1, extraCount + 1);
|
|
var extraEndPages = _.range(lastPage - extraCount + 1, lastPage + 1);
|
|
|
|
var startPagesDiff = pagesRelativeToCurrentPage[0] - extraStartPages.slice(-1)[0];
|
|
if (startPagesDiff === 2) {
|
|
// There is only one missing page in the gap, so add it
|
|
extraStartPages.push(pagesRelativeToCurrentPage[0] - 1);
|
|
} else if (startPagesDiff > 2) {
|
|
// There are more hidden pages at low range, add padding at end
|
|
extraStartPages.push(-1);
|
|
}
|
|
|
|
var endPagesDiff = extraEndPages[0] - pagesRelativeToCurrentPage.slice(-1);
|
|
if (endPagesDiff === 2) {
|
|
// There is only one missing page in the gap, so add it
|
|
extraEndPages.unshift(extraEndPages[0] - 1);
|
|
} if (endPagesDiff > 2) {
|
|
// There are more hidden pages at high range, add padding at beginning
|
|
extraEndPages.unshift(-2);
|
|
}
|
|
|
|
return _.union(extraStartPages, pagesRelativeToCurrentPage, extraEndPages);
|
|
},
|
|
|
|
_inLowRange: function () {
|
|
return this.get('current_page') < this._startOffset();
|
|
},
|
|
|
|
_inHighRange: function () {
|
|
return this.get('current_page') < this._highBoundary();
|
|
},
|
|
|
|
_highBoundary: function () {
|
|
return this.pagesCount() - this._startOffset();
|
|
},
|
|
|
|
_startOffset: function () {
|
|
return Math.floor(this.get('display_count') / 2);
|
|
},
|
|
|
|
_rangeEnd: function (rangeStart) {
|
|
// If we are too close to the range end then cap to the pages count.
|
|
return Math.min(rangeStart + this.get('display_count'), this.pagesCount() + 1);
|
|
}
|
|
});
|