&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);
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);
$.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);