本人做一個名為“安徽中控”項目時,為快速開發基礎數據增刪改模塊,遂采用EasyUIDatagrid將所有增刪改查的操作都集中於表格中,並且所有增刪改查操作都集中於泛型對象,從而不必為每個表寫具體的增刪改查代碼。而在做時間編輯時,因為EasyUI DataGrid本身沒有或者缺失時間控件編輯功能(有可能easyui版本低),需要另外為其擴展。這個過程中出現了一些問題:
1.行進入編輯狀態,但時間控件卻沒有顯示出來。
2.行數據是通過后台對象序列化傳到前台,因此時間數據格式為"\/Date(1460008088000)\/",使得時間顯示和編輯出現問題。
為了實現行編輯中嵌入時間控件編輯,首先我在網絡上查找了一段擴展代碼如下:
<script type="text/javascript">
//datagrid 時間控件編輯器擴展 $.extend($.fn.datagrid.defaults.editors, { timespinner: { init: function (container, options) { var input = $('<input/>').appendTo(container); input.timespinner(options); return input }, getValue: function (target) { var val = $(target).timespinner('getValue'); }, setValue: function (target, value) { $(target).timespinner('setValue', value); }, resize: function (target, width) { var input = $(target); if ($.boxModel == true) { input.resize('resize', width - (input.outerWidth() - input.width())); } else { input.resize('resize', width); } } } }); //datagrid 時間控件編輯器擴展 $.extend($.fn.datagrid.defaults.editors, { datetimebox: {// datetimebox就是你要自定義editor的名稱 init: function (container, options) { var input = $('<input class="easyuidatetimebox">').appendTo(container); return input.datetimebox({ formatter: function (date) { return new Date(date).format("yyyy-MM-dd hh:mm:ss"); } }); }, getValue: function (target) { return $(target).parent().find('input.combo-value').val(); }, setValue: function (target, value) { $(target).datetimebox("setValue", value); }, resize: function (target, width) { var input = $(target); if ($.boxModel == true) { input.width(width - (input.outerWidth() - input.width())); } else { input.width(width); } } } }); // 時間格式化 Date.prototype.format = function (format) { /* * eg:format="yyyy-MM-dd hh:mm:ss"; */ if (!format) { format = "yyyy-MM-dd hh:mm:ss"; } var o = { "M+": this.getMonth() + 1, // month "d+": this.getDate(), // day "h+": this.getHours(), // hour "m+": this.getMinutes(), // minute "s+": this.getSeconds(), // second "q+": Math.floor((this.getMonth() + 3) / 3), // quarter "S": this.getMilliseconds() // millisecond }; if (/(y+)/.test(format)) { format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); } for (var k in o) { if (new RegExp("(" + k + ")").test(format)) { format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)); } } return format; };
</script>
在擴展之后,我就引入EasyUI插件進行前台編寫后進行測試發現時間控件居然顯示不出來,我研究很久發現問題在於列寬太小,將原本顯示的時間控件按鈕遮擋住,於是這個問題通過調整列寬和設置fitColumns: false解決了。 而后發現后台傳過來的時間數據格式是"\/Date(1460008088000)\/"不能正常顯示,又通過在列初始化中的格式化函數中進行相應的處理(引入了datapattern.js,附加在文章最后)進行處理如下。此處應注意是列的格式化函數而不是列時間控件編輯器的格式化函數里進行處理!
{field: 'START_TIME', title: '開始時間', width: 150,
formatter: function (value, row, index) {
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;//時間格式驗證yyyy-M-d h:m:s
var r = value.match(reg);
if (r == null) {
return (eval(value.replace(/\/Date\((\d+)\)\//gi,"new Date($1)"))).pattern("yyyy-MM-dd hh:mm:ss");
} else {
return value;
}
},
editor: 'datetimebox'//注意此控件只能這么調用否則有大問題,並注意列寬夠大並且fitColumns: false
}
其中BaseTableHeard.js文件里是公共的對表格初始化設置(附加在文章最后)
<head id="Head1" runat="server">
<title></title>
<link href="../JS/jquery-easyui-1.3.5/themes/default/easyui.css" rel="stylesheet"
type="text/css" />
<link href="../JS/jquery-easyui-1.3.5/themes/icon.css" rel="stylesheet" type="text/css" />
<link href="../Common/BaseTableStyle.css" rel="stylesheet" type="text/css" />
<script src="../JS/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="../JS/jquery-easyui-1.3.5/jquery.easyui.min.js" type="text/javascript"></script>
<script src="../JS/jquery-easyui-1.3.5/locale/easyui-lang-zh_CN.js" type="text/javascript"></script>
<script src="../JS/jquery.json.js" type="text/javascript"></script>
<script src="../JS/datapattern.js" type="text/javascript"></script>
<script src="../JS/jquery-easyui-1.3.5/easyExtend.js" type="text/javascript"></script>
<script src="../JS/BaseTableHeard.js" type="text/javascript"></script>
<script type="text/javascript">
//初始化查詢條件begin
function initSearch() {
$('#btSearch').click(function () {
var txtName = $('#txtNM').val();
var whereT; //查詢條件對象
if (txtNM) {
whereT = { NM: txtName };
}
loadGridData(whereT);
});
}
//初始化查詢條件end
//initGridData方法begin
function initGridData() {
//初始化Grid表格begin
$('#gridList').datagrid({
fitColumns: false,
columns: [[
{ field: 'ID', title: '主鍵', width: 100, hidden: true },
{ field: 'NM', title: '班次名稱', width: 100, editor: { type: 'validatebox', options: { required: true}} },
{ field: 'CD', title: 'CD', width: 100, editor: 'text', hidden: true },
{ field: 'CTRL', title: 'CTRL', width: 100, editor: 'text', hidden: true },
{ field: 'USED', title: '狀態', width: 100,
formatter: function (value, row, index) {
switch (value) {
case 'Y':
return '在用'
break;
case 'N':
return '停用'
break;
default:
return '在用'
break;
}
},
editor: { type: 'combobox', options: {
panelHeight: "auto",
valueField: 'key',
textField: 'value',
data: [{ key: 'Y', value: '在用' }, { key: 'N', value: '停用'}],
required: true
}
}
},
{field: 'START_TIME', title: '開始時間', width: 150,
formatter: function (value, row, index) {
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;//時間格式驗證yyyy-M-d h:m:s
var r = value.match(reg);
if (r == null) {
return (eval(value.replace(/\/Date\((\d+)\)\//gi,"new Date($1)"))).pattern("yyyy-MM-dd hh:mm:ss");
} else {
return value;
}
},
// editor: 'datetimebox'//注意此控件只能這么調用否則有大問題,並注意列寬夠大並且fitColumns: false
editor: 'datetimebox'//注意此控件只能這么調用否則有大問題
},
{field: 'END_TIME', title: '結束時間', width: 150,
formatter: function (value, row, index) {
if(value!=null)
{
var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;//時間格式驗證yyyy-M-d h:m:s
var r = value.match(reg);
if (r == null) {
return (eval(value.replace(/\/Date\((\d+)\)\//gi,"new Date($1)"))).pattern("yyyy-MM-dd hh:mm:ss");
} else {
return value;
}
}},
editor: 'datetimebox'//注意此控件只能這么調用否則有大問題
},
{ field: 'SHIFT_NUM', title: 'SHIFT_NUM', width: 100, editor: 'text',hidden:true },
{ field: 'ISSEND', title: 'ISSEND', width: 100, editor: 'text' ,hidden:true}
]]
});
//initGridData方法end
//加載數據
loadGridData(null);
}
//initialGrid方法end
</script>
</head>
<body>
<div class="context">
<div class="search">
班次名稱:<input type="text" id="txtNM" />
<a id="btSearch" onclick="javascript:void(0);" >查詢</a>
</div>
<div class="list" style="margin: 0px">
<table id="gridList">
</table>
<div id="pager">
</div>
</div>
</div>
</body>
</html>
附件1:
BaseTableHeard.js
var url = window.location.href;
$(function () {
initGridHeader();
initGridData();
initSearch();
});
function initGridHeader() {
//初始化Grid表格begin
var tableHeight = $(document).height() - 100;
var lastIndex;
var editFlag = false;
$('#gridList').datagrid({
// url: '/GetPosList.ashx',
singleSelect: true,
striped: true,
height: tableHeight,
width: window.document.width,
rownumbers: true,
checkOnSelect: false,
selectOnCheck: false,
fitColumns: true,
showFooter: true,
// frozenColumns: [[
// { field: 'ck', checkbox: true },
// ]],
toolbar: [{
text: '新增',
iconCls: 'icon-add',
handler: function () {
$('#gridList').datagrid('endEdit', lastIndex);
var rows = $('#gridList').datagrid('getRows'); //獲取所有當前加載的數據行
var row = rows[rows.length - 1];
//不使用原行對象否則會產生關聯
var newRow = cloneRow(row);
newRow.ID = -1;
newRow.NM = '';
$('#gridList').datagrid('appendRow', newRow);
lastIndex = $('#gridList').datagrid('getRows').length - 1;
$('#gridList').datagrid('selectRow', lastIndex);
$('#gridList').datagrid('beginEdit', lastIndex);
// var grid = document.getElementById('gridList');
// grid.scrollBottom = 0;
$("#gridList").scrollBottom(0);
}
}, '-', {
text: '刪除',
iconCls: 'icon-remove',
handler: function () {
var rows = $('#gridList').datagrid('getSelections');
// var checkedRow = $('#gridList').datagrid('getChecked');
if (rows.length <= 0) {
alert('請選擇要刪除的記錄!');
return false;
}
if (confirm('你確定要刪除所選記錄嗎?')) {
if (rows) {
for (var i = 0; i < rows.length; i++) {
var index = $('#gridList').datagrid('getRowIndex', rows[i]);
$('#gridList').datagrid('deleteRow', index);
}
}
var deleteRows = $('#gridList').datagrid('getChanges', 'deleted');
var saveArray = [null, deleteRows, null];
var saveArrayJson = JSON.stringify(saveArray);
$.post(url, { Action: 'save', SaveArray: saveArrayJson }, function (data) {
if (data) {
loadGridData();
alert("刪除成功!");
} else {
alert("刪除失敗!");
}
});
$('#gridList').datagrid('acceptChanges'); //在前端保存使操作不能回滾
}
}
}, '-', {
text: '編輯',
iconCls: 'icon-edit',
handler: function () {
if (editFlag) {//當驗證未通過則上一個編輯行不能結束編輯,則editFlag=true
$('#gridList').datagrid('selectRow', lastIndex);
return;
}
var seleRow = $('#gridList').datagrid('getSelected');
if (seleRow) {
var rowIndex = $('#gridList').datagrid('getRowIndex', seleRow);
if (lastIndex != rowIndex) {
$('#gridList').datagrid('endEdit', lastIndex);
$('#gridList').datagrid('beginEdit', rowIndex);
}
lastIndex = rowIndex;
} else {
alert('請選擇要編輯的記錄!');
}
}
}, '-', {
text: '保存',
iconCls: 'icon-save',
handler: function () {
var rows = $('#gridList').datagrid('getRows');
for (var i = 0; i < rows.length; i++) {
$('#gridList').datagrid('endEdit', i); //強制所有行結束編輯
}
$('#gridList').datagrid('endEdit', lastIndex); //強制結束編輯
if (editFlag) {//當驗證未通過則上一個編輯行不能結束編輯,則editFlag=true
$('#gridList').datagrid('selectRow', lastIndex);
return;
}
debugger;
if (isRepeatNM(lastIndex)) {
alert('已經存在同名記錄!');
return false;
}
var insertRows = $('#gridList').datagrid('getChanges', 'inserted');
var deleteRows = $('#gridList').datagrid('getChanges', 'deleted');
var updateRows = $('#gridList').datagrid('getChanges', 'updated');
var saveArray = [insertRows, deleteRows, updateRows];
var saveArrayJson = JSON.stringify(saveArray);
$.post(url, { Action: 'save', SaveArray: saveArrayJson }, function (data) {
if (data) {
alert("保存成功!");
loadGridData();
// window.location.reload();
}
});
$('#gridList').datagrid('acceptChanges'); //在前端保存使操作不能回滾
}
// }, '-', {
// text: '撤銷',
// iconCls: 'icon-undo',
// handler: function () {
// $('#gridList').datagrid('rejectChanges');
// }
}, '-', {
text: '刷新',
iconCls: 'icon-reload',
handler: function () {
loadGridData();
}
}],
onBeforeLoad: function () {
$(this).datagrid('rejectChanges');
},
onClickRow: function (rowIndex) {
//如非當前編輯行則結束編輯
if (lastIndex != rowIndex) {
$('#gridList').datagrid('endEdit', lastIndex);
}
debugger;
if (lastIndex && isRepeatNM(lastIndex)) {
alert('已經存在同名記錄!');
}
},
onBeforeEdit: function (rowIndex, rowData) {
editFlag = true;
}
,
onAfterEdit: function (rowIndex, rowData, changes) {
editFlag = false;
}
// ,
// onDblClickRow: function (rowIndex) {
// //如並編輯行則使得編輯行結束編輯(此邏輯已在單擊事件處理)
// //雙擊選中復選框
// var row = $('#gridList').datagrid('getRows')[rowIndex];
// var checkedRow = $('#gridList').datagrid('getChecked');
// var isChecked = false;
// for (var i = 0; i < checkedRow.length; i++) {
// var index = $('#gridList').datagrid('getRowIndex', checkedRow[i]);
// if (index == rowIndex) {
// isChecked = true;
// }
// }
// if (isChecked) {
// $('#gridList').datagrid('uncheckRow', rowIndex);
// } else {
// $('#gridList').datagrid('checkRow', rowIndex);
// }
// }
});
}
//loadGridData方法begin
function loadGridData(whereT) {
//加載數據
var whereTStr = JSON.stringify(whereT);
$.post(url, { Action: 'getGridData', Parameters: whereTStr }, function (data) {
var json = $.parseJSON(data);
$('#gridList').datagrid('loadData', json); //將數據綁定到datagrid
});
}
//loadGridData方法end
//判斷是否重名begin
function isRepeatNM(lastIndex) {
//如名稱重復則alert並退回上條進行編輯
$('#gridList').datagrid('endEdit', lastIndex);
var rows = $('#gridList').datagrid('getRows');
var lastRow = rows[lastIndex];
//此處lastRow有bug初次加載是lastRow為null
var isRepeat = false;
for (var i = 0; i < rows.length; i++) {
if (rows[i].NM && i != lastIndex && rows[i].NM == rows[lastIndex].NM) {
isRepeat = true;
}
}
if (isRepeat) {
$('#gridList').datagrid('selectRow', lastIndex);
$('#gridList').datagrid('beginEdit', lastIndex);
}
return isRepeat;
}
//判斷是否重名end
//構造新行對象begin,不使用原型拷貝
function cloneRow(modelRow) {
var newRow = {};
for (var p in modelRow) {
var name = p; //屬性名稱
var value = modelRow[p]; //屬性對應的值
newRow[name] = modelRow[p];
}
return newRow;
}
//構造新行對象end
附件2:
datapattern.js
/**
* 對Date的擴展,將 Date 轉化為指定格式的String
* 月(M)、日(d)、12小時(h)、24小時(H)、分(m)、秒(s)、周(E)、季度(q) 可以用 1-2 個占位符
* 年(y)可以用 1-4 個占位符,毫秒(S)只能用 1 個占位符(是 1-3 位的數字)
* eg:
* (new Date()).pattern("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
* (new Date()).pattern("yyyy-MM-dd E HH:mm:ss") ==> 2009-03-10 二 20:09:04
* (new Date()).pattern("yyyy-MM-dd EE hh:mm:ss") ==> 2009-03-10 周二 08:09:04
* (new Date()).pattern("yyyy-MM-dd EEE hh:mm:ss") ==> 2009-03-10 星期二 08:09:04
* (new Date()).pattern("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
*/
Date.prototype.pattern=function(fmt) {
var o = {
"M+" : this.getMonth()+1, //月份
"d+" : this.getDate(), //日
"h+" : this.getHours()%12 == 0 ? 12 : this.getHours()%12, //小時
"H+" : this.getHours(), //小時
"m+" : this.getMinutes(), //分
"s+" : this.getSeconds(), //秒
"q+" : Math.floor((this.getMonth()+3)/3), //季度
"S" : this.getMilliseconds() //毫秒
};
var week = {
"0" : "/u65e5",
"1" : "/u4e00",
"2" : "/u4e8c",
"3" : "/u4e09",
"4" : "/u56db",
"5" : "/u4e94",
"6" : "/u516d"
};
if(/(y+)/.test(fmt)){
fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
}
if(/(E+)/.test(fmt)){
fmt=fmt.replace(RegExp.$1, ((RegExp.$1.length>1) ? (RegExp.$1.length>2 ? "/u661f/u671f" : "/u5468") : "")+week[this.getDay()+""]);
}
for(var k in o){
if(new RegExp("("+ k +")").test(fmt)){
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
return fmt;
}
