完整的YUI3 Datatable翻页及查询Plugin样例
和前一篇比,增加了自动读取数据的插件并完成了翻页插件的完整代码
页面现在生成DataTable的代码如下:
var table = new Y.DataTable({ columns: Y.TableConfig.Get('user'), scrollable: 'y', height: '200px' }); table.plug(Y.DataTablePlugin.CheckboxPlugin).plug(Y.DataTablePlugin.PageBarPlugin, { info: { pagecount: 1, totalcount: 2, currentpage: 1} }).plug(Y.DataTablePlugin.DataReaderPlugin, { moniker: 'UserInfo', gridname: 'user', paging: true, queryNode: '#usercondition' }); table.render('#dtable');
和标准的YUI3的DataTable相比,这里有几处改动(可以参考前篇)
首先是不用在脚本里定义columns参数了,不管怎么样,看起来代码简洁了很多,而columns里的checkbox列也无需定义,如果需要checkbox列,直接plug CheckboxPlugin就行了
其次也不用定义Data参数了,Data将由DataReaderPlugin自动获取
CheckboxPlugin的代码就不贴了
页脚翻页条的代码如下
function DataTablePageBar(config) { DataTablePageBar.superclass.constructor.apply(this, arguments); }; Y.mix(DataTablePageBar, { NAME: 'dataTablePageBar', NS: 'pageBarPlugin', ATTRS: { place: { value: 0, validator: Y.Lang.IsNumber }, fixed: { value: false, validator: YLang.isBoolean }, info: { value: { pagecount: 1, currentpage: 1, totalcount: 1 }, setter: function(val) { this._tfootThNode.one('.page').set('text', '第' + val.currentpage + '页/共' + val.pagecount + '页 ' + val.totalcount + '条记录'); return val; } } } }); Y.extend(DataTablePageBar, Y.Plugin.Base, { _tfootContainer: null, _tfootNode: null, _tfootTrNode: null, _tfootThNode: null, initializer: function() { this.afterHostMethod("render", this.renderPluginUI); this.onHostEvent("sort", this.sort); }, renderPluginUI: function() { var dt = this.get(HOST), hdg = this.get(FOOT_HDG), tfootParent = dt._parentNode; if (dt.get("contentBox").one(".yui3-datatable-y-scroller-container")) { this._tfootNode = dt.get("contentBox").one(".yui3-datatable-y-scroller-container").appendChild(YCreate("<table width='100%'/>")).appendChild(YCreate("<tfoot/>")); } else { this._tfootNode = dt.get("contentBox").one(".yui3-datatable-table").appendChild(YCreate("<tfoot/>")); } this._tfootTrNode = this._tfootNode.appendChild(YCreate("<tr/>")); this._tfootThNode = this._tfootTrNode.appendChild(YCreate("<th colSpan='" + dt.get('columns').length + "'/>")); this._tfootThNode.addClass('yui3-datatable-ftth'); this._tfootThNode.appendChild(YCreate('<span><a class="firstpage" href="#"><img src="../image/page-first.gif" /></a></span><span><a class="prevpage" href="#"><img src="../image/page-prev.gif" /></a></span><span><a class="nextpage" href="#"><img src="../image/page-next.gif" /></a></span><span><a class="lastpage" href="#"><img src="../image/page-last.gif" /></a></span><span class="page"></span><span class="jump">跳转到第<input type="text" style="width:20px" maxlength="3">页<a class="jumppage" href="#"><image src="../image/go.gif" /></a></span>')); this._tfootThNode.delegate('click', this.changePage, 'a', this._tfootThNode, this); }, changePage: function(e, plugin) { var gopage = plugin.get('info').currentpage; if (e != null) { var enode = e.currentTarget; if (enode.hasClass('firstpage')) { gopage = 1; } else if (enode.hasClass('prevpage')) { gopage = gopage > 1 ? gopage - 1 : 1; } else if (enode.hasClass('nextpage')) { gopage = gopage > plugin.get('info').pagecount - 1 ? gopage : gopage + 1; } else if (enode.hasClass('lastpage')) { gopage = plugin.get('info').pagecount; } else if (enode.hasClass('jumppage')) { var s = parseInt(plugin._tfootThNode.one('.jump input').get('value')); if (isNaN(s)) { return; } if (s > plugin.get('info').pagecount || s < 1) { return; } gopage = s; } var dt = plugin.get(HOST); dt.dataReaderPlugin.goPage(gopage); } }, sort: function(e) { var dt = e.target; var field = '', asc = true; for (attr in e.sortBy[0]) { field = attr; asc = e.sortBy[0][attr] == 1 ? true : false; } dt.dataReaderPlugin.sort(field, asc); } });
翻页是通过翻页条和数据读取条合作动作的,如果没有翻页条(把dataReaderPlugin的paging设为false),读取数据就使用获取全部数据的方法
同时,翻页条支持DataTable的sort事件,当列定义了可以进行排序,并且用户点击排序时,通过sort事件方法调用dataReaderPlugin的sort方法用远程数据重新获取取代默认的当前页面数据排序
数据读取plugin代码如下:
function DataReaderPlugin(config) { DataReaderPlugin.superclass.constructor.apply(this, arguments); }; Y.mix(DataReaderPlugin, { NAME: 'dataReader', NS: 'dataReaderPlugin', ATTRS: { moniker: { value: '' }, rowNumber: { value: 10, validator: YLang.IsNumber }, paging: { value: true, validator: YLang.IsBoolean }, queryNode: { value: '' }, gridname: { value: '' } } }); Y.extend(DataReaderPlugin, Y.Plugin.Base, { _pagecount: 1, _totalcount: 1, _currentpage: 1, _querystr: '', _sort: '', _asc: true, initializer: function() { this.beforeHostMethod("render", this.load); this.afterHostMethod("render", this.syncPage); }, load: function() { var dt = this.get(HOST); var plugin = this; var data = { moniker: this.get('moniker'), gridname: this.get('gridname') }; if (this.get('paging')) { Y.mix(data, { page: this._currentpage, limit: this.get('rowNumber') }); } if (this._querystr != '') { Y.mix(data, { query: this._querystr }); } if (this._sort != '') { Y.mix(data, { sort: this._sort, asc: this._asc }); } var configuration = { method: 'POST', sync: true, data: data, on: { complete: function(o) { var list = Y.JSON.parse(o.data.responseText); plugin._totalcount = list.results; plugin._pagecount = Math.floor((list.results - 1) / plugin.get('rowNumber')) + 1; dt.set('data', list.rows); } } }; var rio = new Y.IO({ emitFacade: true, bubbles: true }); rio.send(this.get('paging') ? '../Query/Read' : '../Query/ReadAll', configuration); }, syncPage: function() { var dt = this.get(HOST); if (dt.pageBarPlugin != null) { dt.pageBarPlugin.set('info', { pagecount: this._pagecount, totalcount: this._totalcount, currentpage: this._currentpage }); } }, goPage: function(page) { if (page < 1) { page = 1; } if (page > this._pagecount) { page = this._pagecount; } this._currentpage = page; this.load(); this.syncPage(); }, read: function() { this._currentpage = 1; this._sort = ''; if (this.get('queryNode') != null && this.get('queryNode') != '') { this._querystr = Y.Form.GetFormData(Y.one(this.get('queryNode'))); } this.load(); this.syncPage(); }, sort: function(field, asc) { this._sort = field; this._asc = asc; this.load(); this.syncPage(); } });
属性解释:
moniker,数据类型,用于后台识别查询的数据类型
rowNumber,每页显示条数
paging:是否翻页,如果是true获取数据时使用QueryPage方法,否则使用QueryAll方法
queryNode:定义的查询条件div节点名,代码里使用额外封装的方法Y.Form.GetFormData来自动从div里生成如Name=123&Gender=1这样的数据,在我的后台代码里,定义成了象User.Name.Like=abc这样的格式,这样后台查询时就知道是模糊查询Name字段
gridname:生成的表格名,和外面的生成columns的表格名相同,后台获取这个表格名后将会根据该表格的配置调用对应的数据渲染器来渲染数据,例如,在我编写的样例里,user表格的gender列将会通过gendercolumnrender渲染器,将性别变更为male和female的图片地址
load方法:根据当前参数使用io调用后台的查询,获取数据,
syncPage方法:将结果发送给DataTable的PageBarPlugin,修正界面显示信息
这两个方法要分开的原因,是DataTable在生成时就需要数据,但是syncPage方法必须在DataTable render后才能调用(因为pageBarPlugin的render也在之后)
在查询界面上,当修改了查询条件后,点击查询按钮要重新生成查询结果时,通过如下代码调用:
Y.Widget.getByNode(Y.one('#dtable .yui3-datatable')).dataReaderPlugin.read();
上面这行代码也是我通过command模式封装在配置文件里的代码,这样不同的页面的查询代码只要拷贝粘贴,简单修改下参数就可以了
如果要动态修改显示条目数,可以通过设置dataReaderPlugin的rowNumber属性实现
下面是完整的效果图