使用者抱怨當使用某編輯UI網頁輸入資料時,常要切換多個<input type=”text”>輸入文字,一不留神讓欄位失去焦點(文字游標沒有停在輸入欄位上閃爍),卻按下Backspace(後退鍵)想刪除文字,此時會觸發瀏覽器的快捷鍵跳回到前一網頁,辛苦輸入的資料瞬間化為烏有,徒留"暗"聲繞樑,久久不絕於耳...

針對這個問題,最直覺的解法是攔截按鍵事件沒收Backspace回上頁的功能。我想到的寫法是攔截document的keydown事件,檢查e.target.type,若觸發來源不是輸入文字欄位,就停用按鍵功能。程式不寫難,範例如下:

<!DOCTYPE html>
<html>
<head>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js" 
     type="text/javascript"></script>  
     <script type="text/javascript">
         $(function () {
            //除了input text外,停用Backsapce,防止不慎回前一頁
             $(document).keydown(function (e) {
                 //採用demo建議 多考量"textarea"
                 if (e.which == 8 && !(e.target.type == "text" || e.target.type == "textarea")) 
                        e.preventDefault();
             });
         });
     </script>
</head>
<body>
<form id="form1" method="get">
    <div>T1: <input type="text" id="t1" value="1" /></div>
    <div>T2: <input type="text" id="t2" value="2" /></div>
    <div>T3: <input type="text" id="t3" value="3" /></div>
    <div>T4: <input type="text" id="t4" value="4" /></div>
    <div><input type="submit" id="send" value="Send" /></div>
</form>
</body>
</html>

然而,我們還可以再多想一點,除了按Backspace鍵,使用者也可能不慎點到網頁上其他連結而被轉往其他網頁,或是不小心關閉瀏覽器,一樣都可能造成輸入後還沒儲存的資料遺失。因此,更理想的做法是在發現使用者修改過資料未儲存就離開時發出提醒,請求確認是否真的要離開。

以下是一個簡單的範例,透過輸入欄位的change事件(本範例只針對input:text,實務上應涵蓋所有資料更動操作)觸發onbeforeunload事件的設定(onbeforeunload的應用,可參考保哥的介紹),如此當使用者要離開網頁時,可跳出警告訊息要求使用者確認;當使用者按下儲存鈕(或離開鈕)時,會取消onbeforeunload設定,不再需要提醒使用者。如此可減少使用者因操作失誤而遺失資料的機會,編輯介面的貼心度就更上一層樓囉~~

<!DOCTYPE html>
 
<html>
<head>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.js" 
     type="text/javascript"></script>  
     <script type="text/javascript">
         $(function () {
             function setUnloadWarning(enabled) {
                 window.onbeforeunload =
                    enabled ? showWarning : null;
             }
             function showWarning() {
                 return "資料尚未儲存,確定要離開嗎?"
             }
             $("input:text").live("change", function () {
                 setUnloadWarning(true);
             });
             $("input:submit").click(function () {
                 setUnloadWarning(false);
             });
         });
     </script>
</head>
<body>
<form id="form1" method="get">
    <div>T1: <input type="text" id="t1" value="1" /></div>
    <div>T2: <input type="text" id="t2" value="2" /></div>
    <div>T3: <input type="text" id="t3" value="3" /></div>
    <div>T4: <input type="text" id="t4" value="4" /></div>
    <div><input type="submit" id="send" value="Send" /></div>
</form>
</body>
</html>

Comments

# by demo

當表單包含了 textarea 那使用者想刪除 textarea 的文字就變成不可能了,所以我稍微修改一下判斷方式 http://jsfiddle.net/Um2pA/

# by Jeffrey

to demo, 感覺你的判斷方式涵蓋性更大,已修改本文,謝謝回饋。

# by demo

抱歉,發現了 Bug 依據上方這種寫法,如果只判斷 e.target.type == undefined 有可能因為使用者點選 Checkbox 或是 RadioButton 這種可以 focus 的表單元件後直接按下 backspace 依然可以回到上一頁....目前還是乖乖的判斷 text 和 textarea ,沒有想到什麼比較漂亮的方法

# by yyfish

判斷有誤喔, 少了一個"!", 這樣變成text裡面不能倒退了 if (e.which == 8 && !(e.target.type == "text" || e.target.type == "textarea")) e.preventDefault();

# by George

邏輯有點奇怪...原判斷式是:若按下 backspace 鍵,而且欄位為 textbox 或 textarea,就阻止預設的行為... 但是在 textbox 與 textarea 的預設行為是刪除文字,這樣變成無法刪除了! 好像應該是這樣: if (e.which == 8 && (e.target.type != "text" && e.target.type != "textarea")) 還請不吝指教~

# by Jeffrey

to yyfish, George,謝謝指正,程式範例少了一個"!",已校正。

# by French

你好 有借用這個sample code 來用 的確可以使用 但是有碰到個問題,是可以優化的。 那就是 當input 欄位是 readonly or disabled 時,鼠標點到上面在按鍵盤上的倒退鍵時,一樣會觸發上一頁事件。 建議可以補上下面的判斷式 if($(e.target).length > 0) { if($(e.target).attr("readonly") || $(e.target).attr("disabled")) { e.preventDefault(); }} 這樣就能防止target在不能輸入的input欄位時的上一頁事件 我大概手key的 如果code 有 error還請包涵 不過邏輯看得懂應該就好

# by Jeffrey

to French, 謝謝你的回饋補充。

Post a comment