物理キーボードに繋いだiPadでカーソル移動する
2019/5/20
iPadOSではなく、iOSの話です
前提共有
Scrapboxの編集エリアは
目に見えるtextareaやinputは存在しない
その代わり、隠しtextareaが存在する
IMEでの日本語変換するために使っている
PCやAndroidではここで矢印キーのkey eventを監視している
これまでのiOSブラウザに関する調査
隠しtextareaにfocusが当たっている状態で、矢印キーを押すと
onKeyDown, onKeyPress, onKeyUp など、すべてeventが飛んでこない
隠さないtextareaを置いて試しても同様
→ onKeyXXX をソースとして矢印キーの押下を判定するのは無理
解決
既存の隠しtextareaに役割を一つ増やす
textarea内の隠しテキストを工夫する
上下左右の移動を検出するため 2列 × 3行 の隠しテキストを用意し、常にカーソルを中央で待機させる
以下、詳説
onselectionchange とは
以下の事象が発生した時にeventを発行する
選択範囲が変わった時
カーソル位置が変わった時
selectionStart === selectionEnd である範囲選択の特殊な状態、と捉える
iOSでもしっかり発火された。これは使える daiiz.icon*2
モードが2つ存在する
カーソル移動 (onselectionchange) を検知するモード
従来の隠しtextareaでの文字入力モード
モードごとに隠しtextareaが必要になる
モードの切り替えとして、適切なタイミングでfocusを移し合わないといけない
これはかなり難しく、絶対に安定しない
上のアイデアを改良した本手法でのミソ
隠しtextareaは、既存のもの1個でよい
focus移し合い問題がなくなった
モードの切り替え判定
onKeyDownを検知した時
→ 文字入力モード
実装に即した説明としては「カーソル移動検知モード OFF」
disableCursorMovementDetector()
(矢印キーが押された場合は絶対にevent来ない。来たらこんな苦労要らない。)
onFocus、入力確定、action完了した時
→ カーソル移動検知モード
resetAndEnableCursorMovementDetector()
各モードでの動作
文字入力モード
入力開始直後ならば、textarea内のテキストをクリア
他は従来どおり、変更なし
カーソル移動検知モード
textarea.selectionStartの値を取得して移動方向を判断する
移動方向を知るために、textarea内のテキストを\t\t\n\t\t\n\t\tにしてある
カーソルの初期位置を中央 (4) にしておき、移動検出のたびに4に戻すことで無限に検出できる
戻さない場合、4 → 1 に移動した以降は上方向を検出できなくなる
https://nota.gyazo.com/3faf963eb5cdf2889b0040a670fa1b08
番号はtextarea.selectionStartで取得できる値
得られた値に応じて Cursor.goUp, Cursor.goLeft, ... すればいい
https://nota.gyazo.com/63e46841f27e46b5699e443fd14e98f2
操作動画撮った daiiz.icon
https://youtu.be/0SpAGufAV-U
今後 daiiz.icon
個人的にはこの2つは対応したい
iPad × 物理キーボードで範囲選択する (リリース済み)
const shiftKey = textarea.selectionStart !== textarea.selectionEnd
const direction = (selectionStart === 4) ? selectionEnd : selectionStart
iPad × 物理キーボードで Ctrl+I する (リリース済み)
便利ツールも作った