目前,网络上能够找得到的、基于jQuery 框架 的、功能 比较强大的grid有两个:jqGrid和 Flexigrid。虽然这两个表格插件 没有Ext-Grid表格功能那么强大,但基本能满足日常应用 。jqGrid的用法石头在《封装了 jqGrid为control,大家用用看? 》的贴子里已做了具体介绍,在此我不再赘言。Flexigrid的功能比jqGrid稍弱,但胜在界 面美观(仿Ext),易于上手。下面我就Flexigrid在FleaPHP 下的使用方法进行具体说明。
一、Flexigrid的新特性:
二、相关代码 下载 :
三、代码安装:
代码安装比较简单,将代码解压缩到自己项目 的相应子目录 下即可,我这里是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存在不足的地方主要有两点:
六、结束语
石头曾经叫我将Flexigrid封装成QeePHP 插件,但由于我对 Qee PHP的使用还不太熟悉,真是有心无力,无法完成此艰巨的任务了,这一工作留待其他大虾去完成吧。不 过,后来想深一层,将Flexigrid封装成 QeePHP 或 Flea PHP 插件,其通用性如何?倒值得好好分析分析,研究研究。Flexigrid 的使用就介绍到这里吧,不好的地方,请各位水之。
本人论坛贴:http://qeephp.com/bbs/thread-7309-1-1.html