easyui datagrid 批量編輯和提交 並改變修改過單元格的顏色
阿新 • • 發佈:2018-12-22
//首先我們需要一下工具方法
//為陣列新增一些方法
//去重
Array.prototype.unique = function() {
this.sort();
var re = [ this[0] ];
for (var i = 1; i < this.length; i++) {
if (this[i] !== re[re.length - 1]) {
re.push(this[i]);
}
}
return re;
}
//判斷元素是否存在
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
//刪除
Array.prototype.remove = function(val) {
var index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
}
//判斷元素是否存在
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] === obj) {
return true;
}
}
return false;
}
//對陣列或集合的深拷貝
function objDeepCopy(source) {
var sourceCopy = source instanceof Array ? [] : {};
for ( var item in source) {
sourceCopy[item] = typeof source[item] === 'object' ? objDeepCopy(source[item])
: source[item];
}
return sourceCopy;
}
//定位
Array.prototype.indexOf = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i] == val) return i;
}
return -1;
};
//判斷兩個物件指定屬性的值是否相等(忽略型別)
function isObjectValueEqual(obj1, obj2, arr) {
for (var i = 0; i < arr.length; i++) {
var propName = arr[i];
if (obj1[propName] != obj2[propName]) {
return false;
}
}
return true;
}
$(function() {
var dg = $("#dg");
//建立一個全域性陣列 我們方便稱號取個名字叫:更新陣列 裡面儲存修改後(這裡的修改後指的是值有變動的而不是我開啟編輯過的行)的行物件
var updatedrows = [];
/*
這裡我先來科普下 最近使用easyui datagrid我發現 datagrid中存在一個元資料物件(我就這麼稱呼它吧) 就是頁面第一次載入後的所獲得的資訊後
我們在頁面上進行的任何修改 新增 刪除 都會更改這個資料物件的值 我們無論通過何種方法或事件獲取的資料都是該資料物件的一個引用 並不是一個新的物件
就是說我們對所獲取的物件進行修改都是對資料物件的修改 所以說元資料物件並不等於初始化資料(初始化資料指我們頁面載入所請求的資料)
*/
//建立一個全域性物件(olddata) 我們方便稱號取個名字叫:初始化資料物件 裡面儲存datagrid首次載入完資料時元資料物件的一個拷貝 (不要直接使用=號賦值)
var olddata;
//全域性變數當前正在編輯的行號
var editIndex = undefined;
//我個人用來偷懶的 用來代替$('#dg').datagrid(xx,xx,xx....) 建議你們好好的寫$('#dg').datagrid(xx,xx,xx....)
function mydg() {
var str = '(';
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == "string") {
str += "'" + arguments[i] + "',"
} else if (typeof arguments[i] == "object") {
str += JSON.stringify(arguments[i]) + ","
} else {
str += +arguments[i] + ","
}
}
str = (str.substring(str.length - 1) == ',') ? str.substring(0,
str.length - 1) : str;
str += ')'
str = "$('#dg').datagrid" + str;
var retu = eval(str);
return retu;
}
//初始化我們的datagrid
$("#dg").datagrid(
{
//從遠端站點請求資料的 URL。
url : '${pageContext.request.contextPath}/emp/getEmpAll',
//設定為 true,則只允許選中一行。(並不是指每行的複選框)
singleSelect : true,
// 如果設定為 true,當用戶點選某一行時,則會選中/取消選中複選框。如果設定為 false 時,只有當用戶點選了複選框時,才會選中/取消選中複選框。
checkOnSelect : false,
//如果設定為 true,點選複選框將會選中該行。如果設定為 false,選中該行將不會選中複選框。
selectOnCheck : false,
//使列自動展開/摺疊以適應資料網格(datagrid)的寬度。
fitColumns : true,
//指示哪個欄位是標識欄位。
idField : 'empno',
//設定為 true,則在資料網格(datagrid)底部顯示分頁工具欄。
pagination : true,
fit : true,
fitColumn : false,
// 設定為 true,則把行條紋化。(即奇偶行使用不同背景色)
striped : true,
//
nowap : true,
border : true,
//標題文字
title : '員工管理',
rownumbers : true,
//當用戶雙擊一個單元格時觸發
onDblClickCell : onDblClickCell,
//該事件在完成編輯但是編輯器尚未銷燬之前觸發
onEndEdit : onEndEdit,
/*
* 當資料載入成功時觸發 我們會用這個事件備份資料但是要注意這個事件並不是載入完資料第一個執行的方法
* field裡有很多方法都會優先與onLoadSuccess之前執行,例如styler formatter 他們都有可能改變資料格式
* 我們可以利用這個特性來改變我們想要備份的資料格式
*/
onLoadSuccess : onLoadSuccess,
//當用戶完成編輯一行時觸發
onAfterEdit : onAfterEdit,
//傳送載入資料的請求前觸發,如果返回 false 載入動作就會取消。
onBeforeLoad : onBeforeLoad,
//從遠端站點請求資料的 URL
//初始化列
columns : [ [
{
field : 'ck',
checkbox : true
},
{
field : 'empno',
title : '員工編號',
width : 100,
/*
* styler:單元格的樣式函式,返回樣式字串來自定義該單元格的樣式
* styler 方法會優先與onLoadSuccess事件執行前執行
* 另我們每次結束編輯模式之後都會重新呼叫styler方法
* 我們利用這個特性來達到每次修值後更改背景顏色
*/
styler : styler
},
{
field : 'deptno',
title : '員工部門',
width : 100,
styler : styler,
// formatter 方法會優先與onLoadSuccess事件執行前執行
formatter : function(value, row) {
//我們可以將資料改成我們想要備份的格式 注意這裡會更改元資料物件
if (row.dept) {
row.deptno = row.dept.deptno;
row.dname = row.dept.dname;
delete row.dept.loc;
return row.dept.dname;
}
},
//指示編輯型別 要想開啟編輯模式必須為field指定編輯型別
editor : {
type : 'combobox',
options : {
valueField : 'DEPTNO',
textField : 'DNAME',
method : 'get',
url : '${pageContext.request.contextPath}/dept/getDeptAlls'
}
}
}, {
field : 'ename',
title : '員工姓名',
width : 100,
styler : styler,
editor : {
type : 'validatebox',
options : {
required : false
}
}
}, {
field : 'hiredate',
title : '員工生日',
width : 100,
styler : styler,
editor : 'datebox'
}, {
field : 'sal',
title : '員工薪水',
width : 100,
align : 'right',
styler : styler,
editor : {
type : 'numberbox',
options : {
precision : 1
}
}
} ] ],
//頭部工具欄
toolbar : [ {
iconCls : 'icon-add',
handler : append,
text : '新增'
}, '-', {
iconCls : 'icon-remove',
handler : removeit,
text : '刪除'
}, '-', {
iconCls : 'icon-save',
handler : accept,
text : '儲存'
}, '-', {
iconCls : 'icon-undo',
handler : reject,
text : '撤銷'
} ]
});
/*
* 判斷值是否被修改 如果被修改更改單元格的背景顏色
* 這裡的思路是這樣的 首先我們要進行判斷 所修改的資料是否是初始化資料
如果是將修改後的值和初始化資料物件進行比較 返回顏色
如果不是初始化資料物件 則代表是新增加的行 直接返回顏色就可以了
*/
function styler(value, row, index) {
if (olddata) {
//這裡是一個簡單的演算法 計算當前行是初始化資料的第幾行
var Index = index - (mydg('getRows').length - olddata.length);
if (Index >= 0) {
for ( var aq in row) {
if (row[aq] == value) {
if (value != olddata[Index][aq]) {
return 'background-color:#ffee00;';
}
}
}
} else {
return 'background-color:#ffee00;';
}
}
}
/*定義一個方法 判斷當前有沒有正在編輯的行 如果沒有 則返回true
* 如果有 則判斷當前編輯的行是否有效 如果有效 則結束對改行的編輯 並更新全域性變數的值 返回true
* 如果沒效直接返回false
* */
function endEditing() {
if (editIndex == undefined) {
return true;
} else if (dg.datagrid("validateRow", editIndex)) {
dg.datagrid("endEdit", editIndex);
editIndex = undefined;
return true;
} else {
return false;
}
}
//雙擊單元格事件 開啟行的編輯模式
function onDblClickCell(rowIndex, field, value) {
if (editIndex != rowIndex) {
if (endEditing()) {
mydg('beginEdit', rowIndex);
var rows = mydg('getRows');
var row = rows[rowIndex];
//取消識別符號單元格的可編輯屬性
var tt = mydg('getColumnOption', 'empno');
tt.editor = {};
//為下拉框賦值
//使單元獲取焦點
var ed = mydg('getEditor', {
index : rowIndex,
field : field
});
if (ed) {
($(ed.target).data('textbox') ? $(ed.target).textbox(
'textbox') : $(ed.target)).focus();
}
editIndex = rowIndex;
}
}
}
//新增一行
function append() {
if (endEditing()) {
mydg('insertRow', {
index : 0, // index start with 0
row : {
}
});
var tt = mydg('getColumnOption', 'empno');
tt.editor = {
type : 'numberbox'
};
mydg('beginEdit', 0);
//使單元獲取焦點
var ed = mydg('getEditor', {
index : 0,
field : 'empno'
});
if (ed) {
($(ed.target).data('textbox') ? $(ed.target).textbox(
'textbox') : $(ed.target)).focus();
}
editIndex = 0;
}
}
//onEndEdit:該事件在完成編輯但是編輯器尚未銷燬之前觸發;
function onEndEdit(rowIndex, row) {
var ed = $(this).datagrid('getEditor', {
index : rowIndex,
field : 'deptno'
})
var dept={};
row.dept=dept;
row.dname = $(ed.target).combobox('getText');
row.dept.dname = row.dname;
row.dept.deptno = row.deptno;
}
//傳送載入資料的請求前觸發,如果返回 false 載入動作就會取消。
function onBeforeLoad() {
olddata = null;
updatedrows = [];
}
//當資料載入成功時觸發 用來備份原始資料
function onLoadSuccess() {
olddata = objDeepCopy(mydg('getData').rows);
}
// onAfterEdit:該事件在完成編輯並且編輯器銷燬之後觸發 判斷資料是否被修改
function onAfterEdit(rowIndex, rowData, changes) {
var bl = false;
var Index;
//updatedrows
if (olddata) {
Index = rowIndex - (mydg('getRows').length - olddata.length);
//判斷元資料是否被修改
if (Index >= 0) {
bl = isObjectValueEqual(rowData, olddata[Index], [ 'ename',
'hiredate', 'sal', 'deptno', 'dname' ]);
}
}
if (Index >= 0) {
if (!bl) {
if (!updatedrows.contains(rowData)) {
updatedrows.push(rowData)
}
} else {
updatedrows.remove(rowData)
}
}
}
//儲存
/*datagrid當然也有獲取updated的方法 不過我個人覺得這個方法實在太簡單了。他會將你點選過編輯的行的都獲取到 (新增加的沒有)主要還是因為我們開啟過編輯模式後 如何你的欄位值有非string型別的它都會將它變為string型別的 當值型別改變他也會預設這行是修改過的。所以我們就用自己寫好的updatedrows就可以了 */
function accept() {
if (endEditing()) {
var inserted = mydg('getChanges', "inserted");
var deleted = mydg('getChanges', "deleted");
if (inserted.length > 0 || updatedrows.length > 0
|| deleted.length > 0) {
var effectRow = new Object();
if (inserted.length) {
effectRow["inserted"] = JSON.stringify(inserted);
}
if (deleted.length) {
effectRow["deleted"] = JSON.stringify(deleted);
}
if (updatedrows.length) {
effectRow["updated"] = JSON.stringify(updatedrows);
}
$.post("${pageContext.request.contextPath}/emp/batchData",
effectRow, function(result) {
if (result.success){
$.messager.alert("提示", "提交成功!", "info");
$('#dg').datagrid('reload'); // reload the user data
} else {
$.messager.show({ // show error message
title: 'Error',
msg: result.msg
});
}
}, "JSON").error(function() {
$.messager.alert("提示", "提交錯誤了!");
});
} else {
$.messager.alert("提示", "請先編輯資料!!!", "info");
}
}
}
//刪除
function removeit() {
//var Index = index - (mydg('getRows').length - olddata.length);getRowIndex
if (endEditing()) {
//id陣列
var ids = [];
var rows = mydg('getChecked');
if (rows.length > 0) {
for (var i = 0; i < rows.length; i++) {
ids.push(rows[i].empno);
}
}
if (ids.length > 0) {
$.messager.confirm('批量刪除確認', '你確定要刪除編號為' + ids.join(',')
+ '的員工嗎?', function(r) {
if (r) {
var rowarr=mydg('getData').rows;
for (var i = 0; i < ids.length; i++) {
var Index = rowarr.indexOf(rows[0]) - (mydg('getRows').length - olddata.length);
//判斷元資料是否有資料被刪除?
if (Index>=0) {
//刪除元資料中被刪除的資料
olddata.splice(Index,1);
//刪除更新陣列中被刪除的資料 因為既然資料已經被刪除我們就沒必要在將該資料拿到後臺進行更新操作了 直接刪除就可以了
updatedrows.remove(rows[0])
}
//刪除指定行
mydg('deleteRow', rowarr.indexOf(rows[0]));
rowarr=mydg('getData').rows;
}
}
});
} else {
$.messager.alert("提示", "請選擇要刪除的行", "error");
}
}
}
//撤銷
function reject() {
mydg('rejectChanges')
updatedrows = [];
editIndex = undefined;
}
});