/*!
* Mricode Pagination Plugin
* Github: https://github.com/mricle/Mricode.Pagination
* Version: 1.4.4
*
* Required jQuery
*
* Copyright 2016 Mricle
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node / CommonJS
factory(require('jquery'));
} else {
// Globals
factory(jQuery);
}
})(function ($) {
"use strict";
var Page = function (element, options) {
var defaultOption = {
pageIndex: 0,
pageSize: 10,
total: 0,
pageBtnCount: 11,
showFirstLastBtn: true,
firstBtnText: null,
lastBtnText: null,
prevBtnText: "«",
nextBtnText: "»",
loadFirstPage: true,
remote: {
url: null,
params: null,
pageParams: null,
success: null,
beforeSend: null,
complete: null,
pageIndexName: 'pageIndex',
pageSizeName: 'pageSize',
totalName: 'total',
traditional: false
},
pageElementSort: ['$page', '$size', '$jump', '$info'],
showInfo: false,
infoFormat: '{start} ~ {end} of {total} entires',
noInfoText: '0 entires',
showJump: false,
jumpBtnText: 'Go',
showPageSizes: false,
pageSizeItems: [5, 10, 15, 20],
debug: false
}
this.$element = $(element);
this.$page = $('
').hide();
this.$size = $('').hide();
this.$jump = $('').hide();
this.$info = $('').hide();
this.options = $.extend(true, {}, defaultOption, $.fn.pagination.defaults, options);
if (options.pageElementSort) {
this.options.pageElementSort = options.pageElementSort
} else {
if ($.fn.pagination.defaults && $.fn.pagination.defaults.pageElementSort) {
this.options.pageElementSort = $.fn.pagination.defaults.pageElementSort;
} else {
this.options.pageElementSort = defaultOption.pageElementSort;
}
}
this.options.pageSizeItems = options.pageSizeItems || (($.fn.pagination.defaults && $.fn.pagination.defaults.pageSizeItems) ? $.fn.pagination.defaults.pageSizeItems : defaultOption.pageSizeItems);
this.total = this.options.total;
this.currentUrl = this.options.remote.url;
this.currentPageIndex = utility.convertInt(this.options.pageIndex);
this.currentPageSize = utility.convertInt(this.options.pageSize);
this.currentParams = utility.deserializeParams(this.options.remote.params) || {};
this.getLastPageNum = function () {
return pagination.core.calLastPageNum(this.total, this.currentPageSize);
}
if (this.options.remote.success === null) {
this.options.remote.success = this.options.remote.callback;
}
this.init();
}
Page.prototype = {
getPageIndex: function () {
return this.currentPageIndex;
},
getPageSize: function () {
return this.currentPageSize;
},
getParams: function () {
return this.currentParams;
},
setPageIndex: function (pageIndex) {
if (pageIndex !== undefined && pageIndex !== null) {
this.currentPageIndex = utility.convertInt(pageIndex);
}
},
setPageSize: function (pageSize) {
if (pageSize !== undefined && pageSize !== null) {
this.currentPageSize = utility.convertInt(pageSize);
}
},
setRemoteUrl: function (url) {
if (url) {
this.currentUrl = url;
}
},
setParams: function (params) {
if (params) {
this.currentParams = utility.deserializeParams(params);
}
},
render: function (total) {
if (total !== undefined && total !== null) {
this.total = utility.convertInt(total);
}
this.renderPagination();
this.debug('pagination rendered');
},
init: function () {
this.initHtml();
this.initEvent();
if (this.currentUrl && this.options.loadFirstPage) {
this.remote();
} else {
this.renderPagination();
}
this.debug('pagination inited');
},
initHtml: function () {
//init size module
var sizeHtml = $('');
for (var i = 0; i < this.options.pageSizeItems.length; i++) {
sizeHtml.append('')
}
sizeHtml.val(this.currentPageSize);
this.$size.append(sizeHtml);
//init jump module
var jumpHtml = '';
this.$jump.append(jumpHtml);
for (var i = 0; i < this.options.pageElementSort.length; i++) {
this.$element.append(this[this.options.pageElementSort[i]]);
}
},
initEvent: function () {
this.$element
.on('click', { page: this }, function (event) {
if ($(event.target).is('button')) {
if ($(event.target).data('pageBtn') == 'jump') {
var $input = event.data.page.$element.find('input[data-page-btn=jump]');
event.data.page.jumpEventHandler($input.val(), event);
}
} else {
if ($(event.target).data('pageIndex') !== undefined)
eventHandler.call(event.data.page, event);
}
}).on('change', { page: this }, function (event) {
var $this = $(event.target);
if ($this.data('pageBtn') == 'jump') {
event.data.page.jumpEventHandler($this.val(), event);
}
if ($this.data('pageBtn') == 'size') {
eventHandler.call(event.data.page, event);
}
}).on('keypress', { page: this }, function (event) {
if (event.keyCode == "13") {
var $input = event.data.page.$element.find('input[data-page-btn=jump]')
event.data.page.jumpEventHandler($input.val(), event);
}
});
this.$element.find('input[data-page-btn=jump]').on('blur', {
page: this
}, function(event){
event.stopPropagation();
var pageIndex = $(this).val();
event.data.page.jumpEventHandler($(this).val(), event);
$(this).val(pageIndex)
})
},
jumpEventHandler: function (inputValue, event) {
if (!inputValue) {
this.$jump.removeClass('error');
} else if (!pagination.check.checkJumpPage(inputValue)) {
this.$jump.addClass('error');
}
else if (utility.convertInt(inputValue) > this.getLastPageNum()) {
this.$jump.addClass('error');
}
else {
this.$jump.removeClass('error');
eventHandler.call(this, event);
}
},
doPagination: function () {
if (this.currentUrl) {
this.remote();
} else {
this.renderPagination();
}
},
remote: function () {
if (typeof this.options.remote.pageParams === 'function') {
var pageParams = this.options.remote.pageParams.call(this, { pageIndex: this.currentPageIndex, pageSize: this.currentPageSize });
this.currentParams = $.extend({}, this.currentParams, pageParams);
} else {
this.currentParams[this.options.remote.pageIndexName] = this.currentPageIndex;
this.currentParams[this.options.remote.pageSizeName] = this.currentPageSize;
}
pagination.remote.getAjax(this, this.currentUrl, this.currentParams, this.ajaxCallBack, this.options.remote.beforeSend, this.options.remote.complete,this.options.remote.traditional);
},
ajaxCallBack: function (result) {
var total = utility.mapObjectNameRecursion(result, this.options.remote.totalName);
if (total == null || total == undefined)
throw new Error("the response of totalName : '" + this.options.remote.totalName + "' not found.");
total = utility.convertInt(total);
this.total = total;
var lastPageNum = this.getLastPageNum();
if (this.currentPageIndex > 0 && lastPageNum - 1 < this.currentPageIndex) {
this.setPageIndex(lastPageNum - 1);
this.remote();
} else {
if (typeof this.options.remote.success === 'function') this.options.remote.success(result);
this.renderPagination();
}
},
onEvent: function (eventName, pageIndex, pageSize) {
if (pageIndex != null) this.currentPageIndex = utility.convertInt(pageIndex);
if (pageSize != null) this.currentPageSize = utility.convertInt(pageSize);
this.doPagination();
this.$element.trigger(eventName, {
pageIndex: this.currentPageIndex, pageSize: this.currentPageSize
});
this.debug('pagination ' + eventName);
},
//生成分页
renderPagination: function () {
var option = {
showFirstLastBtn: this.options.showFirstLastBtn,
firstBtnText: this.options.firstBtnText,
prevBtnText: this.options.prevBtnText,
nextBtnText: this.options.nextBtnText,
lastBtnText: this.options.lastBtnText
}
var lastPageNum = this.getLastPageNum();
this.currentPageIndex = lastPageNum > 0 && this.currentPageIndex > lastPageNum - 1 ? lastPageNum - 1 : this.currentPageIndex;
this.$page.empty().append(pagination.core.renderPages(this.currentPageIndex, this.currentPageSize, this.total, this.options.pageBtnCount, option)).show();
if (this.options.showPageSizes && lastPageNum !== 0) this.$size.show(); else this.$size.hide();
if (this.options.showJump && lastPageNum !== 0) this.$jump.show(); else this.$jump.hide();
this.$info.text(pagination.core.renderInfo(this.currentPageIndex, this.currentPageSize, this.total, this.options.infoFormat, this.options.noInfoText));
if (this.options.showInfo) this.$info.show(); else this.$info.hide();
},
//销毁分页
destroy: function () {
this.$element.unbind().data("pagination", null).empty();
this.debug('pagination destroyed');
},
debug: function (message, data) {
if (this.options.debug && console) {
message && console.info(message + ' : pageIndex = ' + this.currentPageIndex + ' , pageSize = ' + this.currentPageSize + ' , total = ' + this.total);
data && console.info(data);
}
}
}
var eventHandler = function (event) {
var that = event.data.page;
var $target = $(event.target);
if (event.type === 'click' && $target.data('pageIndex') !== undefined && !$target.parent().hasClass('active')) {
that.onEvent(pagination.event.pageClicked, $target.data("pageIndex"), null);
}
else if ((event.type === 'click' || event.type === 'keypress') && $target.data('pageBtn') === 'jump') {
var pageIndexStr = that.$jump.find('input').val();
if (utility.convertInt(pageIndexStr) <= that.getLastPageNum()) {
that.onEvent(pagination.event.jumpClicked, pageIndexStr - 1, null);
that.$jump.find('input').val(null);
}
}
else if (event.type === 'change' && $target.data('pageBtn') === 'size') {
var newPageSize = that.$size.find('select').val();
var lastPageNum = pagination.core.calLastPageNum(that.total, newPageSize);
if (lastPageNum > 0 && that.currentPageIndex > lastPageNum - 1) {
that.currentPageIndex = lastPageNum - 1;
}
that.onEvent(pagination.event.pageSizeChanged, that.currentPageIndex, newPageSize);
} else if (event.type === 'blur'){
var pageIndexStr = that.$jump.find('input').val();
if (utility.convertInt(pageIndexStr) <= that.getLastPageNum()) {
that.onEvent(pagination.event.jumpClicked, pageIndexStr - 1, null);
that.$jump.find('input').val(null);
}
}
};
var pagination = {};
pagination.event = {
pageClicked: 'pageClicked',
jumpClicked: 'jumpClicked',
pageSizeChanged: 'pageSizeChanged'
};
pagination.remote = {
getAjax: function (pagination, url, data, success, beforeSend, complate,traditional) {
$.ajax({
url: url,
dataType: 'json',
data: data,
cache: false,
traditional:traditional,
contentType: 'application/Json',
beforeSend: function (XMLHttpRequest) {
if (typeof beforeSend === 'function') beforeSend.call(this, XMLHttpRequest);
},
complete: function (XMLHttpRequest, textStatue) {
if (typeof complate === 'function') complate.call(this, XMLHttpRequest, textStatue);
},
success: function (result) {
success.call(pagination, result);
}
})
}
};
pagination.core = {
/*
options : {
showFirstLastBtn
firstBtnText:
}
*/
renderPages: function (pageIndex, pageSize, total, pageBtnCount, options) {
options = options || {};
var pageNumber = pageIndex + 1;
var lastPageNumber = this.calLastPageNum(total, pageSize);
var html = [];
if (lastPageNumber <= pageBtnCount) {
html = this.renderGroupPages(1, lastPageNumber, pageNumber);
}
else {
var firstPage = this.renderPerPage(options.firstBtnText || 1, 0);
var lastPage = this.renderPerPage(options.lastBtnText || lastPageNumber, lastPageNumber - 1);
//button count of both sides
var symmetryBtnCount = (pageBtnCount - 1 - 4) / 2;
if (!options.showFirstLastBtn)
symmetryBtnCount = symmetryBtnCount + 1;
var frontBtnNum = (pageBtnCount + 1) / 2;
var behindBtnNum = lastPageNumber - ((pageBtnCount + 1) / 2);
var prevPage = this.renderPerPage(options.prevBtnText, pageIndex - 1);
var nextPage = this.renderPerPage(options.nextBtnText, pageIndex + 1);
symmetryBtnCount = symmetryBtnCount.toString().indexOf('.') == -1 ? symmetryBtnCount : symmetryBtnCount + 0.5;
frontBtnNum = frontBtnNum.toString().indexOf('.') == -1 ? frontBtnNum : frontBtnNum + 0.5;
behindBtnNum = behindBtnNum.toString().indexOf('.') == -1 ? behindBtnNum : behindBtnNum + 0.5;
if (pageNumber < frontBtnNum) {
if (options.showFirstLastBtn) {
html = this.renderGroupPages(1, pageBtnCount - 2, pageNumber);
html.push(nextPage);
html.push(lastPage);
} else {
html = this.renderGroupPages(1, pageBtnCount - 1, pageNumber);
html.push(nextPage);
}
}
else if (pageNumber > behindBtnNum) {
if (options.showFirstLastBtn) {
html = this.renderGroupPages(lastPageNumber - pageBtnCount + 3, pageBtnCount - 2, pageNumber);
html.unshift(prevPage);
html.unshift(firstPage);
} else {
html = this.renderGroupPages(lastPageNumber - pageBtnCount + 2, pageBtnCount - 1, pageNumber);
html.unshift(prevPage);
}
}
else {
if (options.showFirstLastBtn) {
html = this.renderGroupPages(pageNumber - symmetryBtnCount, pageBtnCount - 4, pageNumber);
html.unshift(prevPage);
html.push(nextPage);
html.unshift(firstPage);
html.push(lastPage);
} else {
html = this.renderGroupPages(pageNumber - symmetryBtnCount, pageBtnCount - 2, pageNumber);
html.unshift(prevPage);
html.push(nextPage);
}
}
}
return html;
},
renderGroupPages: function (beginPageNum, count, currentPage) {
var html = [];
for (var i = 0; i < count; i++) {
var page = this.renderPerPage(beginPageNum, beginPageNum - 1);
if (beginPageNum === currentPage)
page.addClass("active");
html.push(page);
beginPageNum++;
}
return html;
},
renderPerPage: function (text, value) {
return $("" + text + "");
},
renderInfo: function (currentPageIndex, currentPageSize, total, infoFormat, noInfoText) {
if (total <= 0) {
return noInfoText;
} else {
var startNum = (currentPageIndex * currentPageSize) + 1;
var endNum = (currentPageIndex + 1) * currentPageSize;
endNum = endNum >= total ? total : endNum;
return infoFormat.replace('{start}', startNum).replace('{end}', endNum).replace('{total}', total);
}
},
//计算最大分页数
calLastPageNum: function (total, pageSize) {
total = utility.convertInt(total);
pageSize = utility.convertInt(pageSize);
var i = total / pageSize;
return utility.isDecimal(i) ? parseInt(i) + 1 : i;
}
};
pagination.check = {
//校验跳转页数有效性
checkJumpPage: function (pageIndex) {
var reg = /^\+?[1-9][0-9]*$/;
return reg.test(pageIndex);
}
};
var utility = {
//转换为int
convertInt: function (i) {
if (typeof i === 'number') {
return i;
} else {
var j = parseInt(i);
if (!isNaN(j)) {
return j;
} else {
throw new Error("convertInt Type Error. Type is " + typeof i + ', value = ' + i);
}
}
},
//返回是否小数
isDecimal: function (i) {
return parseInt(i) !== i;
},
//匹配对象名称(递归)
mapObjectNameRecursion: function (object, name) {
var obj = object;
var arr = name.split('.');
for (var i = 0; i < arr.length; i++) {
obj = utility.mapObjectName(obj, arr[i]);
}
return obj;
},
//匹配对象名称
mapObjectName: function (object, name) {
var value = null;
for (var i in object) {
//过滤原型属性
if (object.hasOwnProperty(i)) {
if (i == name) {
value = object[i];
break;
}
}
}
return value;
},
deserializeParams: function (params) {
var newParams = {};
if (typeof params === 'string') {
var arr = params.split('&');
for (var i = 0; i < arr.length; i++) {
var a = arr[i].split('=');
newParams[a[0]] = decodeURIComponent(a[1]);
}
}
else if (params instanceof Array) {
for (var i = 0; i < params.length; i++) {
newParams[params[i].name] = decodeURIComponent(params[i].value);
}
}
else if (typeof params === 'object') {
newParams = params;
}
return newParams;
}
}
$.fn.pagination = function (option) {
if (typeof option === 'undefined') {
return $(this).data('pagination') || false;
} else {
var result;
var args = arguments;
this.each(function () {
var $this = $(this);
var data = $this.data('pagination');
if (!data && typeof option === 'string') {
throw new Error('MricodePagination is uninitialized.');
}
else if (data && typeof option === 'object') {
throw new Error('MricodePagination is initialized.');
}
//初始化
else if (!data && typeof option === 'object') {
var options = typeof option == 'object' && option;
var data_api_options = $this.data();
options = $.extend(options, data_api_options);
$this.data('pagination', (data = new Page(this, options)));
}
else if (data && typeof option === 'string') {
result = data[option].apply(data, Array.prototype.slice.call(args, 1));
}
});
return typeof result === 'undefined' ? this : result;
}
}
});