dwi2的碎念

不能只是曬網

JavaScript KeyboardEvent

| Comments

最近我因為工作上的需要擷取user在網頁上所有keydown, keyup的事件, 過程中發現一些有趣的事情, 這裡特別跟大家介紹一下

KeyboardEvent裡的keycode/which

通常我們會用類似下面的event callback取得keycode

1
2
3
4
var keyboard_hook = function (eventt) {
  var key = event.keyCode || event.which;
   // do something
}

因為不是每個瀏覽器實作的KeyboardEvent都有keyCode這個properties, 所以通常會先偵測是否有keyCode, 沒有就取用which

當然更省事的作法就是直接用jQuery幫我們包好的event handler以及jQuery Event Object, jQuery會幫忙處理相容性問題, 直接拿jQuery Event Object的which即可

但這裡有個很奇妙的地方要注意, 當keypress發生時, event的keyCode或which的內容是該按鍵代表的char值(ASCII); 但在keydown或keyup事件中, keyCode或which的內容卻是瀏覽器給予按鍵定義的scancode(沿用微軟的稱呼), 而且scancode會因為瀏覽器不同而有不同的值.

按鍵的char值和scancode是不同的, 因為不是所有的按鍵都有對應的char值, 例如shift, ctrl, alt, capslock…等

這部份詳細來龍去脈, 網路上有人整理好一篇非常完整的介紹http://unixpapa.com/js/key.html, 如果各位工作上要處理瀏覽器按鍵事件的話, 這篇非常值得一讀

瀏覽器Scancode差異

為了取得一致的scancode, 我後來都只使用keydown跟keyup事件(keypress帶char值, 因此不是所有按鍵都有keypress事件, 例如ctrl, shift這些)

scancode的定義, 主流瀏覽器大約97%相同(指IE, Chrome, Firefox, Safari), 這次的例外不是IE(我知道大家都很想未看先罵IE XDD), 例外的居然是Firefox呀!!!真是太令人意外了!!!

Firefox跟其他瀏覽器的主要差異如下圖:

Firefox跟其他瀏覽器的scancode主要差異

資料來源: MDN

好用Library

如果想要偵測keydown, keyup事件, 而且想要正確得知哪個按鍵被按下, 除了自己辛苦寫scancode mapping table之外, 還有更輕鬆的方法 – 就是使用別人寫好的JavaScript library, 我再網路上目前有看到這兩個

KeyboardJS

Mousetrap

我沒有試過mousetrap就直接使用KeyboardJS, 主要原因是看上KeyboardJS有個method很合用:

1
KeyboardJS.activeKeys()

可以一次取得目前被按下的所有按鍵.

不過KeyboardJS的一個小缺點就是API文件說明跟實際上執行的狀況稍有出入, 以KeyboardJS.on()為例, 它的格式為

1
KeyboardJS.on(keyCombo, onDownCallback, onUpCallback);

其中onDownCallback和onUpCallback是function object, 網頁上說明帶入三個參數: key event, keys pressed, key combo string

但我實際測試時發現只有傳入第一個參數key event, 仔細追source code之後發現還真的只有傳key event, 後面兩個都只是唬人的…orz

另外一點很可惜的是KeyboardJS也沒有注意到Firefox scancode的獨特之處, 我就只好順手幫作者修正這個問題啦! 修正版的code在這: https://github.com/dwi2/KeyboardJS

只是我送了pull request, 原作者過了兩天都還沒有理我呢… (大概是我的description寫太少吧! XDDD)

Comments