Quantcast
Channel: Darkthread
Viewing all articles
Browse latest Browse all 428

【茶包射手日記】網頁 Enter 鍵誤擊刪除鈕疑雲

$
0
0

同事報案,在「以 MVVM 清單實作資料編輯介面」的經典應用場景(Knockout版範例Angular版範例)遇見怪事。新増一筆資料後,將焦點移至 <input type="text"> 輸入欄位,若按下 Enter 資料會莫名消失,按一次消失一筆…

程式用了 jQuery、Bootstrape、Knockout、KendoUI,加上一堆自訂程式庫,無法斷定是誰造成,只好抽絲剝繭,以能重現問題為原則,將掛載的程式庫及 DOM 元素一一拆除。歷經一番功夫,最後竟發現是個 HTML 基本觀念,某自以為資深的網頁設計老鳥,乖乖上了一課。

用一個超精簡範例重現問題:Live Demo

將焦點停在 Input A,按下 Enter 鍵會觸發 Button A 的 onclick 事件;但同樣狀況則不會發生在 Input B 與 Button B 上,關鍵在於 Input A 與 Button A 被包在 <form></form> 之中,而 Input B / Button B 沒有:

<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8">
<title>Enter on form</title>
</head>
<body>
<form>
<fieldset>
<legend>Inside Form</legend>
<inputtype="text"value="Input A"/>
<buttononclick="alert('Button A Clicked');return false;">Button A</button>
</fieldset>
</form>
<fieldset>
<legend>Outside Form</legend>
<inputtype="text"value="Input B"/>
<buttononclick="alert('Button B Clicked')">Button B</button>
</fieldset>
</body>
</html>

追究原因,「在輸入欄位按 Enter 送出表單」幾乎是所有瀏覽器的預設行為(感覺是網頁設計基本常識,但先前以寫 AJAX 跟 SPA 為主,碰 Form 的經驗不夠多,沒遇過還真就沒學到),Enter 送出表單可以理解,但瀏覽器送出前還幫忙按下 <form> 裡的第一顆按鈕倒是出乎意料。(在以上範例,Button A onclick alert 完要 return false,不然會觸發表單送出行為)再回頭觀察一開始的展示,按 Enter 被刪除的永遠是第一筆,由此可證。

2017-6-29補充: 貼文後不少網友提醒我 <button> 在各瀏覽器的預設 type 可能不同,而我這也才發現對 Chrome 與 IE 而言,<button> type 預設為 submit,是按 Enter 會連帶觸發按鈕的原因,改為 type="button" 後不再被 Enter 觸發點擊,但在這個案例中要防止表單被送出。感謝大家的回饋~(再上一課)

至於解決方案,用 prevent enter submit form 可以 Google 到一大票詢問與討論,常見做法是攔截 document 或 input 的 keypress 事件,在遇到 Enter 鍵時取消動作。但本案例倒不用這麼麻煩,該段程式以 AJAX 方式運作,用不到 <form> ,是因為寫在 ASP.NET WebForm 才被包在 <form> 中,只需將該段 HTML 移至 <form> 之外,問題即刻消失。

撇開這次遇到的特殊狀況,回到「按 Enter 會送出 Form 」行為上,其實存在爭議。Stackoverflow 上有一堆人詢問如何取消,卻也有人強力主張不該改掉(The Enter Key should Submit Forms, Stop Suppressing it),我則喜歡 StackExchange 的這篇觀點,作者以 Facebook 提供 Press Enter to send 選項為例(過去式 ,現已改版),認為交由使用者決定才是最佳選擇,附議!


Viewing all articles
Browse latest Browse all 428

Trending Articles