之前写过一篇用flexigrid实现分页显示 一,现在继续改进。
由于分页是一个非常常见的功能,因此需要一个可以重用,尽可能减少重复工作的JavaScript对象。在之前的第一篇中,是我的第一次探索,但是还没有做到实现一个重用的对象。本篇,将介绍一个可以重用的对象。
由于每个分页功能获取的数据不一样,所以下面几个部分是不可重用的:
1. 后台REST API
负责接受请求,解析参数,实现分页算法,返回目标页的记录和相关信息
2. 前台JavaScript控制代码
调用哪个REST API, 发送什么参数,解析REST API返回的结果并转换成flexigrid可以接受的数据格式
fexligrid UI 控制逻辑可以重用
可以重用的其实只有一个,就是如何控制flexigrid来帮助我们显示数据,包括中英文的控制,分页状态的显示,以及当用户切换分页的时候需要通过事件通知 step 2的JavaScript代码向step 1发出新的分页请求
好,实现的界面和第一篇是一样的,只不过signTable被换成了更通用的pageTable。先看一下如何使用pageTable对象。
首先,配置pageTable
config: function (id, address, userId, description, location, status, del) { var cfg, ob = this; cfg = { dataType: 'json', width: 870, height: 420, colModel : [ {hide: '_id', name: 'id', width: 140, sortable: true, align: 'left'}, {display: '设备ID', name: 'address', width: 120, sortable: true, align: 'left'}, {display: userId, name: 'userId', width: 200, sortable: true, align: 'left'}, {display: description, name: 'description', width: 150, sortable: true, align: 'left'}, {display: location, name: 'location', width: 130, sortable: true, align: 'left'}, {display: status, name: 'status', width: 60, sortable: true, align: 'left'}, {display: del, name: 'del', width: 40, sortable: true, align: 'left', process: (function (ob, hdl) { return function (celDiv, id) { hdl(ob, celDiv, id); }; }(ob, ob.remove)) } ] }; ob.pageTable.config("allDisplays", cfg, ob.locale, ob.onChangePage, null, null, null, ob); },
最后一行是关键,调用了pageTable的config方法,
第一个参数是HTML table元素的id
第二个参数是flexigrid需要的配置对象,还可以看到我在cfg对象的最后一列用闭包技巧绑定了remove方法到点击事件中。
第三个参数是locale,值是"en"或者"cn“,pageTable会跟据它控制显示英文还是中文
第四个参数是一个回调函数,当用户在pageTable中做了切换页面的操作,该函数就会被回调
第五,六,七参数暂时不用,
最后一个参数ob是拥有回调函数的对象。
第二步,调用setData方法设置数据
ob.pageTable.setData(ob.pageTable.pageSize, v.admin_sign_page.page_index, v.admin_sign_page.max_page_count, v.admin_sign_page.max_sign_count, jQuery.parseJSON(d));
第一个参数是每页的最大记录数
第二个参数是当前页的索引
第三个参数是页数
第四个参数是记录总数
第五个参数是符合flexigrid格式的数据
pageTable提供了一些属性用于读取信息:pageIndex,maxPageCount,pageSize
再看一下回调函数onChangePage:
/** * pageSize, reload, next, prev, last and first page action */ onChangePage: function (action, self) { if (action === "next") { self.loadAllSigns(self.pageTable.pageIndex + 1, ""); } else if (action === "prev") { self.loadAllSigns(self.pageTable.pageIndex - 1, ""); } else if (action === "reload") { self.loadAllSigns(self.pageTable.pageIndex, ""); } else if (action === "last") { self.loadAllSigns(self.pageTable.maxPageCount, ""); } else if (action === "first") { self.loadAllSigns(1, ""); } else if (action === "pageSize") { self.loadAllSigns(1, ""); } },
self就是之前config的最后一个参数,loadAllSigns负责调用REST API获取分页数据。
最后是pageTable.js的全部代码:
// provides some common functions on top of flexigrid for simplifying web front-end development // If some web page use one same grid, add it here, they can resuse these codes define(["jquery", "flexigrid", "flexigrid.pack"], function ($) { 'use strict'; return { // config grid's basic structures, columnts and events config: function ( tableId, //table id config, //the config object which defines the flexigrid locale, //"en" or "cn" onChangePage, //event handler when page is changed, the arg is one of these: "pageSize", "reload", "next", "prev", "last" and "first" onCheck, //event handler when user checks/unchecks the checkbox of one row onClick, //event handler when user clicks one row, two args, the row and cell objects afterRenderPage, //event handler after the page is rendered eventHolder //the holder object of onChangePage and onSelectDisplay methods ) { this.tableId = tableId; this.config = config; this.config.usepager = true; this.locale = locale; this.onChangePage = onChangePage; this.onCheck = onCheck; this.onClick = onClick; this.eventHolder = eventHolder; if (this.locale === "cn") { this.t1 = "显示 {0} 到 {1}, 总数: {2} 设备"; this.t2 = "页面 <input id=\"pageIndexInput\" type=\"number\" min=\"1\" style=\"width:40px;\" value=\"{0}\"> 到 <span>{1}</span>"; } else { this.t1 = "from {0} to {1}, total: {2} signs"; this.t2 = "Page <input id=\"pageIndexInput\" type=\"number\" min=\"1\" style=\"width:40px;\" value=\"{0}\"> to <span>{1}</span>"; } $("#" + this.tableId).flexigrid(this.config); }, onNext: function (event) { var ob = event.data; ob.onChangePage("next", ob.eventHolder); }, onPrev: function (event) { var ob = event.data; ob.onChangePage("prev", ob.eventHolder); }, onLast: function (event) { var ob = event.data; ob.onChangePage("last", ob.eventHolder); }, onFirst: function (event) { var ob = event.data; ob.onChangePage("first", ob.eventHolder); }, onReload: function (event) { var ob = event.data; var pageIndex = $("#pageIndexInput").val(); if (pageIndex !== "") { ob.pageIndex = pageIndex; } ob.onChangePage("reload", ob.eventHolder); }, onChangePageSize: function (event) { var ob = event.data; ob.pageSize = parseInt($(this).val()); ob.onChangePage("pageSize", ob.eventHolder); }, // fill in Chinese or English words according to this.locale // fill in page number according to the total pages and current page index // enable/disable buttons in page bar updatePagebar: function() { var innerHtml, i, j; this.pageSize = parseInt($("select[name=rp]").val()); i = this.pageSize * (this.pageIndex - 1) + 1; j = i + this.pageSize - 1; if (j > this.maxCount) { j = this.maxCount; } if (j === 0) { i = 0; } innerHtml = jQuery.validator.format(this.t1, i, j, this.maxCount); $($(".pDiv2").children()[10]).children(0).html(innerHtml); innerHtml = jQuery.validator.format(this.t2, this.pageIndex, this.maxPageCount); $(".pcontrol").html(innerHtml); if (this.pageIndex === 1) { if (this.maxPageCount === 1) { $(".pPrev").removeClass("pButton"); $(".pFirst").removeClass("pButton"); $(".pNext").removeClass("pButton"); $(".pLast").removeClass("pButton"); } else { $(".pPrev").removeClass("pButton"); $(".pFirst").removeClass("pButton"); $(".pNext").addClass("pButton"); $(".pLast").addClass("pButton"); } } else { if (this.pageIndex === this.maxPageCount) { $(".pNext").removeClass("pButton"); $(".pLast").removeClass("pButton"); $(".pPrev").addClass("pButton"); $(".pFirst").addClass("pButton"); } else { $(".pNext").addClass("pButton"); $(".pLast").addClass("pButton"); $(".pPrev").addClass("pButton"); $(".pFirst").addClass("pButton"); } } // just register them at the first time if (!this.hasPageBarEvents) { $(".pNext").on("click", this, this.onNext); $(".pFirst").on("click", this, this.onFirst); $(".pPrev").on("click", this, this.onPrev); $(".pLast").on("click", this, this.onLast); $(".pReload").on("click", this, this.onReload); $("select[name=rp]").on("change", this, this.onChangePageSize); this.hasPageBarEvents = true; } $(".pDiv2 .pGroup select").width(60); }, // return row array that contains all checked rows(JQuery object) getCheckedRows: function() { var rows = []; $('.row_class').each( function () { if ($(this).is(':checked')) { rows.push($(this)); } } ); return rows; }, setData: function(pageSize, pageIndex, maxPageCount, maxCount, pageData) { this.pageSize = pageSize; this.pageIndex = pageIndex; this.pageData = pageData; this.maxPageCount = maxPageCount; this.maxCount = maxCount; $("#" + this.tableId).flexAddData(this.pageData); $("#" + this.tableId + " tbody tr td div input").on("click", this.eventHandler, this.onSelect); this.updatePagebar(); } }; });