#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イベントの組み合わせがどうしても必要でした。
#対応案
-
keyup自体は動作する(keyCode=0が返るが...)のでkeypressでkeyCodeを取っておいてkeyupは取っておいたkeyCodeのkeyupとみなす
(→複数キーの同時押しに対応できない!) -
iPadはiOSのせいにして諦める
(→iPad前提の案件のため不可!) -
上にあるように矢印キーを駆使して代替する
(→最大で5つぐらいキーを押す必要があるため矢印キーだと足りない、ESCもあるけどちょっと) -
アプリにすれば何とかなる??
(→アプリ経験ないので不可!) -
iPadはやめてsurfaceにしたらどうかと、surfaceの営業をかける
思いつくのはこれぐらいでしょうか。
#調査
みんなできない言うても自分で調べないと納得できないので、調査を行います。
調査といってもeventの中身を見るだけですが。
- 手持ちのiPhoneを手持ちのmacと有線でつなぎます。
- iPhoneの「設定」>「safari」>「詳細」>「webインスペクタ」を有効にします。
- iPhoneとBluetoothでAppleのキーボードをペアリングします。
- サンプルのwebpageをiPhoneのsafariで開きます。
- macのsafariの開発者ツールから自分のiPhoneを指定します。
- iPhoneのsafari上でAppleのキーボードにてkeyupを行います。
- 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イベントは上記環境では取得できない。