一款Jquery 分页插件的改造方法(服务器端分页)


Posted in Javascript onJuly 11, 2011

分页几乎是每个外部程序必不可少的东西,在webform时代很多人都用过AspNetPager这个用户控件吧,用的人之多其实就在于它的优点:传给它几个参数就可以生成像样的分页,其实这个也是绝大多数程序员(包括我)的致命缺点:样式..,我对于咱们来说用尝试用CSS把一个模块调美观好看所花的时间远远超过了实现功能所需的时间- -!
现在越来越多做web的开始采用.NET MVC框架,抛开一切服务器控件,回归正宗的B/S编程,享受灵活控制好处之余,也得花费很多功夫,很多地方都得自己去实现,例如分页这样的东西。简单实现功能肯定很简单,但是要做到好用,通用,性能好,易于修改也不是一个很简单的事情,所以各种JS分页控件大显身手,如jquery pager、jquery Pagination等等,调用很方便,生成效果也很好,唯一缺点就是都是内存分页,数据量少点还好,如果成千上万几百上千万数据可就要命了。要是能有一个调用方便还能配合进行服务端分页的前端控件该多好呢:)
说了这么多接下来就给大家看看我利用一个富客户端UI框架(DWZ)中分离改造出来的一个JS分页控件,先看看效果图:

页面代码:

<div class="panelBar"> 
<div class="pages"> 
<span>显示</span> 
@Html.DropDownList("numPerPage", ViewBag.dNumPerPage as SelectList, new { onchange = "PageBreak({numPerPage:this.value})" }) 
<span>条,共 @Model.TotalCount 条</span> 
</div> 
<div class="pagination" totalcount="@Model.TotalCount" numperpage="@Model.NumPerPage" 
pagenumshown="@Model.PageNumShown" currentpage="@Model.CurrentPage"> 
</div>

其实这个完全可以写成HtmlHelper调用,例如 Html.Pagination(ViewBag.dNumPerPage,Model.TotalCount,Model.NumPerPage,Model.PageNumShown,Model.CurrentPage)
这样,一条语句就可以。
原理就是用js通过获取 class="pagination" 的div的自定义属性:总页数TotalCount,每页多少条NumPerPage ,显示多少页码 PageNumShown,当前页数CurrentPage,
然后将这四个属性传给分页js,分页js内利用这几个关键属性进行计算,然后将预制好的分页模板进行替换,展现出分页效果。
为了好让美工根据项目整体风格来对分页进行调整,实现好的分工合作的原则,这里分页的js和CSS和分页替换模板是完全分开的,不至于程序看CSS晕,美工看JS晕。
分页js分为两部分,一部分只负责根据参数计算分页(pagination.js),一部分是作之前的准备工作的(core.js),一些参数的预制,在这里其实只有一个就是分页模板的位置参数,还有一些分页内部用到的自定义扩展函数,分页模板为了美工便于修改观察,不混在js里面,而又便于js利用,这里用XML的格式(pagination.xml),先把代码贴出来
 core.js:
(function($){ 
$.extend(String.prototype, { 
isPositiveInteger:function(){ 
return (new RegExp(/^[1-9]\d*$/).test(this)); 
}, 
replaceAll:function(os, ns) { 
return this.replace(new RegExp(os,"gm"),ns); 
} 
}); 
$.fn.extend({ 
hoverClass: function(className){ 
var _className = className || "hover"; 
return this.each(function(){ 
$(this).hover(function(){ 
$(this).addClass(_className); 
},function(){ 
$(this).removeClass(_className); 
}); 
}); 
} 
}); 
})(jQuery); 
var DWZ = { 
frag: {}, 
init: function (pageFrag) { 
$.ajax({ 
type: 'GET', 
url: pageFrag, 
dataType: 'xml', 
timeout: 50000, 
cache: false, 
error: function (xhr) { 
alert('Error loading XML document: ' + pageFrag + "\nHttp status: " + xhr.status + " " + xhr.statusText); 
}, 
success: function (xml) { 
DWZ.frag["pagination"]= $(xml).find("#pagination").text(); 
} 
}); 
} 
};

pagination.js:
(function($){ 
$.fn.pagination = function(opts){ 
var setting = { 
first$:"li.j-first", prev$:"li.j-prev", next$:"li.j-next", last$:"li.j-last", nums$:"li.j-num>a", jumpto$:"li.jumpto", 
pageNumFrag:'<li class="#liClass#"><a href="#">#pageNum#</a></li>' 
}; 
return this.each(function(){ 
var $this = $(this); 
var pc = new Pagination(opts); 
var interval = pc.getInterval(); 
var pageNumFrag = ''; 
for (var i=interval.start; i<interval.end;i++){ 
pageNumFrag += setting.pageNumFrag.replaceAll("#pageNum#", i).replaceAll("#liClass#", i==pc.getCurrentPage() ? 'selected j-num' : 'j-num'); 
} 
$this.html(DWZ.frag["pagination"].replaceAll("#pageNumFrag#", pageNumFrag).replaceAll("#currentPage#", pc.getCurrentPage())).find("li").hoverClass(); 
var $first = $this.find(setting.first$); 
var $prev = $this.find(setting.prev$); 
var $next = $this.find(setting.next$); 
var $last = $this.find(setting.last$); 
if (pc.hasPrev()){ 
$first.add($prev).find(">span").hide(); 
_bindEvent($prev, pc.getCurrentPage()-1, pc.targetType()); 
_bindEvent($first, 1, pc.targetType()); 
} else { 
$first.add($prev).addClass("disabled").find(">a").hide(); 
} 
if (pc.hasNext()) { 
$next.add($last).find(">span").hide(); 
_bindEvent($next, pc.getCurrentPage()+1, pc.targetType()); 
_bindEvent($last, pc.numPages(), pc.targetType()); 
} else { 
$next.add($last).addClass("disabled").find(">a").hide(); 
} 
$this.find(setting.nums$).each(function(i){ 
_bindEvent($(this), i+interval.start, pc.targetType()); 
}); 
$this.find(setting.jumpto$).each(function(){ 
var $this = $(this); 
var $inputBox = $this.find(":text"); 
var $button = $this.find(":button"); 
$button.click(function(event){ 
var pageNum = $inputBox.val(); 
if (pageNum && pageNum.isPositiveInteger()) { 
PageBreak({ pageNum: pageNum }); 
} 
}); 
$inputBox.keyup(function(event){ 
if (event.keyCode == 13) $button.click(); 
}); 
}); 
}); 
function _bindEvent(jTarget, pageNum, targetType){ 
jTarget.bind("click", {pageNum:pageNum}, function(event){ 
PageBreak({ pageNum: event.data.pageNum }); 
event.preventDefault(); 
}); 
} 
} 
var Pagination = function(opts) { 
this.opts = $.extend({ 
targetType:"navTab", // navTab, dialog 
totalCount:0, 
numPerPage:10, 
pageNumShown:10, 
currentPage:1, 
callback:function(){return false;} 
}, opts); 
} 
$.extend(Pagination.prototype, { 
targetType:function(){return this.opts.targetType}, 
numPages:function() { 
return Math.ceil(this.opts.totalCount/this.opts.numPerPage); 
}, 
getInterval:function(){ 
var ne_half = Math.ceil(this.opts.pageNumShown/2); 
var np = this.numPages(); 
var upper_limit = np - this.opts.pageNumShown; 
var start = this.getCurrentPage() > ne_half ? Math.max( Math.min(this.getCurrentPage() - ne_half, upper_limit), 0 ) : 0; 
var end = this.getCurrentPage() > ne_half ? Math.min(this.getCurrentPage()+ne_half, np) : Math.min(this.opts.pageNumShown, np); 
return {start:start+1, end:end+1}; 
}, 
getCurrentPage:function(){ 
var currentPage = parseInt(this.opts.currentPage); 
if (isNaN(currentPage)) return 1; 
return currentPage; 
}, 
hasPrev:function(){ 
return this.getCurrentPage() > 1; 
}, 
hasNext:function(){ 
return this.getCurrentPage() < this.numPages(); 
} 
}); 
})(jQuery);

分页模板pagination.xml:
<?xml version="1.0" encoding="utf-8"?> 
<_AJAX_> 
<!-- pagination --> 
<_PAGE_ id="pagination"><![CDATA[ 
<ul> 
<li class="j-first"> 
<a class="first" href="#"><span>首页</span></a> 
<span class="first"><span>首页</span></span> 
</li> 
<li class="j-prev"> 
<a class="previous" href="#"><span>上一页</span></a> 
<span class="previous"><span>上一页</span></span> 
</li> 
#pageNumFrag# 
<li class="j-next"> 
<a class="next" href="#"><span>下一页</span></a> 
<span class="next"><span>下一页</span></span> 
</li> 
<li class="j-last"> 
<a class="last" href="#"><span>末页</span></a> 
<span class="last"><span>末页</span></span> 
</li> 
<li class="jumpto"><input class="jumptotext" type="text" value="#currentPage#" /><input class="goto" type="button" value="确定" /></li> 
</ul> 
]]></_PAGE_> 
</_AJAX_>

