標題有點長實在不知道該怎麼下 = =
前言 :
最近被要求做一個功能,這個功能是這樣子的~~
文章想直接跳到 JSON 操作 請按此,想跳到 離開頁面提示 的請按次
有一個落落長的表單要使用者填寫
然後在使用者離開這個表單的時候要提醒她資料有修改是否要離開?
然後如果她不離開按下儲存按鈕
就要列出有異動的欄位 and 更改的值 (後來只列出欄位不列出值了)
畫面做成像下圖這樣子,感覺像是要簽入原始碼控制般的介面
然後寫入資料庫,紀錄 log + 版本號
然後我就放了一個全域物件來記錄一下異動的資訊
var grobal = grobal || {};
grobal = {
changeTimes: 0,
changeControl: []
}
然後下面監控頁面上欄位的異動
這邊比較有問題的是 textarea,因為textarea 已經換成 ckeditor 所以抓不到 change
要用特別的方法之後再提,不過還是先寫上去
$("input,select,textarea").change(function () {
});
然後我每個項目都有自訂txt屬性,去說明欄位是幹嘛的
ex : <input type="text" txt="作者">
再來一步一步說明實在太麻煩了,直接把程式片段貼出來好了 @@
/*
紀錄頁面異動全域物件
changeTimes:異動次數,changeControl:異動的陣列實字組
*/
var grobal = grobal || {};
grobal = {
changeTimes: 0
changeControl: []
}
//監控頁面上控制項所有異動 (除ckeditor)
$("input,select,textarea").change(function () {
var val = $(this).attr("txt");
//push 前先移除該項目舊紀錄
removeJArray (grobal.changeControl, "txt", val);
//紀錄異動欄位
grobal.changeControl.push(
{ txt: val }
);
//紀錄異動次數
grobal.changeTimes += 1;
});
//刪除JSON裡面陣列中的某個指定值
function removeJArray (arr,pid, val) {
for (var i = 0; i < arr.length; i++) {
var cur = arr[i];
if (cur[pid] == val) {
arr.splice(i, 1);
break;
}
}
}
然後隨便異動幾個欄位,檢查一下JSON內容
alert(JSON.stringify(grobal));
就會輸出如下圖的JSON
有了異動資料,再來就是使用者要離開前要提示她是否要存檔
就像 gmail 的離開提示,這邊用 beforeunload 事件
$(window).on("beforeunload", function (e) {
e = e || window.event;
if (e) {
e.returnValue = (function () {
if (grobal.changeTimes > 0) {
return "您異動了一些資料,確定不儲存離開?";
}
})();
}
//給chrome + safari用
return (function () {
if (grobal.changeTimes > 0) {
return "您異動了一些資料,確定不儲存離開?";
}
})();
});
然後IE、Chrome的判斷方法不同,所以很蠢的加了兩個幾乎一樣的訊息
這邊有空可以再寫的好一些
邏輯就是如果 grobal 這個全域物件中的 changeTimes 屬性值 > 0
就表示有異動囉
再來按下頁面中的存檔按鈕要跳出類似原始碼簽入的dialog 給user 輸入異動原因
前面的 UI 就不貼了,直接看 script
假設我的儲存按鈕是
<input type="button" class="save" value="儲存">
//按下儲存按鈕,因為我儲存按鈕有兩個,所以用 class="save"
$(".save").click(function () {
//因為儲存會postback,也算是離開頁面
//所以要先解除 beforeunload 事件
$(window).unbind("beforeunload");
var arr = [],str = "",arrlist = grobal.changeControl;
//把grobal.changeControl 中儲存的異動欄位寫到空陣列中
for (var i in arrlist) {
arr.push(arrlist[i].txt);
}
//直接用 .join 串在一起,然後填入前端頁面的容器中
$("#update_fieldmsg").html(arr.join("、"));
$('#signin').modal("show");
return false;
});
就會長的如下圖
再來說明一下 ckeditor 要怎麼監控有沒有被異動
ckeditor 有提供 checkDirty 方法來判斷有無異動
checkDirty()
http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.editor.html#checkDirty
雖然 on change 也可以監控 (但是要先得到 ckeditor 的 instances)
但是用 change 會有個問題..........使用者每打一個字都被認為是一次 change
但如果每打一個字都要記錄一次異動效能也太差
change 事件比較適合用在計算字數
所以監控異動的話用 checkDirty() 比較適合
下面例子是監控頁面上所有 ckeditor 異動
然後一樣寫到紀錄異動的物件
for (var i in CKEDITOR.instances) {
var ckeditor = CKEDITOR.instances[i];
//判斷ckeditor異動
if (ckeditor.checkDirty()) {
//取得 ckeditor 的名稱,也就是ID
var val = ckeditor.name;
//先移除之前異動紀錄,如果有的話
removeJArray (grobal.changeControl, "txt", val);
//寫入新異動紀錄
grobal.changeControl.push(
{ txt: val }
);
grobal.changeTimes += 1;
}
}
再來要記錄幾個比較常用的 JSON 操作方式,有些算是蠻基本的陣列操作
一、首先是最常用的
JSON.stringify
MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
它可以把你的 JSON 物件轉為 JSON 字串,方便傳輸或利用
ex : 我宣告一個物件實字
var grobal = grobal || {};
grobal = {
changeTimes: 0,
changeControl: []
}
JSON.stringify(grobal ) 就會得到字串
"{"changeTimes":0,"changeControl":[]}"
二、如果要新增 JSON 內的陣列元素
push
MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
其實網址內有範例了,不過還是寫一下
如果我要在下面 grobal 物件的 changeControl 陣列中新增元素
grobal = {
changeTimes: 0,
changeControl: []
}
grobal.changeControl.push(
{ "control" : "cname" }
);
結果就會變成這樣
"{"changeTimes":0,"changeControl":[{ "control" : "cname" }]}"
三、刪除 JSON 內指定元素
delete
MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
網址裡面也有範例,不過我還是摳一下網路上的用法
假設 JSON 如下
var myObj = {'test' : {'key1' : 'value', 'key2': 'value'}}
然後要刪掉 key1 就這樣下
delete myObj.test.key1;
就會變成
"{'test' : {'key2': 'value'}}"
四、刪除元素內指定元素值
這個可能就要靠手工
例如 JSON 如下 :
grobal = {
changeTimes: 0,
changeControl: [
{ "control" : "cname" },
{ "control" : "ename" },
{ "control" : "bokno" }
]
}
如果要刪除 { "control" : "ename" }
可以利用寫好的這個 function
function removeJArray (arr,pid, val) {
for (var i = 0; i < arr.length; i++) {
var cur = arr[i];
if (cur[pid] == val) {
arr.splice(i, 1);
break;
}
}
}
只要這樣下就可以了
removeJArray (grobal.changeControl, "control", "ename");
五、 將 JSON 字串轉為 JSON 物件
JSON.parse
MSDN : http://msdn.microsoft.com/zh-tw/library/cc836466(v=vs.94).aspx
MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
用法如下
var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);
document.write(contact.surname + ", " + contact.firstname);
或利用 jQuery 的 parseJSON
jQuery.parseJSON()
http://api.jquery.com/jquery.parsejson/
六、快速的尋找 JSON 中的值
可以用 JSON Select
它可以讓你用簡單下 selector 的方式找到你要的值
到它網站上玩玩範例就會知道有多好用了
以下有想到或看到什麼好用的東西再補充
留言列表