目前,网络上能够找得到的、基于jQuery 框架 的、功能 比较强大的grid有两个:jqGrid和 Flexigrid。虽然这两个表格插件 没有Ext-Grid表格功能那么强大,但基本能满足日常应用 。jqGrid的用法石头在《封装了 jqGrid为control,大家用用看? 》的贴子里已做了具体介绍,在此我不再赘言。Flexigrid的功能比jqGrid稍弱,但胜在界 面美观(仿Ext),易于上手。下面我就Flexigrid在FleaPHP 下的使用方法进行具体说明。
一、Flexigrid的新特性:
- 可调整大小的列
- 可调整大小的高度和宽度
- 可排序的列标题
- 酷主题
- 可 将普通表格转换成grid
- 能够连接到一个AJAX 数据 源( 支持XML和JSON [新] )
- 分 页
- 显示/隐藏列
- 工具栏(新)
- 搜索(新)
- 可访问 的API
二、相关代码 下载 :
- 官方网站:http://www.flexigrid.info , 由于开发 者没有自己的主机,主页空间是申请的,因此官方网站经 常变换,这个不久之后很有可能变成死链。
- 最新源代码(目前为1.0B3)下载:http://code.google.com/p/flexigrid/ , 这个就不会经常变换了。
- jQuery框架代码下载:http://code.google.com/p/jqueryjs/downloads/list 。
- jQuery UI 下载:http://jqueryui.com/themeroller/ , 下载之前,最好先定制好自己喜欢的主题风格再下载。
- jQuery表单 插件下载:http://www.malsup.com/jquery/form/#download 。
- jQuery alert插件下载:http://abeautifulsite.net/notebook_files/87/jquery.alerts.zip 。
三、代码安装:
代码安装比较简单,将代码解压缩到自己项目 的相应子目录 下即可,我这里是lib/jquery目录。
四、使用方法:
1、为了不将大家弄迷糊,且便于后续介绍,容我先将用到的数据表单视图 代码贴出来。
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(10) unsigned NOT NULL auto_increment,
`unit_id` int(10) unsigned NOT NULL default '0',
`jg_id` int(10) unsigned NOT NULL default '0',
`username` varchar(8) NOT NULL default '',
`password` varchar(64) NOT NULL default '',
`name` varchar(10) NOT NULL default '',
`class` enum('0','1') NOT NULL default '0',
`created` datetime NOT NULL default '0000-00-00 00:00:00',
`updated` datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (`user_id`)
)
说 明:数据库 与数据表均为 GB2312 编码 格式创建。
2、制作模板 文件 (Smarty)
由于Smarty要将JavaScript代码里的url 进行转换,因此我将xhtml 模 板代码跟JavaScript合并在一起组成一个模板文件。如果你将JavaScript代码里的URL写实,也可以将JavaScript代码写入文件 中,然后通过<script type="text/javascript" src="lib/jquery/your_js_file.js"></script>的方式引用。
xhtml代码:
<link rel="stylesheet" type="text/css" href="lib/jquery/ui/css/cupertino/jquery-ui-1.7.1.custom.css">
<link rel="stylesheet" type="text/css" href="lib/jquery/flexigrid/css/flexigrid/flexigrid.css">
<script type="text/javascript" src="lib/jquery/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="lib/jquery/jquery-ui-1.7.1.custom.min.js"></script>
<script type="text/javascript" src="lib/jquery/jquery.form.js"></script>
<script type="text/javascript" src="lib/jquery/flexigrid/flexigrid.js"></script>
<!-- //jquery.alerts -->
<link rel="stylesheet" type="text/css" href="lib/jquery/alerts/jquery.alerts.css">
<script type="text/javascript" src="lib/jquery/alerts/jquery.alerts.js"></script>
<style>
.flexigrid div.fbutton .add
{
background: url(lib/jquery/flexigrid/css/images/row_add.gif) no-repeat center left;
}
.flexigrid div.fbutton .edit
{
background: url(lib/jquery/flexigrid/css/images/row_edit.gif) no-repeat center left;
}
.flexigrid div.fbutton .delete
{
background: url(lib/jquery/flexigrid/css/images/row_delete.gif) no-repeat center left;
}
.flexigrid div.fbutton .reset
{
background: url(images/user_reset.gif) no-repeat center left;
}
.flexigrid div.fbutton .excel
{
background: url(images/excel.gif) no-repeat center left;
}
#dialog_div {
text-align: left;
padding-left: 20px;
margin: 0px;
padding-top: 10px;
background-color: #E3F0EA;
}
#dialog_form {
margin: 0px;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 12px;
font-style: normal;
}
#dialog_form input.txt {
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
font-style: normal;
}
</style>
<!-- // 数据显示表格 -->
<table id="grid"></table>
<!-- // 添加/修改数据对话框 -->
<div id="dialog_div" style='display:none'>
<form id="dialog_form" name="dialog_form" action="">
<input name="user_id" type="hidden" id="user_id" value="" />
<label>用户工号:
<input name="username" type="text" class="txt" id="username" />
</label>
<br /><br />
<label>真实姓名:
<input name="name" type="text" class="txt" id="name" />
</label>
<br /><br />
{{if $input.unitView}}
<label>所属单位:
{{$input.html_unit}}
</label>
<br /><br />
{{/if}}
{{if $input.jgView}}
<label>所属机构:
{{$input.html_jg}}
</label>
<br /><br />
{{/if}}
<label>分配角色:
{{$input.html_auth}}
</label>
</form>
javaScript代码:
<script type="text/javascript">
$(document).ready(function(){
$("#grid").flexigrid({
url: '{{url controller='User' action='GetJsonData'}}',
dataType: 'json',
colModel:
[
{display: '序号', name : 'seq', width : 40, sortable : false, align: 'center'},
{display: '#ID', name : 'user_id', width : 40, sortable : true, align: 'left', hide: true},
{display: '用户工号', name : 'username', width : 70, sortable : true, align: 'left'},
{display: '真实姓名', name : 'name', width : 60, sortable : true, align: 'left'},
{display: '所属单位', name : 'unitname', width : 100, sortable : false, align: 'left'},
{display: '所属机构', name : 'jgname', width : 100, sortable : false, align: 'left'},
{display: '分配角色', name : 'jgname', width : 80, sortable : false, align: 'left'},
{display: '创建时间', name : 'created', width : 110, sortable : true, align: 'left'},
{display: '更新时间', name : 'updated', width : 110, sortable : true, align: 'left'}
],
searchitems:
[
{display: '用户工号', name : 'username'},
{display: '用户姓名', name : 'name', isdefault: true}
],
sortname: "username",
sortorder: "asc",
usepager: true,
title: '用户工号维护',
useRp: true,
rp: 20,
rpOptions:[10,15,20,25,40],
showTableToggleBtn: false,
width: 590,
height: 400,
striped:true,
timeout:1000,
// onSubmit: addFormData,
pagestat: '当前显示记录 {from} 到 {to} 条,共 {total} 条记录',
procmsg: '正在处理,请稍等 ...',
nomsg:'找不到符合条件的资料!',
errormsg:'连接数据库失败!',
buttons:
[
{name: '添加', bclass: 'add', onpress: opt},
{name: '修改', bclass: 'edit', onpress: opt},
{name: '删除', bclass: 'delete', onpress: opt},
{separator: true},
{name: '重置密码', bclass: 'reset', onpress: opt},
{separator: true},
{name: '导出EXCEL', bclass: 'excel', onpress: opt},
{separator: true}
]
});
/**
* 添加/修改对话框
*/
$('#dialog_div').dialog({
hide:'', //点击取消后隐藏,如果设为true,则无法关闭弹窗。
autoOpen:false,
width:360,
height:250,
//modal:true, //蒙层
//title:'单位资料添加/修改',
overlay: {
opacity: 0.5,
background: "black"
},
buttons:{
'提交':function(){ addUpdate(); },
'取消':function(){ $(this).dialog("close"); },
'重置':function(){ $(this).children('form')[0].reset(); }
}
});
/**
* 点击工具条按钮操作
*/
function opt(com, grid) {
switch (com) {
case '添加':
$('.ui-dialog-title').text('添加用户工号');
$('#dialog_div').dialog('open').children('form')[0].reset();
break;
case '修改':
$('.ui-dialog-title').text('修改用户工号');
selected_count = $('.trSelected', grid).length;
if (selected_count == 0) {
jAlert('请选择一条记录。', '消息提示');
return false;
}
if(selected_count>1){
jAlert('抱歉每次只能修改一条记录。', '消息提示');
return false;
}
var data = new Array();
$('.trSelected td', grid).each(function(i){
//$('.trSelected td:nth-child(2) div', grid).each(function(i){
data=$(this).children('div').text();
//data=$(this).text();
});
//alert(data[3]);
//form = $('#dialog_div').dialog('open').children('form');
//form.children('input[name=unit_id]').val(data[1]);
//form.children('input[name=code]').val(data[2]);
//form.children('input[name=name]').val(data[3]);
$('#user_id')[0].value = data[1];
$('#username')[0].value = data[2];
$('#name')[0].value = data[3];
$.ajax({
url:'{{url controller='User' action='GetIds'}}',
data:{user_id:data[1]},
type:'POST',
dataType:'json',
success:function(data){
//alert($('#jg_id').options);
var unit_slt = $('#unit_id option');
var jg_slt = $('#jg_id option');
var unit_len = unit_slt.length;
var jg_len = jg_slt.length;
if(unit_len > 0) {
setSelected(unit_slt, data.unit_id);
}
if(jg_len > 0) {
setSelected(jg_slt, data.jg_id);
}
var auth_radio = $('input:radio');
//alert(auth_radio.length);
if (auth_radio.length > 0) {
setChecked(auth_radio, data.auth);
}
}
});
$('#dialog_div').dialog('open');
break;
case '删除':
selected_count = $('.trSelected', grid).length;
if (selected_count == 0) {
jAlert('请选择一条记录。', '消息提示');
return false;
}
if(selected_count>1){
jAlert('抱歉每次只能删除一条记录。', '消息提示');
return false;
}
var names = '';
$('.trSelected td:nth-child(4) div',grid).each(function(i){
if(i) {
names += ',';
}
names += $(this).text();
});
var ids = '';
$('.trSelected td:nth-child(2) div',grid).each(function(i){
if(i){
ids += ',';
}
ids += $(this).text();
})
/*
if (ids == '') {
alert('请选择删除记录,允许同时选择多条记录。');
return;
}*/
/*
if(confirm("确认删除[" + names + "]的用户工号吗?")){
del(ids);
}*/
jConfirm("确认删除[<font color='#FF0000'>" + names + "</font>]的用户工号吗?", '删除确认', function(btn){
if (btn) { del(ids); }
});
break;
case '重置密码':
selected_count = $('.trSelected', grid).length;
if (selected_count == 0) {
jAlert('请选择一条记录。', '消息提示');
return false;
}
if(selected_count>1){
jAlert('抱歉每次只能选择一条记录。', '消息提示');
return false;
}
var id = $('.trSelected td:nth-child(2) div',grid).text();
/*
var ids = '';
$('.trSelected td:nth-child(2) div',grid).each(function(i){
if(i){
ids += ',';
}
ids += $(this).text();
})*/
reset(id);
break;
case '导出EXCEL':
document.location.href = "{{url controller='User' action='Export'}}";
break;
}
}
/**
* 添加记录
*/
function addUpdate(){
$('#dialog_form').ajaxSubmit({
//$('#dialog_form').ajaxform({
url:"{{url controller='User' action='Save'}}",
type:'POST',
dataType:'json',
resetForm:true,
success:function(){
$('#grid').flexReload();
$('#dialog_div').dialog('close');
},
error:function(data){
jAlert(data.msg, '消息提示');
}
});
};
/**
* 删除记录
*/
function del(ids){
$.ajax({
url:"{{url controller='User' action='Del'}}",
data:{ids:ids},
type:'POST',
dataType:'json',
success:function(){
$('#grid').flexReload();
}
});
};
/**
* 重置密码
*/
function reset(id) {
$.ajax({
url:"{{url controller='User' action='Reset'}}",
data:{user_id:id},
type:'POST',
dataType:'json',
success:function(data){
//$('#grid').flexReload();
jAlert("成功重置[" + data.name + "]工号的密码为[123456]。", '消息提示');
//return;
},
error:function(data){
jAlert("重置[" + data.name + "]工号的密码失败。", '消息提示')
}
});
};
// 根据所属单位数据设置已选项
function setSelected(slt, value) {
for(var i=0; i<slt.length; i++) {
if(slt.value == value) {
slt.selected = true;
} else {
slt.selected = false;
}
}
};
// 根据所属机构数据设置已选项
function setChecked(slt, value) {
for(var i=0; i<slt.length; i++) {
if(slt.value == value) {
slt.checked = true;
} else {
slt.checked = false;
}
}
};
});
</script>
Flexigrid参数 配置说明:
// 设置远端服务器URL地址
url: '{{url controller='User' action='GetJsonData'}}',
// 将发送和接收的数据类型设置为JSON格式
dataType: 'json',
// 设置表格表头及数据显示方式
colModel:
[
{display: '序号', name : 'seq', width : 40, sortable : false, align: 'center'},
{display: '#ID', name : 'user_id', width : 40, sortable : true, align: 'left', hide: true},
{display: '用户工号', name : 'username', width : 70, sortable : true, align: 'left'},
{display: '真实姓名', name : 'name', width : 60, sortable : true, align: 'left'},
{display: '所属单位', name : 'unitname', width : 100, sortable : false, align: 'left'},
{display: '所属机构', name : 'jgname', width : 100, sortable : false, align: 'left'},
{display: '分配角色', name : 'jgname', width : 80, sortable : false, align: 'left'},
{display: '创建时间', name : 'created', width : 110, sortable : true, align: 'left'},
{display: '更新时间', name : 'updated', width : 110, sortable : true, align: 'left'}
],
// 设置快速搜索参数
searchitems:
[
{display: '用户工号', name : 'username'},
{display: '用户姓名', name : 'name', isdefault: true}
],
// 设置表格标题
title: '用户工号维护',
//分页相关参数
usepager: true,
useRp: true,
rp: 20,
rpOptions:[10,15,20,25,40],
// 不显示关闭表格窗口按钮
showTableToggleBtn: false,
// 设置表格宽度及高度
width: 590,
height: 400,
// 设置表格数据隔行变色
striped:true,
// 设置表格中文信息显示
pagestat: '当前显示记录 {from} 到 {to} 条,共 {total} 条记录',
procmsg: '正在处理,请稍等 ...',
nomsg:'找不到符合条件的资料!',
errormsg:'连接数据库失败!',
// 设置表格工具按钮
buttons:
[
{name: '添加', bclass: 'add', onpress: opt},
{name: '修改', bclass: 'edit', onpress: opt},
{name: '删除', bclass: 'delete', onpress: opt},
{separator: true},
{name: '重置密码', bclass: 'reset', onpress: opt},
{separator: true},
{name: '导出EXCEL', bclass: 'excel', onpress: opt},
{separator: true}
]
四、后台 PHP 代码(节选):
获取分页数据代码:
/**
* 返回JSON分页数据到前台
*
*/
function actionGetJsonData()
{
$user = $this->user;
$page = ($_POST['page']) ? $_POST['page'] : 1;
$limit = ($_POST['rp'])?$_POST['rp'] : 20;
$sortname = $_POST['sortname'];
$sortorder = $_POST['sortorder'];
if (!$sortname) $sortname = 'username';
if (!$sortorder) $sortorder = 'asc';
$sort = "$sortname $sortorder";
if (!$page) $page = 1;
if (!$limit) $limit = 15;
$offset = ($page-1) * $limit;
$query = $_POST['query'];
$qtype = $_POST['qtype'];
if ($qtype == 'name') {
$query = mb_convert_encoding($query, 'GB2312', 'utf-8');
}
if ($user['RBAC_ROLES'][0] == 'SYSTEM_ADMIN'){
$conditions = array(
array('class', '1', '='),
);
} else {
$conditions = array(
array('unit_id', $user['UNITID'], '=', 'AND'),
array('class', '0', '=')
);
}
if ($query) {
$conditions = array(
array($qtype, '%' . $query . '%', 'LIKE')
);
}
$this->_tblUser->enableLinks();
$rows = $this->_tblUser->findAll($conditions, $sort, array($limit, $offset));
$rs = $this->_tblUser->findAll($conditions);
$total = count($rs);
$json = "";
$json .= "{\n";
$json .= "page: $page,\n";
$json .= "total: $total,\n";
$json .= "rows: [";
$rc = false;
$i = 1;
foreach ($rows as $row) {
if ($rc) $json .= ",";
$json .= "\n{";
$json .= "user_id:'".$row['user_id']."',";
$json .= "cell:['".$i."'";
$json .= ",'".$row['user_id']."'";
$json .= ",'".$row['username']."'";
$json .= ",'".addslashes($row['name'])."'";
$json .= ",'".addslashes($row['unit']['name'])."'";
$json .= ",'".addslashes($row['jgwh']['name'])."'";
$json .= ",'".$row['roles'][0]['rolename_cn']."'";
$json .= ",'".$row['created']."'";
$json .= ",'".$row['updated']."']";
$json .= "}";
$rc = true;
$i++;
}
$json .= "]\n";
$json .= "}";
echo $json;
exit;
}
注 意上面生成 JSON 格式数据的 PHP 代码,必须严格按照这样的格式返回数据,否则 Flexigrid 将无法处理返回的数据。再有,请注意列模型 colModel 里 的 name 参数,与 user 数据表的字段 并不一一对应,但必须与返回的 JSON 数据保持一致。
保存数据代码:
/**
* 保存数据
*
*/
function actionSave()
{
$user = $this->user;
$data = $_POST;
$data['name'] = mb_convert_encoding(trim($data['name']), 'GB2312', 'utf-8');
if ($data['username'] == ''){
//js_alert("请输入操作帐号。",'',$this->_url());
echo "{succees:false,msg:'用户工号不能为空!'}";
return;
}
if (strlen($data['username']) != 8){
//js_alert("您输入的工号不等于8位,请检查后重新增加。",'',$this->_url());
echo "{succees:false,msg:'用户工号不等于8位!'}";
return;
}
if ($data['name'] == ''){
//js_alert("请输入用户名称。",'',$this->_url());
echo "{succees:false,msg:'用户姓名不能为空!'}";
return;
}
if ($data['user_id']=='') {
$data['password'] = '123456';
//$sort = '`user_id` DESC';
}
if ($data['user_id'] == '' && $this->_tblUser->existsUsername(trim($data['username']))) {
//js_alert("该工号已存在,请重新输入。",'',$this->_url());
echo "{succees:false,msg:'该用户工号已存在!'}";
return false;
}
if (isset($data['auth']) && ($data['auth'] == 1 || $data['auth'] == 2)) {
$data['class'] = '1';
}
if (isset($data['auth'])) {
$data['roles'][0] = $data['auth']; // 为更新 users_roles 中间表准备数据
}
if ($user['RBAC_ROLES'][0] != 'SYSTEM_ADMIN') {
$data['unit_id'] = $user['UNITID'];
}
$this->_tblUser->enableLink('roles');
__TRY();
$this->_tblUser->save($data);
$ex = __CATCH();
if (__IS_EXCEPTION($ex)) {
echo "{succees:false,msg:'保存数据失败!'}";
} else {
echo "{succees:true,msg:'保存数据成功!'}";
}
exit;
}
注 意其中的语句 :
$data['name'] = mb_convert_encoding(trim($data['name']), 'GB2312', 'utf-8');
由于 ajax提交的中文数据为 utf-8 编码格式的数据,因此保存到数据表时,须用多字节字符串处理函数 mb_convert_encoding 转换成 GB2312 编码格式的数据。
删除记录代码:
/**
* 删除记录
*
*/
function actionDel()
{
$ids = $_POST['ids'];
if ($this->user['RBAC_ROLES'][0] == 'SYSTEM_ADMIN') {
__TRY();
$this->_tblUser->removeByPkv((int)$ids);
$ex = __CATCH();
} else {
$conditions = array(
array('unit_id', $this->user['UNITID'], '=', 'AND'),
array('user_id', $ids, '='),
);
$this->_tblUser->enableLink('roles');
__TRY();
$this->_tblUser->removeByConditions($conditions);
$ex = __CATCH();
}
if (__IS_EXCEPTION($ex)) {
echo "{succees:false,msg:'删除数据失败!'}";
} else {
echo "{succees:true,msg:'删除数据成功!'}";
}
exit;
}
在此,不使用json_encoding生成返回的分页json 格式数据,因为在 GB2312 环境下使用时,返回的中文数据会乱码 。估计json_encoding生成了 json 数据对象 ,而 json 数据对象在 JavaScript 中是以 utf-8 编码来保存数据,所以导致在 GB2312 环境下会产生中文乱码。而上面的 PHP 代码直接返回的数据是 json 格式的字符串,所以在浏览器显示中文数据时不会产生乱码。
五、存在不足:
Flexigrid存在不足的地方主要有两点:
- 定制搜索功能太弱,但这也是开发者将搜索功能定义 为“Quick Search”的原因。
- 版 本更新维护严重不足,目前最新版本也是2008-7-14推出来的,现在快一年了还没见更新。
六、结束语
石头曾经叫我将Flexigrid封装成QeePHP 插件,但由于我对 Qee PHP的使用还不太熟悉,真是有心无力,无法完成此艰巨的任务了,这一工作留待其他大虾去完成吧。不 过,后来想深一层,将Flexigrid封装成 QeePHP 或 Flea PHP 插件,其通用性如何?倒值得好好分析分析,研究研究。Flexigrid 的使用就介绍到这里吧,不好的地方,请各位水之。
本人论坛贴:http://qeephp.com/bbs/thread-7309-1-1.html
运 行效果图1: 
运行效果图2:
运行效果图3:

运行效果图4:

运行效果图5:
本文详细介绍了Flexigrid表格插件的使用方法,包括代码安装、配置参数、前后端交互等,并提供了完整的示例代码。
2556

被折叠的 条评论
为什么被折叠?



