JS分页条插件
目标
制作js分页导航jq插件,用于无刷新分页或者刷新分页
实现目标参考京东和天猫的分页条.
有四个固定按钮,前页码,后页码,首页,末页.
程序关键点在于计算中间页面的起止位置.逻辑是以当前页码为参照点,根据需要显示的页码按钮个数,计算参照点前后的页码数量.
当起止点小于1或者大于最大页码时,需要调整起点为1,或止点为最大页码.
效果图
html结构
容器nav,里面分为页码区(pagenum-btns)和跳转区(pagenum-skip)两部分.
js生成nav里面的内容.
<nav class="pagenum" id="pagenum1"> <span class="pagenum-btns"> <a class="pagenum-prev"><</a> <a class="pagenum-num">1</a> <span class="pagenum-break">...</span> <a class="pagenum-num">7</a> <a class="pagenum-num">8</a> <a class="pagenum-active">9</a> <a class="pagenum-num">10</a> <a class="pagenum-num">11</a> <span class="pagenum-break">...</span> <a class="pagenum-num">98</a> <a class="pagenum-next">></a> </span> <span class="pagenum-skip"> 共<b class="pagenum-total">98</b>页 到第<input class="pagenum-input" value="1" type="text" />页<a class="pagenum-ok">确定</a> </span> </nav>
调用
// dom结构 需要一个容器
// 将相应样式添加到容器可调整外观.大小: sm lg xl 颜色: gray red green yellow 位置:center right
<nav class="pagenum" id="pagenumId"></nav> // 调用方法 let cfg={ // 点击页码方法(必须) pageClickE:function(){}, // 总数(必须) >0 totalData:100, // 当前页码(必须) >0 pageIndex:'当前页码', // 每页数量 [5-50] pageSize:10, // 显示几个按钮[5-10] totalBtn:5 } $('#pagenumId').pagenum(cfg);
web前端一般是无刷新分页,pageClickE方法会包含一个ajax请求,这个请求的回调方法里,再执行生成新的分页条,并且配置参数中的pageClickE,再次指向ajax方法自己
// ajax请求示例方法 function getdata() { var para = {}; $.post('/api/PageNumber', { para:JSON.stringify(para) }, function (data) { if (data.length == 0) { // 如果没有数据返回,可以不用生成分页条. return; } // 再生成新分页条 let cfg= { // 这里绑定getdata方法自己 pageClickE:function(){ getdata() }, // 总数(必须) >0 由后端返回新的总数 totalData:data.总数, // 当前页码(必须) >0 由后端返回当前页码,或者页面记住当前请求页面 pageIndex:data.当前页码, // 每页数量 [5-50] pageSize:10, // 显示几个按钮[5-10] totalBtn:5 } $('#pagenumId').pagenum(cfg); }
.pagenum { height: 2.7em; line-height: 2.7em; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .pagenum-btns { font-size: 0; } .pagenum-prev, .pagenum-num, .pagenum-active, .pagenum-next, .pagenum-break { display: inline-block; width: 2.7em; text-align: center; font-size: 14px; color: #007bff; border: 1px solid #ced4da; border-left: none; } .pagenum-prev:hover, .pagenum-num:hover, .pagenum-active:hover, .pagenum-next:hover { text-decoration: none; cursor: pointer; color: #007bff; background-color: #e9ecef; } .pagenum-prev { border-left: 1px solid #ced4da; } .pagenum-active, .pagenum-active:hover { color: #fff; background-color: #007bff; } .pagenum-break { color: #ced4da; } .pagenum-skip { margin-left: 5px; } .pagenum-input { width: 2.7em; text-align: center; border: 1px solid #ced4da; padding: 0; margin: 0 3px; } .pagenum-input:focus { outline: 2px solid #007bff; } .pagenum-ok { display: inline-block; width: 3em; text-align: center; margin-left: 5px; color: #007bff; border: 1px solid #ced4da; } .pagenum-ok:hover { text-decoration: none; color: #007bff; cursor: pointer; } .pagenum.sm { font-size: 12px; } .pagenum.sm .pagenum-prev, .pagenum.sm .pagenum-num, .pagenum.sm .pagenum-active, .pagenum.sm .pagenum-next, .pagenum.sm .pagenum-break { font-size: 12px; } .pagenum.lg { font-size: 16px; } .pagenum.lg .pagenum-prev, .pagenum.lg .pagenum-num, .pagenum.lg .pagenum-active, .pagenum.lg .pagenum-next, .pagenum.lg .pagenum-break { font-size: 16px; } .pagenum.xl { font-size: 20px; } .pagenum.xl .pagenum-prev, .pagenum.xl .pagenum-num, .pagenum.xl .pagenum-active, .pagenum.xl .pagenum-next, .pagenum.xl .pagenum-break { font-size: 20px; } .pagenum.gray .pagenum-prev, .pagenum.gray .pagenum-num, .pagenum.gray .pagenum-active, .pagenum.gray .pagenum-next, .pagenum.gray .pagenum-break, .pagenum.gray .pagenum-prev:hover, .pagenum.gray .pagenum-num:hover, .pagenum.gray .pagenum-active:hover, .pagenum.gray .pagenum-next:hover, .pagenum.gray .pagenum-ok, .pagenum.gray .pagenum-ok:hover { color: #6c757d; } .pagenum.gray .pagenum-active, .pagenum.gray .pagenum-active:hover { color: #fff; background-color: #6c757d; } .pagenum.green .pagenum-prev, .pagenum.green .pagenum-num, .pagenum.green .pagenum-active, .pagenum.green .pagenum-next, .pagenum.green .pagenum-break, .pagenum.green .pagenum-prev:hover, .pagenum.green .pagenum-num:hover, .pagenum.green .pagenum-active:hover, .pagenum.green .pagenum-next:hover, .pagenum.green .pagenum-ok, .pagenum.green .pagenum-ok:hover { color: #28a745; } .pagenum.green .pagenum-active, .pagenum.green .pagenum-active:hover { color: #fff; background-color: #28a745; } .pagenum.red .pagenum-prev, .pagenum.red .pagenum-num, .pagenum.red .pagenum-active, .pagenum.red .pagenum-next, .pagenum.red .pagenum-break, .pagenum.red .pagenum-prev:hover, .pagenum.red .pagenum-num:hover, .pagenum.red .pagenum-active:hover, .pagenum.red .pagenum-next:hover, .pagenum.red .pagenum-ok, .pagenum.red .pagenum-ok:hover { color: #dc3545; } .pagenum.red .pagenum-active, .pagenum.red .pagenum-active:hover { color: #fff; background-color: #dc3545; } .pagenum.yellow .pagenum-prev, .pagenum.yellow .pagenum-num, .pagenum.yellow .pagenum-active, .pagenum.yellow .pagenum-next, .pagenum.yellow .pagenum-break, .pagenum.yellow .pagenum-prev:hover, .pagenum.yellow .pagenum-num:hover, .pagenum.yellow .pagenum-active:hover, .pagenum.yellow .pagenum-next:hover, .pagenum.yellow .pagenum-ok, .pagenum.yellow .pagenum-ok:hover { color: #ffc107; } .pagenum.yellow .pagenum-active, .pagenum.yellow .pagenum-active:hover { color: #fff; background-color: #ffc107; } .pagenum.center { text-align: center; } .pagenum.right { text-align: right; }
$.fn.extend({ /*=============================================================================* * 调用 $('#pagenum1').pagenum(cfg), 每次调用都会更新分页条状态. * 必须参数:{totalData:'总数',pageIndex:'当前页码',pageSize:'每页数量'} * 当总数大于0时,才需要调用分页条 *=============================================================================*/ pagenum: function (config) { // 外层框JQ对象 let pnJQ = $(this); let cfg = {}; /*====================* * 方法 public *====================*/ /*====================* * 方法 private *====================*/ // 初始化配置 {totalData:'总数',pageIndex:'当前页码',pageSize:'每页数量',pageClickE:'点击页码方法'} let initCfg = function (config) { // 当前页码 cfg.PageIndex = config.pageIndex || 1; // 每页数量[5-50] cfg.PageSize = (config.pageSize > 4 && config.pageSize < 51) ? config.PageSize : 10; // 数据总数 cfg.TotalData = config.totalData || 0; // 总页数 cfg.TotalPage = getTotalPage(); // 分页按钮个数[5-10]. cfg.TotalBtn = (config.totalBtn > 4 && config.pageSize < 11) ? config.totalBtn : 5; // 页码点击事件方法 cfg.pageClickE = config.pageClickE; } // 主要方法:更新分页条数据,绑定相关事件 let newPageNum = function () { // 清空DOM,重新生成分页组件DOM,绑定事件 pnJQ.empty(); // 1.页码按钮区域 pnJQ.append('<span class="pagenum-btns"></span>'); // 2.跳转按钮区域 pnJQ.append(String.Format('<span class="pagenum-skip">共<b class="pagenum-total">{0}</b>页 到第<input class="pagenum-input" />页<a class="pagenum-ok">确定</a></span>' , cfg.TotalPage)); // 计算页码起止 pagenumRange(); //console.log(cfg); /*-------------------------------------------------------* * 添加按钮DOM * 页码区固定按钮4个:前一页,第1页和第末页,后一页. *-------------------------------------------------------*/ let btndom = ''; // 向前按钮 btndom += String.Format('<a class="pagenum-prev" pagenum="{0}"><</a>', cfg.PageIndex - 1); // 第1页按钮,当起始页码大于1时添加 if (cfg.StartIndex > 1) btndom += String.Format('<a class="pagenum-{0}" pagenum="1">1</a>', cfg.PageIndex == 1 ? 'active' : 'num'); // 前省略号,当起始页码大于2时添加 if (cfg.StartIndex> 2) { btndom+='<span class="pagenum-break">...</span>'; } // 页码按钮 for (let i = cfg.StartIndex; i <= cfg.EndIndex; i++) { let pagenum = i; btndom += String.Format('<a class="pagenum-{0}" pagenum="{1}">{1}</a>' , pagenum == cfg.PageIndex ? 'active' : 'num', pagenum); } // 后省略号,当结束页小于最大页码-1时 if (cfg.EndIndex < (cfg.TotalPage - 1)) { btndom+='<span class="pagenum-break">...</span>'; } // 末页按钮,当结束页小于最大页码时添加 if (cfg.EndIndex < cfg.TotalPage) btndom += String.Format('<a class="pagenum-{0}" pagenum="{1}">{1}</a>', cfg.PageIndex == cfg.TotalPage ? 'active' : 'num', cfg.TotalPage); // 向后按钮 btndom += String.Format('<a class="pagenum-next" pagenum="{0}">></a>', cfg.PageIndex + 1); // 将btndom添加到页码按钮区域容器 pnJQ.find('.pagenum-btns').append(btndom); // 绑定所有按钮事件 bindEventForAllBtn(); } // 计算起始页码位置:以当前页码为中间位置,根据需要显示的页码按钮个数,计算当前页码之前和之后的页码数. // 当前页码在正中,如果显示按钮个数为偶数,则偏左.例如: "2 3 (4:当前页码在此) 5 6 7" let pagenumRange = function () { let startIndex = cfg.PageIndex - parseInt(cfg.TotalBtn / 2) + (cfg.TotalBtn % 2 == 0 ? 1 : 0); let endIndex = cfg.PageIndex + parseInt(cfg.TotalBtn / 2); // 起始页小于1,说明当前页码位于正中时,前面页码数不够了.应将第1页为起始页码,而结束页码也应该重新计算 if (startIndex < 1) { startIndex = 1; // 根据要显示的页码数计算结束页码,如果算出页码数大于总页码,则以总页码数为结束页码 endIndex = endIndex > cfg.TotalPage ? cfg.TotalPage : cfg.TotalBtn; } // 结束页码大于总页码,说明当前页码位于正中时,后面的页码数不够.应将总页码数为终止页码,起始页码应重新计算 if (endIndex > cfg.TotalPage) { endIndex = cfg.TotalPage; // 根据要显示的页码数计算起始页码,如果算出小于1,则以1为起始页码 startIndex = endIndex - cfg.TotalBtn + 1; if (startIndex < 1) startIndex = 1; } cfg.StartIndex = startIndex; cfg.EndIndex = endIndex; } // 表示前一页码(应由当前页码计算得出) let getPrevPage = function () { return cfg.PageIndex == 1 ? 1 : cfg.PageIndex - 1; } // 表示后一页码 let getNextPage = function () { return cfg.TotalPage == cfg.PageIndex ? cfg.PageIndex : cfg.PageIndex + 1; } // 总页数(由数量总数和分页大小算出) let getTotalPage = function () { if (cfg.TotalData >= 0 && cfg.PageSize >= 5 && cfg.PageIndex >= 1) { let pagecount = parseInt(cfg.TotalData / cfg.PageSize); let pagecountM = cfg.TotalData % cfg.PageSize; return pagecountM > 0 ? pagecount + 1 : pagecount; } return 0; } /*====================* * 事件绑定 *====================*/ let bindEventForAllBtn = function () { // 页码按钮点击 pnJQ.find('.pagenum-prev,.pagenum-next,.pagenum-first,.pagenum-last,.pagenum-num').on('click', function () { // 页码参数范围[1-总页码],范围外不动作 let pnnum = parseInt($(this).attr('pagenum')) || 0; if (pnnum < 1 || pnnum > cfg.TotalPage) return; cfg.pageClickE(pnnum); }); // 确定按钮点击 pnJQ.find('.pagenum-ok').on('click', function () { let pnnum = parseInt(pnJQ.find('.pagenum-input').val()) || 0; if (pnnum < 1 || pnnum > cfg.TotalPage) return; cfg.pageClickE(pnnum); }); } /*============================* * 初始化配置,生成分页组件 *============================*/ initCfg(config); newPageNum(); } })
代码
https://github.com/mirrortom/webcoms/blob/master/mirrorui/js/m-pagenum.js