jQuery - 中文輸入法與KeyDown/KeyPress事件

最近專案中引用了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補充!

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

歡迎推文分享:
Published 26 April 2011 07:32 PM 由 Jeffrey
Views: 46,243



意見

# 林奕忠 said on 09 November, 2012 10:53 PM

黑大的範例沒用到那個神人整合的事件

黑大用的是 後來瀏覽器普遍都支援的 input event  

help.dottoro.com/ljhxklln.php

黑大可用 IE8 測試看看就知道了

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<April 2011>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication