一款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 相关文章推荐
JavaScript 模仿vbs中的 DateAdd() 函数的代码
Aug 13 Javascript
跟着JQuery API学Jquery 之二 属性
Apr 09 Javascript
jQuery实现form表单reset按钮重置清空表单功能
Dec 18 Javascript
JavaScript实现自己的DOM选择器原理及代码
Mar 04 Javascript
JS定义回车事件(实现代码)
Jul 08 Javascript
jQuery+css实现炫目的动态块漂移效果
Jan 28 Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
May 24 Javascript
jQuery动态追加页面数据以及事件委托详解
May 06 jQuery
jQuery操作css样式
May 15 jQuery
node基于async/await对mysql进行封装
Jun 20 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
Jul 29 Javascript
JS/CSS实现字符串单词首字母大写功能
Sep 03 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
PHP模板引擎SMARTY
2006/10/09 PHP
hadoop常见错误以及处理方法详解
2013/06/19 PHP
PHP获得数组交集与差集的方法
2015/06/10 PHP
PHP之密码加密的几种方式
2015/07/29 PHP
Symfony2使用Doctrine进行数据库查询方法实例总结
2016/03/18 PHP
PHP实现补齐关闭的HTML标签
2016/03/22 PHP
php基于Redis消息队列实现的消息推送的方法
2018/11/28 PHP
javascript  Error 对象 错误处理
2008/05/18 Javascript
Javascript中Event属性搜集整理
2013/09/17 Javascript
Node.js抓取中文网页乱码问题和解决方法
2015/02/10 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
JavaScript中使用数组方法汇总
2016/02/16 Javascript
jQuery实现的选择商品飞入文本框动画效果完整实例
2016/08/10 Javascript
AngularJS中如何使用echart插件示例详解
2016/10/26 Javascript
Angular.JS实现无限级的联动菜单(使用demo)
2017/02/08 Javascript
原生js实现轮播图
2017/02/27 Javascript
JavaScript实现图片无缝滚动效果
2017/07/07 Javascript
关于Vue.nextTick()的正确使用方法浅析
2017/08/25 Javascript
React中上传图片到七牛的示例代码
2017/10/10 Javascript
微信小程序实现侧边栏分类
2019/10/21 Javascript
JavaScript 事件代理需要注意的地方
2020/09/08 Javascript
ant design vue中表格指定格式渲染方式
2020/10/28 Javascript
[02:56]DOTA2矮人直升机 英雄基础教程
2013/11/26 DOTA
Python 文件处理注意事项总结
2017/04/10 Python
python实现扫描日志关键字的示例
2018/04/28 Python
实例讲解Python脚本成为Windows中运行的exe文件
2019/01/24 Python
django drf框架自带的路由及最简化的视图
2019/09/10 Python
python 使用pygame工具包实现贪吃蛇游戏(多彩版)
2019/10/30 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
Wedgwood英国官方网站:英式精致骨瓷餐具、礼品与生活精品,源于1759年
2019/09/02 全球购物
青春飞扬演讲稿
2014/09/11 职场文书
资产运营委托书范本
2014/10/16 职场文书
《彼得与狼》教学反思
2016/02/20 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python
MySQL触发器的使用
2021/05/24 MySQL
python flask开发的简单基金查询工具
2021/06/02 Python