Edited at

【javascript】iOSに物理キーボードをつないでkeyupイベントでどのキーがupされたかを取得する

More than 1 year has passed since last update.


iOSの困った現象

iOSのデバイスに物理キーボードをbluetoothや有線でつないで操作するケースはままあると思います。

今日お客さんからiPadにつないだキーボードだと操作ができない旨のお話をいただき調べたところ、iOS+物理キーボード+safariの組み合わせでkeyupイベントのevent.keyCodeがみんな0になってしまうという不具合(仕様?)がありました。

結構前からそうみたいです。

StackOverflowにも同様の質問がいくつかありましたが解決はしていない模様。

https://stackoverflow.com/questions/28944171/e-keycode-in-ios-safari-on-keyup-event

↑現象は説明してくれてるんだけど答えが載ってない... ちなみにevent.whichも0でした。

https://stackoverflow.com/questions/45924702/ipad-bluetooth-keyboard-returns-keycode-of-0-for-any-key-with-onkeyup

↑矢印キーとESCなら取得できる


今回やりたかったこと

キーボードの特定のキーが押されている時間を取得したかったのでkeydownイベントとkeyupイベントの組み合わせがどうしても必要でした。


対応案


  1. keyup自体は動作する(keyCode=0が返るが...)のでkeypressでkeyCodeを取っておいてkeyupは取っておいたkeyCodeのkeyupとみなす

     (→複数キーの同時押しに対応できない!)


  2. iPadはiOSのせいにして諦める

     (→iPad前提の案件のため不可!)


  3. 上にあるように矢印キーを駆使して代替する

     (→最大で5つぐらいキーを押す必要があるため矢印キーだと足りない、ESCもあるけどちょっと)


  4. アプリにすれば何とかなる??

     (→アプリ経験ないので不可!)


  5. iPadはやめてsurfaceにしたらどうかと、surfaceの営業をかける


思いつくのはこれぐらいでしょうか。


調査

みんなできない言うても自分で調べないと納得できないので、調査を行います。

調査といってもeventの中身を見るだけですが。


  1. 手持ちのiPhoneを手持ちのmacと有線でつなぎます。

  2. iPhoneの「設定」>「safari」>「詳細」>「webインスペクタ」を有効にします。

  3. iPhoneとBluetoothでAppleのキーボードをペアリングします。

  4. サンプルのwebpageをiPhoneのsafariで開きます。

  5. macのsafariの開発者ツールから自分のiPhoneを指定します。

  6. iPhoneのsafari上でAppleのキーボードにてkeyupを行います。

  7. macのデバッガでconsole.log(event)の中身を見てみます。

コードは至ってシンプル(jquery)

$(function(){

$(document).keyup(function(ev){
console.log(ev);
});
});


調査結果

1キーを押下してみました。logは取れましたが...

altGraphKey: false

altKey: false
bubbles: true
ancelBubble: false
cancelable: true
charCode: 0
code: "Unidentified"
composed: true
ctrlKey: false
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
isComposing: false
isTrusted: true
key: "Dead"
keyCode: 0
keyIdentifier: "Unidentified"
keyLocation: 0
layerX: 0
layerY: 0
location: 0
metaKey: false
pageX: 0
pageY: 0
repeat: false
returnValue: true
shiftKey: false
srcElement: <body>
target: <body>
timeStamp: 132920459935500700
type: "keyup"
view: Window {}
which: 0

本当にcharCodeもkeyCodeもwhichも0...

キーを判定できそうな情報は皆無です。


解決方法

surfaceの営業マンになるしかないかと諦めかけていたのですが、いろいろいじくってたらログにkey: "1"が出ました。

なんでだろうと思って2のキーを押してみるとちゃんとkey: "2"が…

よくよく見てみるとinputタグのtext入力欄にフォーカスされていました。

textにフォーカスされている状態でkeyupを行うとevent.keyに押下したキーが取得できるようです。

ここまで取れればあとは何とかできそう。

<input type="text" id="tmp"/>をどっかに隠して用意しておいて、

var current_key = undefined;

$(document).keydown(function(event){
$("#tmp").focus();
if(event.key) {
if(event.key !== "Dead"){
current_key = event.key;
}
}
}).keyup(function(event){
if(event.key === current_key) {
something()
}
current_key = undefined;
});
$("#tmp").blur(function(){
if(current_key !== undefined){
something();
}
current_key = undefined;
});

function something(){
//何か処理
}

keydownでテキストボックスにfocus()しておいて、keyup時のkeyを取得、何かの拍子にテキストボックスのfocus()が外れてしまったらそこでkeyupしたこととみなす、

尚windowsではshiftキー単体のkeyupでevent.keyに"Shift"とはいったのですが、iPad+物理キーボードではkeyupイベント自体が動きませんでした。

この辺りはどうしようもなさそうです。


まとめ

・iOS+物理キーボード+safari環境でkeyupイベントは実行できるがevent.keyCodeが常に0

・上記環境のkeyupを使いたい場合は、テキストボックスにフォーカスした状態でkeyupし、event.keyにて打たれたキーの文字を取得する必要がある。

・ShiftキーやAltキーなどの単体のkeyupイベントは上記環境では取得できない。