/**
* Paginator
* Simple and versatile Pagination class for PHP, JavaScript, Python
*
* @version: 1.1.0
* https://github.com/foo123/Paginator
*
**/
!function(root, name, factory) {
"use strict";
if (('undefined'!==typeof Components)&&('object'===typeof Components.classes)&&('object'===typeof Components.classesByID)&&Components.utils&&('function'===typeof Components.utils['import'])) /* XPCOM */
(root.$deps = root.$deps||{}) && (root.EXPORTED_SYMBOLS = [name]) && (root[name] = root.$deps[name] = factory.call(root));
else if (('object'===typeof module)&&module.exports) /* CommonJS */
(module.$deps = module.$deps||{}) && (module.exports = module.$deps[name] = factory.call(root));
else if (('function'===typeof define)&&define.amd&&('function'===typeof require)&&('function'===typeof require.specified)&&require.specified(name) /*&& !require.defined(name)*/) /* AMD */
define(name,['module'],function(module) {factory.moduleUri = module.uri; return factory.call(root);});
else if (!(name in root)) /* Browser/WebWorker/.. */
(root[name] = factory.call(root)||1)&&('function'===typeof(define))&&define.amd&&define(function() {return root[name];} );
}(/* current root */ 'undefined' !== typeof self ? self : this,
/* module name */ "Paginator",
/* module factory */ function ModuleFactory__Paginator(undef) {
"use strict";
function Paginator(totalItems, itemsPerPage, currentPage)
{
var self = this;
self.opts = {};
// some defaults
self.option('type', 'list');
self.option('max-pages', 10);
self.option('url-pattern', '?page=(:page)');
self.option('placeholder', '(:page)');
self.option('prev-text', '« Previous');
self.option('next-text', 'Next »');
self.option('ellipsis', '...');
self._totalItems = parseInt(totalItems || 0);
self._itemsPerPage = parseInt(itemsPerPage || 0);
self._currentPage = parseInt(currentPage || 1);
self.computeNumPages();
}
Paginator.VERSION = "1.1.0";
Paginator.prototype = {
constructor: Paginator,
opts: null,
_totalItems: null,
_itemsPerPage: null,
_currentPage: null,
_numPages: null,
option: function(key, val) {
var self = this, nargs = arguments.length;
if (1 == nargs)
{
return Object.prototype.hasOwnProperty.call(self.opts, key) ? self.opts[key] : undef;
}
else if (1 < nargs)
{
self.opts[key] = val;
}
return self;
},
numPages: function() {
return this._numPages;
},
totalItems: function(totalItems) {
var self = this;
if (arguments.length)
{
self._totalItems = parseInt(totalItems);
return self.computeNumPages();
}
else
{
return self._totalItems;
}
},
itemsPerPage: function(itemsPerPage) {
var self = this;
if (arguments.length)
{
self._itemsPerPage = parseInt(itemsPerPage);
return self.computeNumPages();
}
else
{
return self._itemsPerPage;
}
},
currentPage: function(currentPage) {
var self = this;
if ( arguments.length )
{
self._currentPage = parseInt(currentPage);
return self;
}
else
{
return self._currentPage;
}
},
pageUrl: function(pageNum) {
var self = this;
return self.option('url-pattern').split(self.option('placeholder')).join(String(pageNum));
},
prevPage: function() {
var self = this;
return self._currentPage > 1 ? self._currentPage-1 : null;
},
nextPage: function() {
var self = this;
return self._currentPage < self._numPages ? self._currentPage+1 : null;
},
prevUrl: function() {
var self = this;
return self.prevPage() ? self.pageUrl(self.prevPage()) : null;
},
nextUrl: function() {
var self = this;
return self.nextPage() ? self.pageUrl(self.nextPage()) : null;
},
currentPageFirstItem: function() {
var self = this,
first = (self._currentPage - 1) * self._itemsPerPage + 1;
return first > self._totalItems ? null : first;
},
currentPageLastItem: function() {
var self = this,
first = self.currentPageFirstItem(), last;
if (null == first) return null;
last = first + self._itemsPerPage - 1;
return last > self._totalItems ? self._totalItems : last;
},
/**
* Get an array of paginated page data.
*
* Example:
* array(
* object ('num' : 1, 'url' : '/example/page/1', 'isCurrent' : false),
* object ('num' : '...', 'url' : NULL, 'isCurrent' : false),
* object ('num' : 3, 'url' : '/example/page/3', 'isCurrent' : false),
* object ('num' : 4, 'url' : '/example/page/4', 'isCurrent' : true ),
* object ('num' : 5, 'url' : '/example/page/5', 'isCurrent' : false),
* object ('num' : '...', 'url' : NULL, 'isCurrent' : false),
* object ('num' : 10, 'url' : '/example/page/10', 'isCurrent' : false),
* )
*
* @return array
*/
pages: function() {
var self = this,
i, n,
maxPagesToShow,
numAdjacents,
slidingStart,
slidingEnd,
pages = []
;
if (1 >= self._numPages) return pages;
maxPagesToShow = Math.max(3, self.option('max-pages'));
if (self._numPages <= maxPagesToShow)
{
for (i=1,n=self._numPages; i<=n; ++i)
{
pages.push(self.createPage(i, i == self._currentPage));
}
}
else
{
// Determine the sliding range, centered around the current page.
numAdjacents = Math.floor((maxPagesToShow - 3) / 2);
if (self._currentPage + numAdjacents > self._numPages)
{
slidingStart = self._numPages - maxPagesToShow + 2;
}
else
{
slidingStart = self._currentPage - numAdjacents;
}
if (slidingStart < 2) slidingStart = 2;
slidingEnd = slidingStart + maxPagesToShow - 3;
if (slidingEnd >= self._numPages) slidingEnd = self._numPages - 1;
// Build the list of pages.
// first
pages.push(self.createPage(1, 1 == self._currentPage));
// ellipsis ..
if (slidingStart > 2) pages.push(self.createPage(null));
// shown pages
for (i=slidingStart; i<=slidingEnd; ++i)
{
pages.push(self.createPage(i, i == self._currentPage));
}
// ellipsis ..
if (slidingEnd < self._numPages - 1) pages.push(self.createPage(null));
// last
pages.push(self.createPage(self._numPages, self._numPages == self._currentPage));
}
return pages;
},
render: function() {
var self = this, html, pages, i, l, page;
if (1 >= self._numPages) return '';
if ('selectbox' === self.option('type'))
{
html = '<div class="pagination">';
// previous link
if (self.prevUrl())
{
html += '<span class="page-previous"><a href="' + htmlspecialchars(self.prevUrl()) + '">' + self.option('prev-text') + '</a></span>';
}
html += '<select class="page-select">';
// shown pages by number including first and last
for (pages=self.pages(),i=0,l=pages.length; i<l; ++i)
{
page = pages[i];
if (page.url)
{
// actual page with page number
html += '<option value="' + htmlspecialchars(page.url) + '"' + (page.isCurrent ? ' selected' : '') + '>' + String(page.num) + '</option>';
}
else
{
// ellipsis, more
html += '<option disabled>' + String(page.num) + '</option>';
}
}
html += '</select>';
// next link
if (self.nextUrl())
{
html += '<span class="page-next"><a href="' + htmlspecialchars(self.nextUrl()) + '">' + self.option('next-text') + '</a></span>';
}
html += '</div>';
}
else
{
// possibly should be wrapped around <nav></nav> element when used
html = '<ul class="pagination">';
// previous link
if (self.prevUrl())
{
html += '<li class="page-previous"><a href="' + htmlspecialchars(self.prevUrl()) + '">' + self.option('prev-text') + '</a></li>';
}
// shown pages by number including first and last
for (pages=self.pages(),i=0,l=pages.length; i<l; ++i)
{
page = pages[i];
if (page.url)
{
// actual page with page number
html += '<li class="page-item' + (1 == page.num ? ' first' : '') + (self._numPages == page.num ? ' last' : '') + (page.isCurrent ? ' active' : '') + '"><a href="' + htmlspecialchars(page.url) + '">' + String(page.num) + '</a></li>';
}
else
{
// ellipsis, more
html += '<li class="page-item disabled"><span>' + String(page.num) + '</span></li>';
}
}
// next link
if (self.nextUrl())
{
html += '<li class="page-next"><a href="' + htmlspecialchars(self.nextUrl()) + '">' + self.option('next-text') + '</a></li>';
}
html += '</ul>';
}
return html;
},
toString: function() {
return this.render();
},
computeNumPages: function() {
var self = this;
self._numPages = 0 >= self._itemsPerPage || 0 >= self._totalItems ? 0 : Math.ceil(self._totalItems/self._itemsPerPage);
return self;
},
createPage: function(pageNum, isCurrent) {
var self = this;
return null == pageNum ? {
'num' : String(self.option('ellipsis')),
'url' : null,
'isCurrent' : false
} : {
'num' : pageNum,
'url' : self.pageUrl(pageNum),
'isCurrent' : !!isCurrent
};
}
};
var html_esc_re = /[&<>'"]/g;
function htmlspecialchars(s)
{
return String(s).replace(html_esc_re, function(m) {
switch (m)
{
case '&': return '&';
case '<': return '<';
case '>': return '>';
case '"': return '"';
default: return m;
}
});
}
// export it
return Paginator;
});
|