Avoid double click 防止使用者雙擊按鍵

Avoid double click 防止使用者雙擊按鍵

防呆機制對於功能來說是不可缺少的,若少做了往往會造成系統問題(品質),

例如:有的功能因為較花資源,或因系統資源不足回應時間較慢,

使用者就會不斷地去點擊按鍵,誤以為這樣會比較快得到回應,

往往卻讓系統掛點的更快,甚至會有double pay … 嚴重的交易異常,

第一步可以先做的就是防止使用者double click,

在網路上有些解決,本文中做匯整,以便日後查找。

 

(一)一些基本觀念:

1. 頁面只有Button時, 產生的html 只有submit

2. Button 加入OnClientClick屬性, 產生的html 多了 onclick 事件的程式

Tip: onclick 即是一個function, 若你寫成 OnClientClick=”return false; this.value=1;”後面那段code 永遠都呼叫不到 …

3. 頁面加入Validator 後, 會有驚人多的Code, 很難一言以蔽之, 我們就不探究了,

簡單的說 onclick 事件中多了呼叫WebForm_DoPostBackWithOptions() ,

(下面Code仔細看是有問題的喔)

Tip: OnClientClick 的 return 程式碼會造成Validator失效 !!

此外在form 也多了onsubmit事件並呼叫WebForm_OnSubmit();

如果有興趣, 可以用 IE8 或 Firefox 追蹤, 我簡單的捉出幾個重點, 繪成循序圖, 方便大家來看

validator

由上圖 你可以發現實際執行驗證的程式碼是在 WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions( … )) 中

而 ValidatorOnSubmit 是依照其結果來中斷Postback的動作.

所以當你在OnClientClick加 return 時會造成沒有去做執行驗證, 故ValidatorOnSubmit亦不會幫你block postback.

(二)解決方案

一. Postback 且無Validator

因為直接讓button 的disabled , 會造成頁面中斷Postback , 所以要加一個強迫送出的程式碼

參考:Jason Whitehorn

環境:.NET Framework 2.0 (ok)

C# Code 如下:

 

二. Postback 且有Validator

原本:“Avoid double click” > “驗證成功”> ”Postback”(當驗證失敗時,按鍵亦無法恢復)

改成:“驗證成功” > “Avoid double click” > “Postback”

因要改變其呼叫流程, 故先引用 Page_ClientValidate(), 然後 Button.disabled , 最後再強迫送出程式碼.

參考:ta4ka

環境:.NET Framework 2.0 (ok)

C# Code 如下:

        {
            System.Text.StringBuilder sbValid = new System.Text.StringBuilder();
            sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");
            sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");
            sbValid.Append("this.value = 'Please wait...';");
            sbValid.Append("this.disabled = true;");
            sbValid.Append(this.Page.ClientScript.GetPostBackEventReference(button, ""));
            sbValid.Append(";");
            button.Attributes.Add("onclick", sbValid.ToString());
        }

實際產生的JavaScript Code 如下:

	if (Page_ClientValidate() == false) { return false; }
} 
this.value = 'Please wait...';
this.disabled = true;
__doPostBack('btnOk','');

說穿了就是把 function WebForm_DoPostBackWithOptions() 重組

以上的sample 其實是不完整, 因為如果你附加了WebForm_PostBackOptions 的 actionUrl, trackFocus, clientSubmit 屬性

將會無法處理到, 到時要再多加以下這整段Code來處理

        if ((typeof(options.actionUrl) != "undefined") && (options.actionUrl != null) && (options.actionUrl.length > 0)) {
            theForm.action = options.actionUrl;
        }
        if (options.trackFocus) {
            var lastFocus = theForm.elements["__LASTFOCUS"];
            if ((typeof(lastFocus) != "undefined") && (lastFocus != null)) {
                if (typeof(document.activeElement) == "undefined") {
                    lastFocus.value = options.eventTarget;
                }
                else {
                    var active = document.activeElement;
                    if ((typeof(active) != "undefined") && (active != null)) {
                        if ((typeof(active.id) != "undefined") && (active.id != null) && (active.id.length > 0)) {
                            lastFocus.value = active.id;
                        }
                        else if (typeof(active.name) != "undefined") {
                            lastFocus.value = active.name;
                        }
                    }
                }
            }
        }
    } 
    
    if (options.clientSubmit) {
        __doPostBack(options.eventTarget, options.eventArgument);
    }