最近專案中引用了Telerik ASP.NET擴充元件AutoComplete輸入欄位,測試時發現偶爾會不聽始喚,輸入文字時無法觸發資料查詢,在Javascript Source Code裡反覆追蹤測試,燃燒了可觀的寶貴春青,終於理出頭緒: 問題在中文輸入法!

過去模糊地知道中文輸入在瀏覽器的鍵盤事件行為上有些特殊,但從未深究,這回算是比較清楚研究其中的差別。其實最明顯的差異是: 切到中文輸入法後,輸入文字將不會觸發KeyPress事件,只會有KeyDown,而且傳回的e.keyCode會一律是229。

寫了一段程式來做實驗:

<html>
<head>
<script type='text/javascript' 
        src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js'></script>
<script type='text/javascript'>
$(function() {
  var $log = $("#dvLog");
  $("#txtTest")
  .bind("keypress", function (e) {
      $log.append("<span>KeyPress: " + e.which + "</span> ");
  }).bind("keydown", function (e) {
      $log.append("<span>KeyDown: " + e.which + "</span> ");
  });
  }).bind("input", function (e) {
      $log.append("<span>Input!</span> ");
  });
  $("#btnClear").click(function() { $log.empty(); });
});
</script>
</head><body>
<input type="text" id="txtTest" />
<input type="button" id="btnClear" value="clear" />
<div id="dvLog" style="border: 1px solid red; font-size: 9pt; height: 50px;"></div>
</body>
</html>

我使用倉頡輸入法(New ChangJie 2010),以IE9測試,操作過程及結果如下:

    1. 切換到新倉頡輸入法,點txtTest取得焦點準備輸入文字
    2. 按【一】(M鍵),出現KeyDown: 229
    3. 按Enter鍵確定選字,此時出現Input!
    4. 按數字1,出現KeyDown: 229Input!
    5. 使用滑鼠將輸入法切回英文(不用按鍵切換避免觸發多餘事件)
    6. 按數字2,出現KeyDown: 50KeyPress: 50以及Input!

FireFox4測試的結果與IE9相同。若將IE9切成IE7相容模式,結果不太相同,看來並不支援Input事件

    1. 切換到新倉頡輸入法,點txtTest取得焦點準備輸入文字
    2. 按【一】(M鍵),出現KeyDown: 229
    3. 按空白鍵選字,再出現KeyDown: 229
    4. 按數字1,出現KeyDown: 229
    5. 使用滑鼠將輸入法切回英文(不用按鍵切換避免觸發多餘事件)
    6. 按數字2,出現KeyDown: 50KeyPress: 50

Chrome10的測試結果為:

    1. 切換到新倉頡輸入法,點txtTest取得焦點準備輸入文字
    2. 按【一】(M鍵),出現KeyDown: 229Input!
    3. 按空白鍵選字,出現KeyDown: 229Input!
    4. 按數字1,出現KeyDown: 229Input!
    5. 使用滑鼠將輸入法切回英文(不用按鍵切換避免觸發多餘事件)
    6. 按數字2,出現KeyDown: 50KeyPress: 50以及Input!

胡亂做個結論:

輸入欄位啟用中文輸入法時,將不會觸發KeyPress事件,而KeyDown事件中的KeyCode則固定傳回229。IE9, Firefox 4, Chrome支援按鍵Input事件,在IE9/Firefox4上可輔助判別中文輸入的細節,但IE7不支援,Chrome的行為不同。

綜合以上觀察,要自己搞出跨瀏覽器可以精準在使用者輸入每個字(不管有輸入法、不管中英文)時觸發的事件,看來是很艱鉅的任務。所幸網路上善心神人很多,找到一個不錯的解法, Cross browser input event for jQuery, 這個Plugin重新包裝了input事件,所以我們只需寫成:

$("#txtText").bind("input", function() {
    this.value; //可取得目前的文字內容
});

就能在每次輸入中文字或英文字時觸發input事件,雖然無法精確掌握每次的按鍵內容,但已可滿足掌握中文輸入模式下每次文字變動的需求。[2011-04-26補充]要精確抓取每一個按鍵的keyCode,可考慮使用KeyUp事件(但連選字時的上下鍵,送字的Space都包含在內),感謝drem補充!

為網路開發者社群按一個讚!


Comments

# by 林奕忠

黑大的範例沒用到那個神人整合的事件 黑大用的是 後來瀏覽器普遍都支援的 input event http://help.dottoro.com/ljhxklln.php 黑大可用 IE8 測試看看就知道了

Post a comment