自写的jQuery实现分页功能的分页组件:
功能效果如下:
分页组件就是上图中的三部分, 分别放在表格上部 和下部 。
其中,
1》》》页面的代码如下:
product.jsp
其中引用bootstrap.css 和bootstrap .js是必须的
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 3 4 5 <% 6 String path = request.getContextPath(); 7 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 8 %> 9 <!DOCTYPE HTML> 10 <html> 11 <head> 12 <meta charset="utf-8"> 13 <meta name="renderer" content="webkit|ie-comp|ie-stand"> 14 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 15 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> 16 <meta http-equiv="Cache-Control" content="no-siteapp" /> 17 18 <link href="../css/H-ui.min.css" rel="stylesheet" type="text/css" /> 19 <link href="../css/H-ui.admin.css" rel="stylesheet" type="text/css" /> 20 <link href="../css/style.css" rel="stylesheet" type="text/css" /> 21 <link href="../lib/Hui-iconfont/1.0.1/iconfont.css" rel="stylesheet" type="text/css" /> 22 <link href="../css/bootstrap.min.css" rel="stylesheet" type="text/css" /> 23 <title>资讯列表</title> 24 <style type="text/css" > 25 .pageInfo{ 26 display: inline; 27 } 28 </style> 29 </head> 30 <body> 31 32 <nav class="breadcrumb" style="padding: 0px 1px 20px 0px;margin-bottom: 0px;"><i class="Hui-iconfont"></i> 首页 <span class="c-gray en">></span> 基因信息管理 <span class="c-gray en">></span> 产品列表 <a class="btn btn-success radius r mr-20" style="line-height:1.6em;margin-top:3px" href="javascript:location.replace(location.href);" title="刷新" ><i class="Hui-iconfont"></i></a></nav> 33 34 <div class="pd-20"> 35 <div class="text-c"> 36 <select class="select" id="" name="" style="width:250px"> 37 <option value="0">产品</option> 38 <option value="AccountInfo">基因型</option> 39 <option value="AdminInfo">关键字</option> 40 </select> 41 <button name="" id="" class="btn btn-success" type="submit"><i class="Hui-iconfont"></i> 查询</button> 42 </div> 43 </div> 44 <div class="cl pd-5 bg-1 bk-gray mt-20"> 45 <span class="l"><a href="javascript:;" onclick="datadel()" class="btn btn-danger radius"><i class="Hui-iconfont"></i> 批量删除</a> 46 <a class="btn btn-primary radius" href="javascript:;"><i class="Hui-iconfont"></i> 添加产品</a></span> 47 </div> 48 49 50 <!-- 分页 + table 从这里开始 由于样式采用bootstrap,所以class样式尽量使用一致的 --> 51 <div class="container"> 52 <!-- 分页的第一部分 开始 --> 53 <div class="row" style="margin: 20px 0px 5px 10px;"> 54 <label class="pageInfo">每页显示 </label> 55 <select class="form-control pageInfo" style="width: 20%"> 56 <option>5</option> 57 <option selected="selected">10</option> 58 <option>20</option> 59 <option>50</option> 60 <option>100</option> 61 </select> 62 <label class="pageInfo">条</label> 63 </div> 64 <!-- 分页的第一部分 结束 --> 65 <!-- table部分 开始 --> 66 <div class="row"><!-- 采用样式row 分成一层 一层 --> 67 <table class="table table-hover table-bordered"> 68 <thead> 69 <tr class="text-c"> 70 <th width="25"><input type="checkbox" id="ch1">全选</th> 71 <th width="80">产品名称</th> 72 <th width="280">操作</th> 73 </tr> 74 </thead> 75 <tbody> 76 </tbody> 77 </table> 78 </div> 79 <!-- table 部分结束 --> 80 <!-- 分页 第二部分 开始 --> 81 <div class="row"> 82 <!-- 第二部分左边部分开始 --> 83 <div class="pageInfo pull-left" style="position: relative;top: 32px; font-family: Times New Roman;">当前显示第<label class="startInfo"></label>条到第<label class="endInfo"></label> 条,总共<label class="totalInfo"></label>条</div> 84 <!-- 第二部分右边部分 开始 --> 85 <div class="pageInfo pull-right"> 86 <nav > 87 <ul class="pagination"> 88 <li> 89 <a href="#" aria-label="Previous" style="display: none"> 90 <span aria-hidden="true">«</span> 91 </a> 92 </li> 93 <li class="active"><a href="#">1</a></li> 94 <li> 95 <a href="#" aria-label="Next"> 96 <span aria-hidden="true">»</span> 97 </a> 98 </li> 99 </ul> 100 </nav> 101 </div> 102 </div> 103 <!-- 分页第二部分 结束 --> 104 </div> 105 106 <script type="text/javascript" src="../lib/jquery/1.9.1/jquery.min.js"></script> 107 <script type="text/javascript" src="../lib/layer/1.9.3/layer.js"></script> 108 <script type="text/javascript" src="../lib/My97DatePicker/WdatePicker.js"></script> 109 <script type="text/javascript" src="../js/bootstrap.min.js"></script> 110 <script type="text/javascript" src="../lib/datatables/1.10.0/jquery.dataTables.min.js"></script> 111 <script type="text/javascript" src="../js/H-ui.js"></script> 112 <script type="text/javascript" src="../js/H-ui.admin.js"></script> 113 <script type="text/javascript" src="../js/pageSet.js"></script> 114 <script type="text/javascript" src="../js/geneinfo/product/product.js"></script> 115 </body> 116 </html>
2》》》分页组件的js文件
pageSet.js
1 var tt = {}; //定义分页类 2 (//这里用大括号将整个的类 包括【本类的属性定义】【本类的方法】 整体括起来,是让本类在页面加载的时候就运行 3 4 //tt这个类的字段定义 5 function(){ 6 tt = function page(url){ 7 this.pageNo =1; //当前页 初始值为1 8 this.pageSize = 10; //当前页显示多少条 9 this.startInfo = 1; //开始条数 10 this.endInfo = 10; //结束条数 11 this.totalPage = 0; //总页数 12 this.totalInfo = 0; //总条数 13 this.tempLi = "<li><a href=‘#‘></a></li>"; //用于添加页码处使用 14 this.url = url; //用于不同页面的请求地址 15 this.result = null; //用于可能仅需要正文数据时使用 16 } 17 18 //根据初始化的参数 bindData()绑定参数的方法 page初始化的对象 来请求后台,传回 新的page信息 19 tt.prototype.pageSet = function(bindData, page){ 20 $.post(page.url, 21 { 22 "pageNo" : page.pageNo, 23 "pageSize" : page.pageSize 24 }, 25 function(data){ 26 result = null; 27 data =eval("("+data+")"); 28 if(data != null && data !="" && data != undefined){ 29 page.pageNo = data.pageNum; 30 page.pageSize = data.pageSize; 31 page.startInfo = (page.pageNo-1) * page.pageSize +1; 32 page.endInfo = page.startInfo + page.pageSize - 1; 33 page.endInfo = page.endInfo > data.total ? data.total : page.endInfo; 34 page.totalPage = data.pages; 35 page.totalInfo = data.total; 36 page.result = data.list; 37 } 38 //执行绑定参数的方法 39 bindData(page); 40 //如果总页数 <=1 隐藏下一页 41 if( page.totalPage <= 1){ 42 $("a[aria-label=‘Next‘]").hide(); 43 } 44 }); 45 } 46 47 //设置分页组件的 一些信息 eq:总共多少条 显示第几条~第几条 动态显示页码 48 tt.prototype.setValue = function(page){ 49 $("label.startInfo").text(page.startInfo); //为此三个元素赋值 50 $("label.endInfo").text(page.endInfo); 51 $("label.totalInfo").text(page.totalInfo); 52 var temp = ""; 53 if(page.totalPage != 0) { //首先保证总页数不是0页 54 $(".pagination li").removeClass("active"); //移除掉之前的 当前页面 页码按钮的 选中状态 55 if(page.totalPage <= 5 && $(".pagination li").length != page.totalPage + 2) { //【初始化总页数小于5页的情况】此处规定下面显示的页数就是5页 如果总页数<5则全部显示 》》》$(".pagination li").length != page.totalPage + 2保证不会重复叠加 56 for (var i = 0; i < page.totalPage-1; i++) { //总页数<5,则全部添加 57 temp += $(page.tempLi).find("a").text(i+2).parent().prop("outerHTML"); //为tempLi变量中的a标签添加页码数 然后找到a标签的父层 此时的它是Object类型,需要通过prop("outerHTML")这个属性,获取到HTML代码 ,这样才能用于追加进页面 【 原生JS DOM里有一个内置属性 outerHTML】 58 } 59 $(".pagination li").eq(1).after(temp); //并将动态生成的页码按钮的HTML代码 添加到li的第二个之后 【这里是eq(1)第二个是因为(上一页)这个按钮虽然属性设为隐藏,但是依旧存在;而默认的还有一个第一页这个页码是存在的。所以是两个li,所以是eq(1)】 60 } else { //否则,是总页数>5的 61 var absCon = Math.abs($(".pagination li").eq(3).text() - page.pageNo); //先获取eq(3)也就是 中间位置的页码-当前页 62 //【点击中间页码 靠后的页码按钮的情况】如果当前页>中间位置的页码数 && 中间位置的.length !=0 && (除了最后一个页码li之外的的最后一个li的文本)也就是倒数第二个的文本!=总页数 【这里的判断条件就是 如果点击的是中间位置靠后的页码 eq:12345中的4或者5的话】 条件成立 63 if(page.pageNo > $(".pagination li").eq(3).text() && $(".pagination li").eq(3).length != 0 && $(".pagination li:not(:last):last").text() != page.totalPage) { 64 absCon = page.totalPage - page.pageNo >= absCon ? absCon : page.totalPage - page.pageNo; //【当前页就是即将要显示的页码】如果 总页数-当前页>absCon 那么就给absCon原本的值,否则就将总页数-当前页的值赋值给absCon 65 for (var i = 0; i < absCon; i++) { //此处absCon的作用: 点击中间位置靠后的页码数,可能即将显示的当前页 是最后一页了,那就不再添加新的页码出来了【eq:总共9页,即将显示的是第9页,那9这个页码之后就不再新增加页码了】 66 //然后将新增加的页码添加在最后一个li【此处的最后一个li是下一页按钮】之前 ;要添加的内容就是新生成的li的HTML文本 【eval($(".pagination li").eq($(".pagination li").length - 2).text())+1 这里使用eval()将其中的内容括起来是为了获取到的值直接和1相加】 67 $(".pagination li").last().before($(page.tempLi).find("a").text(eval($(".pagination li").eq($(".pagination li").length - 2).text())+1).parent().prop("outerHTML")); 68 $(".pagination li").eq(1).remove(); //并且在循环中始终删除eq(1)也就是前一页按钮之后的第一个页码 69 } 70 } else { //【初始化 页数大于5页的情况】如果 当前页面上的li【包括上一页,下一页总共7个页码按钮】!=7个 && 当前页面上的li个数 !=总页数+2 【此处的总页数是后台返回的总页数】 71 if($(".pagination li").length != 7 && $(".pagination li").length != page.totalPage+2) { 72 for (var i = 0; i < 4; i++) { 73 temp += $(page.tempLi).find("a").text(i+2).parent().prop("outerHTML"); 74 } 75 $(".pagination li").eq(1).after(temp.toString()); 76 //【点击 中间页码靠前页码的情况】如果当前页<中间位置的页码 && 上一页按钮之后的页码按钮>=2 【即点击的中间页码按钮靠前的页码按钮】 77 } else if(page.pageNo < $(".pagination li").eq(3).text() && $(".pagination li").eq(1).text() >= 2) { 78 absCon = page.pageNo - 1 > absCon ? absCon : page.pageNo - 1; 79 for (var i = 0; i < absCon ; i++) { 80 $(".pagination li").first().after( $(page.tempLi).find("a").text(eval($(".pagination li").eq(1).text()) - 1).parent().prop("outerHTML")); 81 $(".pagination li").eq($(".pagination li").length - 2).remove(); //靠后的页码按钮 【此处-2是将上一页 下一页两个按钮去掉】 82 } 83 } 84 85 } 86 } 87 88 $(".pagination li:contains("+page.pageNo+")").addClass("active"); //为 新的 当前页 页码按钮 添加 active选中状态 89 } 90 } 91 92 93 //初始化方法 页码的点击事件 上下页点击事件 每页显示多少条的 改变事件 94 tt.prototype.init=function(bindData , page){ 95 $("a[aria-label=‘Previous‘]").click(function(){ 96 $("a[aria-label=‘Next‘]").show(); 97 if(page.pageNo == 2 ){ 98 $("a[aria-label=‘Previous‘]").hide(); 99 }else{ 100 $("a[aria-label=‘Previous‘]").show(); 101 } 102 if(page.pageNo == 1){ 103 return; 104 } 105 page.pageNo--; 106 page.pageSet(bindData ,page); 107 }); 108 109 110 //绑定 下一页 的点击事件 111 $("a[aria-label=‘Next‘]").click(function(){ 112 $("a[aria-label=‘Previous‘]").show(); 113 if(page.pageNo == page.totalPage - 1){ 114 $("a[aria-label=‘Next‘]").hide(); 115 }else{ 116 $("a[aria-label=‘Next‘]").show(); 117 } 118 page.pageNo++; 119 page.pageSet(bindData , page); 120 }); 121 122 //上面的.click()绑定点击事件 和 下面的 $(document).on("click",".pagination li:gt(0):not(:last)",function(){});的区别在于: 123 //.click只能为页面现有的元素绑定点击事件,如果是动态生成的新的元素,是没有事件的 124 //而$(document).on("click","指定的元素",function(){});方法则是将指定的事件绑定在document上,而新产生的元素如果符合指定的元素,那就触发此事件 125 126 //为动态生成的 页码按钮 添加 点击事件 127 $(document).on("click",".pagination li:gt(0):not(:last)",function(){ 128 page.pageNo = $(this).text(); 129 $("a[aria-label=‘Previous‘]").show(); 130 $("a[aria-label=‘Next‘]").show(); 131 if(page.pageNo == "1"){ 132 $("a[aria-label=‘Previous‘]").hide(); 133 } 134 if(page.pageNo == page.totalPage){ 135 $("a[aria-label=‘Next‘]").hide(); 136 } 137 138 page.pageSet(bindData , page); 139 }); 140 141 //为select 选择每页显示多少条 添加改变时间 【但是这不使用change而是使用input 是因为change对IE浏览器不支持】 142 $(".pageInfo").on("input",function(){ 143 page.pageSize = $(this).val(); 144 page.pageNo = 1; 145 $("a[aria-label=‘Previous‘]").hide(); 146 $(".pagination li:not(:first):not(:last)").remove(); 147 //$(".pagination li:not(:first), .pagination li:not(:last)").remove(); 148 $(".pagination li:first").after("<li class=‘active‘><a href=‘#‘>1</a></li>"); 149 page.pageSet(bindData , page); 150 }); 151 152 153 } 154 } 155 )(); 156 157 158
3》》》本页面的js中 需要提供数据的封装功能 bindDate()方法
product.js
1 var indexProductAdd;//定义一个index作为产品添加弹出窗的layer打开返回值 ,用于关闭的时候使用 2 $(document).ready( function () { 3 4 /** 5 * 查询类型 【eq:产品:product 疾病:disease 基因:gene 】 6 */ 7 var queryType; 8 9 /** 10 * 添加产品 页面 11 */ 12 13 $(".btn-primary").click( function(){ 14 indexProductAdd = layer.open({ 15 type: 2, 16 title: "添加产品", 17 content: ‘productadd.htmls‘, 18 area: [‘500px‘, ‘580px‘] 19 }); 20 }); 21 22 /** 23 * 实例化一个分页组件的 对象 24 */ 25 var page = new tt("queryAllProduct2.htmls", bindData); 26 page.init(bindData, page); 27 page.pageSet(bindData, page); 28 29 /** 30 * 封装数据 的方法 在本页面的js中, 31 */ 32 function bindData(page){ 33 var result = page.result; 34 if(result != "" && result != null && result != undefined) { 35 var temp = ""; 36 $.each(result, function(index, item) { 37 temp += "<tr class=‘text-c‘><td><input type=‘checkbox‘ value=‘"+item.productId+"‘></td><td>"+item.productName+"</td><td><a href=‘checkdisease.htmls‘>【查看疾病信息】</a><a href=‘updateproduct.htmls‘>【更新】</a></td></tr>"; 38 }); 39 $(".table-bordered tbody").empty(); 40 $(".table-bordered tbody").append(temp); 41 page.setValue(page); 42 } 43 44 } 45 46 47 48 49 } );
4》》》controller服务器中的处理方法
@Controller
@RequestMapping("geneInfo")
public class GeneInfoController {
1 /** 2 * 分页查询---查询所有产品 3 * @param model 4 * @return 5 */ 6 @RequestMapping("/queryAllProduct2") 7 @ResponseBody 8 public PageInfo<Product> queryAllProduct2(ModelMap model, int pageNo, int pageSize){ 9 Criteria criteria = getCurrentSession().createCriteria(Product.class); 10 return productService.findQuery(criteria ,pageNo , pageSize ); 11 } 12
5》》》Dao的实现层 的分页实现
1 @Override 2 public PageInfo<T> findQuery(Criteria criteria, int pageNo, int pageSize) { 3 try { 4 Assert.isTrue(pageNo >= 1, "pageNO should start from 1"); 5 //拆分order by子句 6 Field field = CriteriaImpl.class.getDeclaredField("orderEntries"); 7 field.setAccessible(true); 8 List<?> orderEntrys = (List<?>) field.get(criteria); 9 field.set(criteria, new ArrayList()); 10 //统计总数 11 long totalCount = countAll(criteria); 12 criteria.setProjection(null); 13 //统计完了再把order by子句加上 这样保证了sql语句不会出错 14 field.set(criteria, orderEntrys); 15 List<T> list = findPage(criteria, pageNo, pageSize); 16 if (totalCount < 1) { 17 return new PageInfo<T>(); 18 } 19 PageInfo<T> page = new PageInfo<T>(); 20 page.setPageNum(pageNo); 21 page.setTotal(totalCount); 22 page.setPages((int) (totalCount / pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1)); 23 page.setPageSize(pageSize); 24 page.setList(list); 25 return page; 26 } catch (Exception e) { 27 // TODO: handle exception 28 throw new QueryException("查询出错!"); 29 } 30 31 }
其中主要的思想 就是 将分页组件 分离出来,仅作分页处理。而数据的封装则是在不同的页面进行不同的封装实现。然后封装数据的方法作为参数传递给分页对象。
时间: 2024-10-13 11:41:43