一款Jquery 分頁外掛程式的改造方法(伺服器端分頁)

來源:互聯網
上載者:User

分頁幾乎是每個外部程式必不可少的東西,在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動態賦值的

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.