/*
backgrid-paginator
http://github.com/wyuenho/backgrid
Copyright (c) 2013 Jimmy Yuen Ho Wong
Licensed under the MIT @license.
*/
(function ($, _, Backbone, Backgrid) {
"use strict";
/**
Paginator is a Footer element that re-renders a large result set in a table
by splitting it across multiple pages. If the result set is still larger,
the page handles are rendered within a sliding window, with 10 indexed page
handles each by default, plus the fast forward, fast backward, previous and
next page handles. The fast forward, fast backward, previous and next page
handles can be turned off.
@class Backgrid.Extension.Paginator
*/
Backgrid.Extension.Paginator = Backgrid.Footer.extend({
/** @property */
className: "paginator",
/** @property */
windowSize: 10,
/** @property */
fastForwardHandleLabels: {
first: "《",
prev: "〈",
next: "〉",
last: "》"
},
/** @property */
template: _.template('
'),
/** @property */
events: {
"click a": "changePage"
},
/**
Initializer.
@param {Object} options
@param {Backbone.Collection.|Array.|Array.} options.columns
Column metadata.
@param {Backbone.Collection} options.collection
@param {boolean} [options.fastForwardHandleLabels] Whether to render fast forward buttons.
*/
initialize: function (options) {
Backgrid.Footer.prototype.initialize.call(this, options);
var columns = this.columns;
this.listenTo(columns, "add", this.render);
this.listenTo(columns, "remove", this.render);
this.listenTo(columns, "change:renderable", this.render);
var collection = this.collection;
var fullCollection = collection.fullCollection;
if (fullCollection) {
this.listenTo(fullCollection, "add", this.render);
this.listenTo(fullCollection, "remove", this.render);
this.listenTo(fullCollection, "reset", this.render);
}
else {
this.listenTo(collection, "add", this.render);
this.listenTo(collection, "remove", this.render);
this.listenTo(collection, "reset", this.render);
}
},
/**
jQuery event handler for the page handlers. Goes to the right page upon
clicking.
@param {Event} e
*/
changePage: function (e) {
e.preventDefault();
var label = $(e.target).text();
var ffLabels = this.fastForwardHandleLabels;
var collection = this.collection;
if (ffLabels) {
switch (label) {
case ffLabels.first:
collection.getFirstPage();
return;
case ffLabels.prev:
if (collection.hasPrevious()) collection.getPreviousPage();
return;
case ffLabels.next:
if (collection.hasNext()) collection.getNextPage();
return;
case ffLabels.last:
collection.getLastPage();
return;
}
}
var state = collection.state;
var pageIndex = $(e.target).text() * 1 - state.firstPage;
collection.getPage(state.firstPage === 0 ? pageIndex : pageIndex + 1);
},
/**
Internal method to create a list of page handle objects for the template
to render them.
@return Array. an array of page handle objects hashes
*/
makeHandles: function () {
var handles = [];
var collection = this.collection;
var state = collection.state;
// convert all indices to 0-based here
var lastPage = state.lastPage ? state.lastPage : state.firstPage;
lastPage = state.firstPage === 0 ? lastPage : lastPage - 1;
var currentPage = state.firstPage === 0 ? state.currentPage : state.currentPage - 1;
var windowStart = Math.floor(currentPage / this.windowSize) * this.windowSize;
var windowEnd = windowStart + this.windowSize;
windowEnd = windowEnd <= lastPage ? windowEnd : lastPage + 1;
if (collection.mode !== "infinite") {
for (var i = windowStart; i < windowEnd; i++) {
handles.push({
label: i + 1,
title: "No. " + (i + 1),
className: currentPage === i ? "active" : undefined
});
}
}
var ffLabels = this.fastForwardHandleLabels;
if (ffLabels) {
if (ffLabels.prev) {
handles.unshift({
label: ffLabels.prev,
className: collection.hasPrevious() ? void 0 : "disabled"
});
}
if (ffLabels.first) {
handles.unshift({
label: ffLabels.first,
className: collection.hasPrevious() ? void 0 : "disabled"
});
}
if (ffLabels.next) {
handles.push({
label: ffLabels.next,
className: collection.hasNext() ? void 0 : "disabled"
});
}
if (ffLabels.last) {
handles.push({
label: ffLabels.last,
className: collection.hasNext() ? void 0 : "disabled"
});
}
}
return handles;
},
/**
Render the paginator handles inside an unordered list placed inside a
cell that spans all the columns.
*/
render: function () {
this.$el.empty();
var colspan = _.reduce(
this.columns.pluck("renderable"),
function (accum, renderable) {
return renderable ? accum + 1 : accum;
}, 0);
this.$el.append($(this.template({
colspan: colspan,
handles: this.makeHandles()
})));
return this;
}
});
}(jQuery, _, Backbone, Backgrid));