pagination.css:
@charset "utf-8"; 
/* CSS Document */ 
/* public */ 
ul li,ol li,dt,dd {list-style:none;} 
a:link{ 
color:#000000; 
text-decoration:none; 
} 
a:visited{ 
color:#000000; 
text-decoration:none; 
} 
a:hover{ 
color:#000000; 
text-decoration:underline; 
} 
/* pagination */ 
.panelBar{ 
margin-top:12px; 
height:26px; 
line-height:26px; 
} 
.panelBar ul{ 
float:left; 
} 
.panelBar ul li{ 
float:left; 
} 
.disabled{ 
padding:0 6px; 
} 
.j-num{ 
padding:0 4px; 
} 
.pages 
{ 
margin-top:12px; 
float:left; 
} 
.pagination 
{ 
float:left; 
padding-left:50px; 
} 
.pagination li, .pagination li.hover { padding:0 0 0 5px;} 
.pagination a, .pagination li.hover a, .pagination li span { float:left; display:block; padding:0 5px 0 0; text-decoration:none; line-height:23px; background-position:100% -150px;} 
.pagination li.selected a{color:red; font-weight:bold;} 
.pagination span, .pagination li.hover span { float:left; display:block; height:23px; line-height:23px; cursor:pointer;} 
.pagination li .first span, .panelBar li .previous span { padding:0 0 0 10px;} 
.pagination li .next span, .panelBar li .last span { padding:0 10px 0 0;} 
.pagination li .first span { background:url(images/pagination/pagination_first_a.gif) left 5px no-repeat;} 
.pagination li .previous span { background:url(images/pagination/pagination_previous_a.gif) left 5px no-repeat;} 
.pagination li .next span { background:url(images/pagination/pagination_next_a.gif) right 5px no-repeat;} 
.pagination li .last span { background:url(images/pagination/pagination_last_a.gif) right 5px no-repeat;} 
.pagination li .last { margin-right:5px;} 
.pagination li.disabled { background:none;} 
.pagination li.disabled span, .grid .pagination li.disabled a { background-position:0 100px; cursor:default;} 
.pagination li.disabled span span { color:#666;} 
.pagination li.disabled .first span { background:url(images/pagination/pagination_first_span.gif) left 5px no-repeat;} 
.pagination li.disabled .previous span { background:url(images/pagination/pagination_previous_span.gif) left 5px no-repeat;} 
.pagination li.disabled .next span { background:url(images/pagination/pagination_next_span.gif) right 5px no-repeat;} 
.pagination li.disabled .last span { background:url(images/pagination/pagination_last_span.gif) right 5px no-repeat;} 
.pagination li.disabled .last { margin-right:5px;} 
.pagination li.jumpto { padding:2px 2px 0 7px; background-position:0 -200px;} 
.pagination li.jumpto .jumptotext { float:left; width:30px; height:15px; padding:1px; border-color:#acaeaf; background:#ffffff; border:1px solid #9999cc;} 
.pagination li.jumpto .goto { float:left; display:block; overflow:hidden; width:16px; height:19px; border:0; text-indent:-1000px; background:url(images/pagination/pagination_goto.gif) no-repeat; cursor:pointer;}

我看CSS也头疼,这个是我找一个朋友写的,自己又改了改
接下来讲讲使用方法:
首先 指定自己分页模板的路径 DWZ.init("js/pagination.xml"); 然后调用分页:
$(function(){ 
$("div.pagination").each(function () { 
var $this = $(this); 
$this.pagination({ 
totalCount: $this.attr("totalCount"), 
numPerPage: $this.attr("numPerPage"), 
pageNumShown: $this.attr("pageNumShown"), 
currentPage: $this.attr("currentPage") 
}); 
}); 
});

这里为什么用each呢,为啥不直接$("div.pagination").pagination({})呢,大家应该想到了,有挺多时候用户喜欢在列表的上下都放分页便于操作,这两块js其实可以单独放一个文件,需要用到分页的文件引用即可,因为程序真正用到的是web和服务器端交换所关心的数据,totalCount numPerPage pageNumShown currentPage ,之前所做的所有都只是实现好用通用的框架。现在无需改动的东西都做好了,怎么实现交互呢,很简单:点击页码或者选择每页显示下拉框或者点击go按钮时候都会触发一个自定义函数 PageBreak ,这个函数内部就大家想实现什么具体去写,例如
function PageBreak(args) { 
alert(args["pageNum"]||args["numPerPage"]); 
}

在这里面可以用js取得当前的totalCount numPerPage pageNumShown curren,和页面上筛选的form的值一并ajax提交给后端页面,然后接收返回的数据,加载到指定位置,并且注意给<div class="pagination" >这个DIV的自定义属性重新赋值然后调用一下pagination方法即可,不知道写清楚没有,先去吃饭了,如果有问题可以留言,如果不清楚具体使用的人多,打算后续写两种用法,一种是返回数据直接返回这个div的,一个是只返回表单中行数据和div的4个自定义属性,然后js动态赋值的
Javascript 相关文章推荐
用js脚本控制asp.net下treeview的NodeCheck的实现代码
Mar 02 Javascript
javascript学习笔记(六) Date 日期类型
Jun 19 Javascript
jquery与js函数冲突的两种解决方法
Sep 09 Javascript
JS中实现简单Formatter函数示例代码
Aug 19 Javascript
零基础搭建Node.js、Express、Ejs、Mongodb服务器及应用开发入门
Dec 20 Javascript
bootstrap-datetimepicker实现只显示到日期的方法
Nov 25 Javascript
深入理解javascript中concat方法
Dec 12 Javascript
利用Ionic2 + angular4实现一个地区选择组件
Jul 27 Javascript
20170918 前端开发周报之JS前端开发必看
Sep 18 Javascript
JS实现点击链接切换显示隐藏内容的方法
Oct 19 Javascript
判断滚动条滑到底部触发事件(实例讲解)
Nov 15 Javascript
JS如何使用剪贴板操作Clipboard API
May 17 Javascript
jQuery :nth-child前有无空格的区别分析
Jul 11 #Javascript
jquery刷新页面的实现代码(局部及全页面刷新)
Jul 11 #Javascript
jquery中防刷IP流量软件影响统计的一点对策
Jul 10 #Javascript
让你的CSS像Jquery一样做筛选的实现方法
Jul 10 #Javascript
基于jquery的使ListNav兼容中文首字拼音排序的实现代码
Jul 10 #Javascript
使用Jquery搭建最佳用户体验的登录页面之记住密码自动登录功能(含后台代码)
Jul 10 #Javascript
JQuery 自定义CircleAnimation,Animate方法学习笔记
Jul 10 #Javascript
You might like
玩家交还《星际争霸》原始码光盘 暴雪报以厚礼
2017/05/05 星际争霸
虹吸壶是谁发明的?煮出来的咖啡好喝吗
2021/03/04 冲泡冲煮
php 对输入信息的进行安全过滤的函数代码
2012/06/29 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
php实现向javascript传递数组的方法
2015/07/27 PHP
浅析php静态方法与非静态方法的用法区别
2016/05/17 PHP
PHP使用PDO抽象层获取查询结果的方法示例
2018/05/10 PHP
php写入文件不覆盖的实例讲解
2019/09/17 PHP
使一个函数作为另外一个函数的参数来运行的javascript代码
2007/08/13 Javascript
自己动手手写jQuery插件总结
2015/01/20 Javascript
纯javascript移动优先的幻灯片效果
2015/11/02 Javascript
Underscore源码分析
2015/12/30 Javascript
js实现对table的增加行和删除行的操作方法
2016/10/13 Javascript
bootstrap配合Masonry插件实现瀑布式布局
2017/01/18 Javascript
js中的事件委托或是事件代理使用详解
2017/06/23 Javascript
AngularJS 教程及实例代码
2017/10/23 Javascript
详解如何使用微信小程序云函数发送短信验证码
2019/03/13 Javascript
VUE注册全局组件和局部组件过程解析
2019/10/10 Javascript
jQuery实现form表单基于ajax无刷新提交方法实例代码
2019/11/04 jQuery
Python安装第三方库的3种方法
2015/06/21 Python
K-近邻算法的python实现代码分享
2017/12/09 Python
Python数据分析:手把手教你用Pandas生成可视化图表的教程
2018/12/15 Python
Python实现查找数组中任意第k大的数字算法示例
2019/01/23 Python
解决django服务器重启端口被占用的问题
2019/07/26 Python
python、PyTorch图像读取与numpy转换实例
2020/01/13 Python
Python 实现网课实时监控自动签到、打卡功能
2020/03/12 Python
python TCP包注入方式
2020/05/05 Python
python在地图上画比例的实例详解
2020/11/13 Python
HTML5 3D书本翻页动画的实现示例
2019/08/28 HTML / CSS
全球工业:Global Industrial
2020/02/01 全球购物
介绍一下linux的文件系统
2015/10/06 面试题
社区务虚会发言材料
2014/10/20 职场文书
投标售后服务承诺书
2015/04/29 职场文书
出生证明格式
2015/06/15 职场文书
浅谈Python从全局与局部变量到装饰器的相关知识
2021/06/21 Python
CSS三大特性继承性、层叠性和优先级详解
2022/01/18 HTML / CSS