UNPKG

lu2

Version:

Simple and flexible UI component library based on native HTML and JavaScript

271 lines (226 loc) 9.08 kB
/** * @Pagination.js * @author zhangxinxu * @version * @Created: 15-06-26 */ (function (global, factory) { if (typeof define === 'function' && (define.amd || define.cmd)) { define(factory); } else { global.Pagination = factory(); } }(this, function () { /** * 分页组件 * 支持jQuery包装器调用以及new实例构造 * eg $().pagination(options); new Pagination($(), options); **/ $.fn.pagination = function(options) { return $(this).each(function() { if (!$(this).data('pagination')) { $(this).data('pagination', new Pagination($(this), options)); } }); }; /** * 分页实例方法 * @param {Object} container 显示分页的容器元素 * @param {Object} options 可选参数 */ var Pagination = function(container, options) { container = container || $(); options = options || {}; var page = this; // 默认参数 var defaults = { // 总的数据量 length: 0, // 当前的页码 current: 1, // 每页显示的数目 every: 15, // short 长分页还是短分页 mode: 'long', onClick: $.noop }; var params = $.extend({}, defaults, options); var el = {}; this.el = el; // 存储元素 el.container = container; // 存储数据 var num = {}; this.num = num; // 存储总数据量 num.length = params.length; // 存储当前的页码 num.current = params.current; // 存储每页的条目个数 num.every = params.every; // 分页类别 this.mode = params.mode; this.href = params.href; // 给容器委托点击事件 container.delegate('a', 'click', function(event) { var current = $(this).attr('data-page'); page.num.current = current * 1; var className = this.className; var elClicked; // 分页刷新 page.show(); // 点击回调 if (/prev/.test(className)) { elClicked = container.find('.ui-page-prev'); } else if (/next/.test(className)) { elClicked = container.find('.ui-page-next'); } else { elClicked = container.find('.ui-page-current'); } // 由于HTML刷新,重新获取点击的元素 var eleClicked = elClicked[0]; // aria以及键盘访问 if (eleClicked) { eleClicked.focus(); if (window.isKeyEvent === false) { eleClicked.blur(); } } params.onClick.call(eleClicked, page, current); if (/^javascript/.test(this.href)) { event.preventDefault(); } }); this.show(); return this; }; // IE9+ 前后分页图标使用内联SVG, 以便支持retina屏幕 var svg = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"><path d="M85.876,100.5l49.537-50.526c4.089-4.215,4.089-11.049,0-15.262 c-4.089-4.218-10.719-4.218-14.808,0L63.586,92.868c-4.089,4.215-4.089,11.049,0,15.264l57.018,58.156 c4.089,4.215,10.719,4.215,14.808,0c4.089-4.215,4.089-11.049,0-15.262L85.876,100.5z"/></svg>'; /** * 创建分页字符串的方法 * @param {Object} num 分页相关的数据对象 * @param {String} mode 分页的类型 * @return {String} 返回拼接好的HTML字符串 */ Pagination.prototype.create = function(num, mode) { num = num || {}; var length = num.length || 0; var current = num.current || 1; var every = num.every || 1; mode = mode || 'long'; // a标签的href地址 var href = this.href || 'javascript:'; // 获得href的方法 var fnHref = function(index) { if (typeof href == 'string') { return href; } else if (typeof href == 'function') { return href(index); } }; // ui类名 var CL = 'ui-page'; var prefixPage = CL + '-'; // 计算总页数 var total = Math.ceil(length / every) || 1; var html = ''; // 一些类名 var clPrev = [CL, prefixPage + 'prev'].join(' '); var clNext = [CL, prefixPage + 'next'].join(' '); var clEll = [CL, prefixPage + 'ellipsis'].join(' '); var clText = [CL, prefixPage + 'text'].join(' '); var clCurrent = [CL, prefixPage + 'current'].join(' '); // 1. 首先是通用的前后翻页 if (current > 1) { html = html + '<a href="' + fnHref(current - 1) + '" class="' + clPrev + '" data-page="' + (current - 1) + '" aria-label="上一页,当前第' + current + '页">' + svg + '</a>'; } else { // 当前是第一页,自然不能往前翻页 html = html + '<span class="' + clPrev + '">' + svg + '</span>'; } // 2. 中间部分 // 短分页和长分页 var visible = 6; if (mode == 'long') { var long = function(start) { if (start == current) { html = html + '<span class="' + clCurrent + '" aria-label="第' + start + '页,共' + total + '页" aria-selected="true" role="option">' + start + '</span>'; } else { html = html + '<a href="' + fnHref(start) + '" class="' + CL + '" data-page="' + start + '" aria-label="第' + start + '页,共' + total + '页">' + start + '</a>'; } }; /** * 为了保证体验,在分页数量大的时候,要保证总条目数为7个 假设页码总数20,规则如下 当前是1: 则 1-5,... 20 2: 则 1-5,...,20 3: 则 1-5,...,20 4: 则 1-5,...,20 5: 则 1...456,...,20 ... 参见下面的else if的处理 */ if (total <= visible) { // 如果页面不大于6个,全部显示 for (var start = 1; start <= total; start++) { long(start); } } else if (current < total * 0.5 && current < visible - 1) { // 至少保证current的前后有数据 if (current < visible - 1) { for (start = 1; start < visible; start++) { long(start); } } html = html + '<span class="' + clEll + '">...</span>'; long(total); } else if (current > total * 0.5 && current > total - visible + 2) { long(1); html = html + '<span class="' + clEll + '">...</span>'; for (start = total - visible + 2; start <= total; start++) { long(start); } } else { // 前后两处打点 long(1); html = html + '<span class="' + clEll + '">...</span>'; long(current - 1); long(current); long(current + 1); html = html + '<span class="' + clEll + '">...</span>'; long(total); } } else if (mode == 'short') { html = html + '<span class="' + clText + '" aria-label="第' + current + '页,共' + total + '页" role="option">' + [current, total].join('/') + '</span>'; } // 3. 往后翻页 if (current < total) { html = html + '<a href="' + fnHref(current + 1) + '" class="' + clNext + '" data-page="' + (current + 1) + '" aria-label="下一页,当前第' + current + '页">' + svg + '</a>'; } else { html = html + '<span class="' + clNext + '">' + svg + '</span>'; } return '<div class="' + prefixPage + 'x">' + html + '</div>'; }; /** * 分页显示(也是刷新方法) * @return {Object} 返回当前实例 */ Pagination.prototype.show = function() { // 数据合法性处理 var num = this.num; num.length = Math.max(num.length, 0); num.every = Math.max(num.every, 1); // current合法性处理 var maxCurrent = Math.ceil(num.length / num.every); if (num.current > maxCurrent) { num.current = maxCurrent; } num.current = Math.max(num.current, 1); if (this.el && this.el.container && this.el.container.length) { // 分页刷新 this.el.container.html(this.create(num, this.mode)); } return this; }; return Pagination; }));