UNPKG

zui

Version:

一个基于 Bootstrap 深度定制开源前端实践方案,帮助你快速构建现代跨屏应用。

376 lines (343 loc) 15.1 kB
/* ======================================================================== * ZUI: pager.js * http://zui.sexy * ======================================================================== * Copyright (c) 2017-2018 cnezsoft.com; Licensed MIT * ======================================================================== */ (function($, undefined) { 'use strict'; var NAME = 'zui.pager'; // model name var DEFAULT_PAGER = { page: 1, // current page index recTotal: 0, // records total count recPerPage: 10, // records count per page }; var LANG = { zh_cn: { pageOfText: '第 {0} 页', prev: '上一页', next: '下一页', first: '第一页', last: '最后一页', goto: '跳转', pageOf: '第 <strong>{page}</strong> 页', totalPage: '共 <strong>{totalPage}</strong> 页', totalCount: '共 <strong>{recTotal}</strong> 项', pageSize: '每页 <strong>{recPerPage}</strong> 项', itemsRange: '第 <strong>{start}</strong> ~ <strong>{end}</strong> 项', pageOfTotal: '第 <strong>{page}</strong>/<strong>{totalPage}</strong> 页' }, zh_tw: { pageOfText: '第 {0} 頁', prev: '上一頁', next: '下一頁', first: '第一頁', last: '最後一頁', goto: '跳轉', pageOf: '第 <strong>{page}</strong> 頁', totalPage: '共 <strong>{totalPage}</strong> 頁', totalCount: '共 <strong>{recTotal}</strong> 項', pageSize: '每頁 <strong>{recPerPage}</strong> 項', itemsRange: '第 <strong>{start}</strong> ~ <strong>{end}</strong> 項', pageOfTotal: '第 <strong>{page}</strong>/<strong>{totalPage}</strong> 頁' }, en: { pageOfText: 'Page {0}', prev: 'Prev', next: 'Next', first: 'First', last: 'Last', goto: 'Goto', pageOf: 'Page <strong>{page}</strong>', totalPage: '<strong>{totalPage}</strong> pages', totalCount: '<strong>{recTotal}</strong> in total', pageSize: '<strong>{recPerPage}</strong> per page', itemsRange: 'From <strong>{start}</strong> to <strong>{end}</strong>', pageOfTotal: 'Page <strong>{page}</strong> of <strong>{totalPage}</strong>' } }; // The pager model class var Pager = function(element, options) { var that = this; that.name = NAME; that.$ = $(element); options = that.options = $.extend({}, Pager.DEFAULTS, this.$.data(), options); var lang = options.lang || $.zui.clientLang(); that.lang = $.isPlainObject(lang) ? ($.extend(true, {}, LANG[lang.lang || $.zui.clientLang()], lang)) : LANG[lang]; that.state = {}; that.set(options.page, options.recTotal, options.recPerPage, true); that.$.on('click', '.pager-goto-btn', function() { var $goto = $(this).closest('.pager-goto'); var page = parseInt($goto.find('.pager-goto-input').val()); if (page !== NaN) { that.set(page); } }).on('click', '.pager-item', function() { var page = $(this).data('page'); if (typeof page === 'number' && page > 0) { that.set(page); } }).on('click', '.pager-size-menu [data-size]', function() { var size = $(this).data('size'); if (typeof size === 'number' && size > 0) { that.set(-1, -1, size); } }); }; Pager.prototype.set = function(page, recTotal, recPerPage, notTiggerChange) { var that = this; if (typeof page === 'object' && page !== null) { recPerPage = page.recPerPage; recTotal = page.recTotal; page = page.page; } var state = that.state; if (!state) { state = $.extend({}, DEFAULT_PAGER); } var oldState = $.extend({}, state); if (typeof recPerPage === 'number' && recPerPage > 0) { state.recPerPage = recPerPage; } if (typeof recTotal === 'number' && recTotal >= 0) { state.recTotal = recTotal; } if (typeof page === 'number' && page >= 0) { state.page = page; } state.totalPage = (state.recTotal && state.recPerPage) ? (Math.ceil(state.recTotal / state.recPerPage)) : 1; state.page = Math.max(0, Math.min(state.page, state.totalPage)); // stateRecCount is items count in current page state.pageRecCount = state.recTotal; if (state.page && state.recTotal) { if (state.page < state.totalPage) { state.pageRecCount = state.recPerPage; } else if (state.page > 1) { state.pageRecCount = state.recTotal - (state.recPerPage * (state.page - 1)); } } state.skip = state.page > 1 ? ((state.page - 1) * state.recPerPage) : 0; state.start = state.skip + 1; state.end = state.skip + state.pageRecCount; state.prev = state.page > 1 ? (state.page - 1) : 0; state.next = state.page < state.totalPage ? (state.page + 1) : 0; that.state = state; if (!notTiggerChange && (oldState.page !== state.page || oldState.recTotal !== state.recTotal || oldState.recPerPage !== state.recPerPage)) { that.$.callComEvent(that, 'onPageChange', [state, oldState]); } return that.render(); }; Pager.prototype.createLinkItem = function(page, text, asAElement) { var that = this; if (text === undefined) { text = page; } var $ele = $('<a title="' + that.lang.pageOfText.format(page) + '" class="pager-item" data-page="' + page + '"/>').attr('href', page ? that.createLink(page, that.state) : '###').html(text); if (!asAElement) { $ele = $('<li />').append($ele).toggleClass('active', page === that.state.page).toggleClass('disabled', !page || page === that.state.page); } return $ele; }; Pager.prototype.createNavItems = function(maxCount) { var that = this; var $nav = that.$; var pager = that.state; var totalPage = pager.totalPage; var page = pager.page; var appendItem = function(p, to) { if(p === false) { $nav.append(that.createLinkItem(0, to || that.options.navEllipsisItem)); return; } if(to === undefined) to = p; for(var i = p; i <= to; ++i) { $nav.append(that.createLinkItem(i)); } }; if (maxCount === undefined) { maxCount = that.options.maxNavCount || 10; } appendItem(1); if(totalPage > 1) { if(totalPage <= maxCount) { appendItem(2, totalPage); } else if(page < (maxCount - 2)) { appendItem(2, maxCount - 2); appendItem(false); appendItem(totalPage); } else if(page > (totalPage - maxCount + 2)) { appendItem(false); appendItem((totalPage - maxCount + 2), totalPage); } else { appendItem(false); appendItem(page - Math.ceil((maxCount-4)/2), page + Math.floor((maxCount-4)/2)); appendItem(false); appendItem(totalPage); } } }; Pager.prototype.createGoto = function() { var that = this; var pager = this.state; var $goto = $('<div class="input-group pager-goto" style="width: ' + (35 + (pager.page + '').length * 9 + 25 + that.lang.goto.length*12) + 'px"><input value="' + pager.page + '" type="number" min="1" max="' + pager.totalPage + '" placeholder="' + pager.page + '" class="form-control pager-goto-input"><span class="input-group-btn"><button class="btn pager-goto-btn" type="button">' + that.lang.goto + '</button></span></div>'); return $goto; }; Pager.prototype.createSizeMenu = function() { var that = this; var pager = this.state; var $menu = $('<ul class="dropdown-menu"></ul>'); var options = that.options.pageSizeOptions; if (typeof options === 'string') { options = options.split(','); } for (var i = 0; i < options.length; ++i) { var size = options[i]; if (typeof size === 'string') { size = parseInt(size); } var $li = $('<li><a href="###" data-size="' + size + '">' + size + '</a></li>').toggleClass('active', size === pager.recPerPage); $menu.append($li); } return $('<div class="btn-group pager-size-menu"><button type="button" class="btn dropdown-toggle" data-toggle="dropdown">' + that.lang.pageSize.format(pager) + ' <span class="caret"></span></button></div>').addClass(that.options.menuDirection).append($menu); }; Pager.prototype.createElement = function(element, $pager, pager) { var that = this; var createLinkItem= $.proxy(that.createLinkItem, that); var lang = that.lang; switch (element) { case 'prev': return createLinkItem(pager.prev, lang.prev); case 'prev_icon': return createLinkItem(pager.prev, '<i class="icon ' + that.options.prevIcon + '"></i>'); case 'next': return createLinkItem(pager.next, lang.next); case 'next_icon': return createLinkItem(pager.next, '<i class="icon ' + that.options.nextIcon + '"></i>'); case 'first': return createLinkItem(1, lang.first); case 'first_icon': return createLinkItem(1, '<i class="icon ' + that.options.firstIcon + '"></i>'); case 'last': return createLinkItem(pager.totalPage, lang.last); case 'last_icon': return createLinkItem(pager.totalPage, '<i class="icon ' + that.options.lastIcon + '"></i>'); case 'space': case '|': return $('<li class="space" />'); case 'nav': case 'pages': that.createNavItems(); return; case 'total_text': return $(('<div class="pager-label">' + lang.totalCount + '</div>').format(pager)); case 'page_text': return $(('<div class="pager-label">' + lang.pageOf + '</div>').format(pager)); case 'total_page_text': return $(('<div class="pager-label">' + lang.totalPage + '</div>').format(pager)); case 'page_of_total_text': return $(('<div class="pager-label">' + lang.pageOfTotal + '</div>').format(pager)); case 'page_size_text': return $(('<div class="pager-label">' + lang.pageSize + '</div>').format(pager)); case 'items_range_text': return $(('<div class="pager-label">' + lang.itemsRange + '</div>').format(pager)); case 'goto': return that.createGoto(); case 'size_menu': return that.createSizeMenu(); default: return $('<li/>').html(element.format(pager)); } }; Pager.prototype.createLink = function(page, pager) { if (page === undefined) { page = this.state.page; } if (pager === undefined) { pager = this.state; } var linkCreator = this.options.linkCreator; if (typeof linkCreator === 'string') { return linkCreator.format($.extend({}, pager, {page: page})); } else if ($.isFunction(linkCreator)) { return linkCreator(page, pager); } return '#page=' + page; }; Pager.prototype.render = function(elements) { var that = this; var state = that.state; var createElement = that.options.elementCreator || that.createElement; var isMapperCreator = $.isPlainObject(createElement); elements = elements || that.elements || that.options.elements; if (typeof elements == 'string') { elements = elements.split(','); } that.elements = elements; that.$.empty(); for(var i = 0; i < elements.length; ++i) { var element = $.trim(elements[i]); var creator = isMapperCreator ? (createElement[element] || createElement) : createElement; var $element = creator.call(that, element, that.$, state); if ($element === false) { $element = that.createElement(element, that.$, state); } if ($element instanceof $) { if ($element[0].tagName !== 'LI') { $element = $('<li/>').append($element); } that.$.append($element); } } // Fix page item border var $lastItem = null; that.$.children('li').each(function() { var $li = $(this); var isItem = !!$li.children('.pager-item').length; if ($lastItem) { $lastItem.toggleClass('pager-item-right', !isItem); } else { if (isItem) { $li.addClass('pager-item-left'); } } $lastItem = isItem ? $li : null; }); if ($lastItem) { $lastItem.addClass('pager-item-right'); } that.$.callComEvent(that, 'onRender', [state]); return that; }; // default options Pager.DEFAULTS = $.extend({ elements: ['first_icon', 'prev_icon', 'pages', 'next_icon', 'last_icon', 'page_of_total_text', 'items_range_text', 'total_text'], prevIcon: 'icon-double-angle-left', nextIcon: 'icon-double-angle-right', firstIcon: 'icon-step-backward', lastIcon: 'icon-step-forward', navEllipsisItem: '<i class="icon icon-ellipsis-h"></i>', maxNavCount: 10, menuDirection: 'dropdown', // or dropup pageSizeOptions: [10, 20, 30, 50, 100], // onPageChange: null }, DEFAULT_PAGER); // Extense jquery element $.fn.pager = function(option) { return this.each(function() { var $this = $(this); var data = $this.data(NAME); var options = typeof option == 'object' && option; if(!data) $this.data(NAME, (data = new Pager(this, options))); if(typeof option == 'string') data[option](); }); }; Pager.NAME = NAME; $.fn.pager.Constructor = Pager; // Auto call pager after document load complete $(function() { $('[data-ride="pager"]').pager(); }); }(jQuery, undefined));