用flexigrid实现分页显示 一

基本思路:

1. flexigird只在页面显示数据,仅此而已

2. JavaScript业务代码负责调用REST API获得数据,然后操纵flexigrid显示数据。

特别是负责操控page bar,也就是flexigrid表格下方的哪个页面导航条进行中/英文支持,每个按钮的点击事件等。

3. REST API无状态,因此通过接收一些参数来计算返回的数据:

a. 查询条件 //根据不同的业务有所变化

b. pageSize //每页记录数目

c. pageIndex //期望返回的页面编号

返回的结果包括了:

a. 某页数据的JSON格式表示

b. 查询条件

c. 最大记录数

d. 最大页面


先看个最后完成的效果图:




下面分步骤简述:

1. REST API的实现

REST API由于不记录状态,每次都是通过参数来得知要获取什么页面的数据。这个算法很多,有基于数据库自己提供的功能的,有纯粹在内存中计算的,我用的是先查询符合条件的记录总数,再分页,然后读取指定页的记录。

这到不是重点,关键是返回的数据格式JSON不按照flexigrid的要求,而是根据业务要求生成。之后页面端会有JavaScript代码将其转换成flexigrid格式。REST API返回的格式举例如下面的结果:

{
"sign_page":{
"max_sign_count":50,"page_index":1,"group_id":"","max_page_count":4,"signs":{
"displays":[
{
"index":"0","value":{
"id":"51fe01dbe4b0f241088d3b4e","userId":"4ee175ff82bc6273d0d4672f","address":"000000000001","groupName":"ok67","location":"function test","description":"","status":"offline"
}
},{
"index":"1","value":{
"id":"51fe01dbe4b0f241088d3b4f","address":"000000000002",{
"index":"2","value":{
"id":"51fe01dbe4b0f241088d3b50","address":"000000000003",{
"index":"3","value":{
"id":"51fe01dbe4b0f241088d3b51","address":"000000000004",{
"index":"4","value":{
"id":"51fe01dbe4b0f241088d3b52","address":"000000000005",{
"index":"5","value":{
"id":"51fe01dbe4b0f241088d3b53","address":"000000000006",{
"index":"6","value":{
"id":"51fe01dbe4b0f241088d3b54","address":"000000000007",{
"index":"7","value":{
"id":"51fe01dbe4b0f241088d3b55","address":"000000000008",{
"index":"8","value":{
"id":"51fe01dbe4b0f241088d3b56","address":"000000000009",{
"index":"9","value":{
"id":"51fe01dbe4b0f241088d3b57","address":"000000000010",{
"index":"10","value":{
"id":"51fe01dbe4b0f241088d3b58","address":"000000000011",{
"index":"11","value":{
"id":"51fe01dbe4b0f241088d3b59","address":"000000000012",{
"index":"12","value":{
"id":"51fe01dbe4b0f241088d3b5a","address":"000000000013",{
"index":"13","value":{
"id":"51fe01dbe4b0f241088d3b5b","address":"000000000014",{
"index":"14","value":{
"id":"51fe01dbe4b0f241088d3b5c","address":"000000000015","status":"offline"
}
}
]
}
}
}

2. JavaScript的实现

这是最重要的部分,必须完成JSON格式转换和page bar的操纵,比如事件绑定和处理等。为此,我实现了一个signTable.js,这是一个AMD模块。有了它,JavaScript就可以配置flexigrid,添加数据,并且支持分页。先看如何使用它。

	    this.table.configSigns("mydisplays",this.locale,"multiple",this.ajaxUtility,this.artDialog);
...
	    this.table.fillInSigns("mydisplays",window.userdisplays.sign_page,this.onSelectdisplay,this);

this.table就是signTable对象。就提供了两个方法,configSigns方法配置了flexigrid的列等基本信息,并且支持多选或者单选模式。后面两个参数ajaxUtility和artDialog是另外的模块用来实现ajax调用和对话框的显示。下面是该函数的实现:
	// config grid's basic structures,columents and events
	// tableId is the id of HTML table tag
	// locale is en or cn
	// selectMod single,multiple
	configSigns: function(tableId,locale,selectMod,ajaxUtility,artDialog) {
	    var id,description,location,status,page,innerHtml;
	    this.ajaxUtility = ajaxUtility;
	    this.artDialog = artDialog;
	    this.locale = locale;
	    if (locale === "en") {
		id = "ID";
		description = "Description";
		location = "Location";
		status = "Status";
	    } else if (locale === "cn") {
		id = "ID";
		description = "描述";
		location = "位置";
		status = "状态";		
	    }

	    this.selectMod = selectMod;
	    
	    $("#" + tableId).flexigrid({
		dataType: 'json',width: 630,height: 260,colModel : [
		    {display: '',name: 'id',width: 20,sortable: true,align: 'left'},{display: id,name: 'address',width: 150,{display: description,name: 'description',width: 190,{display: location,name: 'location',width: 130,{display: status,name: 'status',width: 60,align: 'left'}
		],usepager: true
	    });
	},

下面是fillInSigns函数的实现,主要负责填充数据。

	// tableId the id of HTML table tag
	// locale en or cn
	// value the data for filling in table
	// onSelect the event function for hanlding row selection
	// ob this for callback function
	fillInSigns: function(tableId,signPage,onSelect,ob) {
	    this.signPage = signPage;
	    $("#" + tableId).flexAddData(this.convert(locale,signPage));
	    $("#" + tableId +" tbody tr td div input").on("click",ob,onSelect);
	    this.updatePagebar();
	}

由于我的代码是从以前做的系统演化而来,所以signTable不是个通用的分页功能解决方案。仅在这里提供一个解决思路和完整的可参考代码,读者请自己根据情况修改吧。或许什么时候有时间,做成一个通用的flexigrid扩展也不一定。下面是signTable.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("signTable",["jquery","flexigrid","flexigrid.pack"],function ($) {
    'use strict';

    return {
	// config grid's basic structures,getStatus: function (status) {
	    if (status === "online") {
		if (this.locale === "cn") {
		    return "在线";
		} else {
		    return "Online";
		}
	    }
	    if (status === "offline") {
		if (this.locale === "cn") {
		    return "离线";
		} else {
		    return "Offline";
		}
	    }
	    return status;
	},buildCell: function (line) {
	    var template;
	    if (this.selectMod == "multiple") {
		template = "{\"cell\":[\"<input id='{0}' class='row_class' type='checkBox' value='{0}'/>\",\"{1}\",\"{2}\",\"{3}\",\"{4}\"]}";
		return jQuery.validator.format(template,line.id,line.address,line.description,line.location,this.getStatus(line.status));
	    } else {
		template = "{\"cell\":[\"<input id='{0}' class='row_class' name='single' type='radio' value='{0}'/>\",this.getStatus(line.status));
	    }
	},convert : function (locale,signPage) {
	    var ds,d,i,str,s1,s2;
	    ds = signPage.signs.displays;
	    this.length = ds.length;
	    d = "{\"page\": 1,\"total\": 40,\"rows\":[";
	    for (i = 0; i < this.length; (i += 1)) {
		str = this.buildCell(ds[i].value);
		d += str;
		if (i !== (this.length - 1)) {
		    d += ",";
		}
	    }
	    d += "]}";
	    return jQuery.parseJSON(d);
	},afterLoadPageSigns: function (ob,data) {
	    if (data.status === 0) {
		ob.fillInSigns("mydisplays",ob.locale,JSON.parse(data.value).sign_page,ob.onSelectdisplay,ob);
	    } else {
		if (ob.locale === "cn") {
		    ob.artDialog.error('设备查询失败');
		} else {
		    ob.artDialog.error('Load signs Failed.');
		}
	    }
	},// for inner reuse
	search: function(pageIndex) {
	    var pageSize = $("select[name=rp]").val(),data;
	    data = {
		'groupId': this.signPage.group_id,'pageSize': pageSize,'pageIndex': pageIndex,'column': "address",'ascending': 1
	    };
	    this.ajaxUtility.post('pageSigns',false,data,this.afterLoadPageSigns,null,this);
	},onNext: function (event) {
	    var ob = event.data;
	    ob.search(ob.signPage.page_index + 1);
	},onPrev: function (event) {
	    var ob = event.data;
	    ob.search(ob.signPage.page_index - 1);
	},onLast: function (event) {
	    var ob = event.data;
	    ob.search(ob.signPage.max_page_count);
	},onFirst: function (event) {
	    var ob = event.data;
	    ob.search(1);
	},onReload: function (event) {
	    var pageIndex,ob = event.data;
	    pageIndex = $("#pageIndexInput").val();
	    if (pageIndex !== "") {
		ob.search(parseInt(pageIndex,10)); 
	    }
	},onChangePageSize: function (event) {
	    var ob = event.data;
	    ob.search(ob.signPage.page_index);	    
	},/*
	onChangePageIndex: function (event) {
	    var ob,pageIndex;
	    ob = event.data;
	    pageIndex = $(this).val();
	    if (pageIndex !== "") {
		ob.search(parseInt(pageIndex,*/

	// 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,t1,j,pageSize = 15;
	    if (this.locale === "cn") {
		t1 = "显示 {0} 到 {1},总数: {2} 设备";
	    } else {
		t1 = "from {0} to {1},total: {2} signs";
	    }

	    i = pageSize * (this.signPage.page_index - 1) + 1;
	    j = i + pageSize - 1;
	    innerHtml = jQuery.validator.format(t1,this.signPage.max_sign_count);
	    $($(".pDiv2").children()[10]).children(0).html(innerHtml);

	    if (this.locale === "cn") {
		t1 = "页面 <input id=\"pageIndexInput\" type=\"number\" min=\"1\" style=\"width:30px;\" value=\"{0}\"> 到 <span>{1}</span>";
	    } else {
		t1 = "Page <input id=\"pageIndexInput\" type=\"number\" min=\"1\" style=\"width:30px;\" value=\"{0}\"> to <span>{1}</span>";
	    }
	    innerHtml = jQuery.validator.format(t1,this.signPage.page_index,this.signPage.max_page_count);
	    $(".pcontrol").html(innerHtml);

	    if (this.signPage.page_index === 1) {
		if (this.signPage.max_page_count === 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.signPage.page_index === this.signPage.max_page_count) {
		    $(".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");		    
		}
	    }
	    
	    if (!this.hasPageBarEvents) {
		$(".pNext").on("click",this,this.onNext);
		$(".pFirst").on("click",this.onFirst);
		$(".pPrev").on("click",this.onPrev);
		$(".pLast").on("click",this.onLast);
		$(".pReload").on("click",this.onReload);
		$("select[name=rp]").on("change",this.onChangePageSize);
		// $("#pageIndexInput").on("change",this.onChangePageIndex);
		this.hasPageBarEvents = true;
	    }

	},getSelectednum: function() {
	    var n = 0;
	    $('.row_class').each(
		function () {
		    if ($(this).is(':checked')) {
			n += 1;
		    }
		}
	    );
	    
	    return n;
	},// tableId the id of HTML table tag
	// locale en or cn
	// value the data for filling in table
	// onSelect the event function for hanlding row selection
	// ob this for callback function
	fillInSigns: function(tableId,onSelect);
	    this.updatePagebar();
	}
    };
});

相关文章

一:display:flex布局display:flex是一种布局方式。它即可以...
1. flex设置元素垂直居中对齐在之前的一篇文章中记载过如何...
移动端开发知识点pc端软件和移动端apppc端软件是什么,有哪些...
最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周...
display:flex;把容器设置为弹性盒模型(设置为弹性盒模型之后...
我在网页上运行了一个Flex应用程序,我想使用Command←组合键...