MVC+jQuery数据绑定①:列表绑定(二)

&qu其实挂MVC只在上一节有说道,我还是只写Jquery数据绑定吧。

我不知道别人是否使用过我这种绑定方法,这是我想出来的。所以一个人的想法会不会被别人所接受那是别人的看法。我只是分享下自己的方法。
当然,个人能力有限,愚昧的地方还望指出。
首先 试想写这个方法或者说绑定一个列表时需要碰到哪些问题? 如何在这个方法里解决大多数列表的问题?
Ⅰ、如何分页?
Ⅱ、绑定的是Url请求还是Array?
Ⅲ、列表加载后需要做什么处理?
Ⅳ、其他的问题... 
我们把绑定Table的方法写成一个Jquery的插件。 用起来就舒服一些。  
$("#lstTable").bindTable(....);
Ⅰ、如何分页?
但凡列表,都会有分页的问题。在我们这种绑定方法里分页无非是重新绑定列表,只不过请求的数据是后台给的另外一页的数据。
那么,我们的分页只不过是把一些分页连接的点击事件变成绑定请求,类似 
$(".pagelist a").click(function(){
    $("#lstTable").bindTable({pageIndex:xx});
});
假如翻页我们写成一个$("#xx").Paper(...) 翻页后会如何记忆第一次请求传递的参数?  目前是把参数记忆在table的自定义属性里,而才callback则放在一个全局变量里。
Ⅱ、绑定的是Url请求还是Array?
绑定的数据源不一定是ajax请求,可能是ViewData、Model或其他自己整理好的Array,其实Url也是去获取Data,那就视绑定为已有数据而已
已有的数据如何分页?这不和后台已分好页的数据冲突了吗? 确实有点冲突,这个.... 目前ajax数据的分页我们还是按后台来分页吧-_-
Ⅲ、列表加载后需要做什么处理?
我们动态append to tBody的html内容是死的,里面的<a>、<input>可能没有自己的事件,除非里面已经写好了 onclick 。。 这样我们改动起来就失去了Jquery的事件绑定的优势。
所以绑定数据后,我们需要处理所有列表共通的事件绑定,另外需要一个callback方法来处理特定的需求。
Ⅳ、其他的问题... 
点击thead里的连接对数据排序如何处理?  翻页后前一页的已选中的checkbox如何记忆?其他还会发现... 好的方法是慢慢成熟演变的。
以上的问题都是我在实际开发中不断碰到的总结。
Jquery的插件的写法,随便找个插件我们就可以模仿的写下来。 类似$("##").FunctionName(..) 就是下面这种写法。
; (function($) {
   $.fn.FunctionName = function(...){};
})(jQuery);
如果手打代码太累了-。-而且不能高亮,但是代码会比较干净。可是我还是选择了粘贴现在在用的代码(还没做到理想状态),如果把代码打成一个演变的过程可能更容易理解
下面我们开始写bindTable这个扩展方法。
代码
; (function($) {
var callbackList = []; //存放callback
var dataList = []; //存放table的Data 非ajax请求分页
$.fn.bindTable = function(args) {
var me = this;
if (me.length == 0) {
return me;
}
var id = me.attr("id") || me.attr("name") || me.attr("class");

//定义需要的参数
var url, pageSize, pageIndex, recordCount, data, callback, listName, isappend, ispage, sort, desc;

var isFirst, isAjax;
//检查传递的参数
switch (arguments.length) {
case 0: //
args = {};
isFirst
= false;
break;
case 1:
switch (typeof (args)) {
case "string": //只传url
url = args;
isFirst
= true;
isAjax
= true;
args
= {};
break;
case "number": //只传pageSize
pageIndex = args;
isFirst
= false;
args
= {};
break;
case "function": //只传callback
callback = args;
isFirst
= true;
args
= {};
break;
default:
data
= args.data;
if (data != undefined) {
isAjax
= false;
}
break;
}
break;
case 2: //传2个参数
isFirst = true;
isAjax
= true;

if (typeof (arguments[0]) == "string") {//url
url = arguments[0];
args.url
= url;
}
else if (typeof (arguments[0]) == "object") {//data
data = arguments[0];
args.data
= data;
}

if (typeof (arguments[1]) == "function") {//callback
callback = arguments[1];
}
args
= {};
args.callback
= callback;
break;
}

//Ajax请求
url = url || args.url || me.attr("datasource");

if (url == undefined && data == undefined)
return me;

if (isFirst)
callbackList[id]
= undefined;
else
callback
= callbackList[id];

if (isAjax)
dataList[id]
= undefined;
else
data
= args.data || dataList[id];



//是否填充
isappend = args.isappend || false;
//排序
sort = me.attr("sort") || "";
desc
= me.attr("desc") || "";

//数据源成员名
listName = args.list || "list";


//是否分页
ispage = args.ispage || me.attr("ispage") != "false";

if (!ispage) {
pageIndex
= 1;
pageSize
= 0;
recordCount
= 0;
}
else {
pageIndex
= me.attr("pageIndex") || args.pageIndex || 1;
pageSize
= args.pageSize || parseInt(me.attr("pageSize")) || Math.round(Math.round((window.screen.height - 500) / 26) / 5) * 5; //分页

}


//非填充 清空列表
if (!isappend) clearTbody(me);

//如果是url请求
if (data == undefined)
data
= getDataByAjax(getRequestUrl());
if (data == undefined)
return me;

//声明一个新的数据源 不污染原始结构
var dataSource = getDataSource(data, listName);

recordCount
= data.recordCount || data.RecordCount || dataSource.length;
$(me).attr(
"recordCount", recordCount);


var currentPageData = getPageData(dataSource, pageIndex, pageSize, recordCount);

getTbody(me, currentPageData, isappend);

runCallback(callback, dataSource);

me.attr(
"dataSource", url);

if (ispage) {
me.attr(
"pageIndex", pageIndex);
me.attr(
"pageSize", pageSize);
me.attr(
"recordCount", recordCount);
me.attr(
"ispage", ispage);
}

//翻页
if (ispage) {
me.tablePage();
}
me.setLink();
return me;

//private function .....................................................................................................
function getRequestUrl() {
if (url.indexOf("?") == -1)
url
+= "?";
else
url
= url.replace(/&?(pageIndex|pageSize|sort|desc|_)=([^&]*)/gi, "");

url
+= "&sort=" + sort + "&desc=" + desc;
if (ispage)
url
+= "&pageIndex=" + pageIndex + "&pageSize=" + pageSize;

return url;
}
//.....................................................................................................
function getDataByAjax(url) {
var data;
$.ajax({
type:
"POST",
url: url,
async:
false, //这里用了同步请求,IE6下会卡一下,如果用异步,则需要把后面的代码做成一个单独的方法。
success: function(d) {
if (d == "")
data
= undefined;
else
data
= eval("(" + d + ")");
}
});
return data;
}
//.....................................................................................................
function clearTbody(table) {
$(
".pagelist", table).empty().hide();
$(
"tbody:eq(0)", table).empty();
}
//.....................................................................................................
function getDataSource(data, listName) {
var dataSource = [];
if (data[listName] === undefined) {
dataSource
= data;
}
else if (data[listName] != null) {
dataSource
= data[listName];
}
return dataSource;
}
//.....................................................................................................
function runCallback(callback, data) {
try {
$(
">thead th input[type='checkbox']", me).attr("checked", "");
}
catch (e) { }

if (callback != undefined) {
if (typeof (callback) == "function") {
callback(data);
}
else {
try {
eval(callback)();
}
catch (e) { }
}
}

}
//.....................................................................................................
function getPageData(data, pageIndex, pageSize, recordCount) {
if (pageSize == 0)
return data;

if (data.length <= pageSize)
return data;
var pageData = [];
var loop = pageSize * pageIndex;
if (loop >= recordCount) loop = recordCount;

for (var i = (pageIndex - 1) * pageSize; i < loop; i++) {
pageData.push(dataSource[i]);
}
return pageData;
};
//.....................................................................................................
function getTbody(table, data, isAppend) {

//替换模板创建到列表
if ($(">tbody", table).length == 0)
table.append(
"<tbody></tbody>");

//没有数据的显示
if (isAppend == false) {
if (currentPageData.length == 0) {
$(
">tbody", table).html("<tr><td colspan='" + $("thead th", table).length + "'>暂时没有数据</td></tr>");
$(
">tfoot", table).empty().hide();
return table;
}
}
$(
"tr:contains('暂时没有数据')", table).remove();
$(
">tbody", table).append(replaceTemplate(table.getTemplate(), currentPageData)); //这里执行数据替换
}
};


$.fn.selectAll
= function() {
var me = this;
$(
"input[name='selectall']", me).click(function() {
$(
"tbody input[type='checkbox']", me).attr("checked", this.checked);
});
return me;
};

$.fn.getSelectedVal
= function() {
var idList = [];
$(
"tbody input[type='checkbox']:checked", this).each(function() {
idList.push(
this.value);
});
return idList;
}

})(jQuery);

 

代码
; (function($) {
$.fn.tablePage
= function(recordCount, pageSize, pageIndex, alwaysShow) {

var me = this;

recordCount
= parseInt(recordCount || me.attr("recordCount") || 0);
pageSize
= parseInt(pageSize || me.attr("pageSize") || 10);
pageIndex
= parseInt(pageIndex || me.attr("pageIndex") || 1);

alwaysShow
= !!alwaysShow;

var pageCount = parseInt(recordCount / pageSize);

if (recordCount % pageSize > 0)
pageCount
++;
if (pageIndex > pageCount)
pageIndex
= pageCount;


if (pageCount == 1 && alwaysShow == false)
return me;

if (recordCount == 0)
return me;


if ($(">tfoot td", me).length == 0)
me.append(
"<tfoot><tr><td colspan='20'></td></tr></tfoot>");

$(
">tfoot td", me).html(getPageHtml());
me.attr(
"recordCount", recordCount);
me.attr(
"pageSize", pageSize);
me.attr(
"pageIndex", pageIndex);
this.setPageLink(); //设置分页的链接
return me;

function getPageHtml() {

var getLink = function(pageIndex, linkText) {
linkText
== linkText || pageIndex;
return "<span><a href=\"#" + pageIndex + "\">" + linkText + "</a></span>";
}

var getSpan = function(text) {
return "<span>" + text + "</span>";
}

var html = "<div class=\"pagelist\">";
var first = "首页";
var prev = "上一页";
var next = "下一页";
var last = "末页";


if (pageIndex == 1) {
html
+= getSpan(first) + getSpan(prev);
}
else {
html
+= getLink(1, first) + getLink(pageIndex - 1, prev);
}

var listSize = 5;

var listIndex = parseInt(pageIndex / listSize);

if (pageIndex % listSize == 0) listIndex -= 1;

if (listIndex > 0)
html
+= getLink((listIndex - 1) * pageSize + 1, "...");

var beginPage = listIndex * listSize + 1;

var loopTimes = beginPage + listSize;

for (; beginPage <= loopTimes && beginPage <= pageCount; beginPage++) {
if (beginPage == pageIndex)
html
+= "<span class=\"current\">" + pageIndex + "</span>";
else
html
+= getLink(beginPage, beginPage);
}
if ((listIndex + 1) * pageSize < pageCount)
html
+= getLink((listIndex + 1) * pageSize + 1, "...");

if (pageIndex == pageCount) {
html
+= getSpan(next) + getSpan(last);
}
else {
html
+= getLink(pageIndex + 1, next) + getLink(pageCount, last);
}
return html += "</div>";
}

};

$.fn.setPageLink
= function() {
var me = this;
$(
"tfoot .pagelist a", this).unbind("click").click(function() {
var thisPageIndex = $(this).attr("href");
thisPageIndex
= thisPageIndex.substring(thisPageIndex.lastIndexOf("#") + 1);
me.attr(
"pageindex", thisPageIndex);
me.bindTable();
});
return me;
};

})(jQuery);

 

posted @ 2009-09-11 15:00  君之蘭  阅读(4796)  评论(2编辑  收藏  举报