Greasemonkeyでキー制御したい時の書き方
イベントリスナの登録
document.addEventListener('keydown', function (e) { // 処理 }, false);
他にkeypressってのもあるけど、keydownをお勧め。
理由は確かGoogle chromeでkeypressにすると、Ctrl+a(全て選択)のようにデフォルトで別動作が定義されていた場合にそちらが先に動いてしまうため(だったはず)。
押されたキーの取得
var shortcutKey = 'a'; document.addEventListener('keydown', function (e) { var pressed = String.fromCharCode(e.which).toLowerCase(); pressed = (e.ctrlKey ? 'C-' : '') + (e.altKey ? 'A-' : '') + (e.shiftKey ? 'S-' : '') + pressed; if (pressed == shortcutKey) { // 処理 } }, false);
イベントのwhich要素で押されたキーの番号を取得して、StringのfromCharCode関数で文字に直す。
この時、念のため文字列のtoLowerCase関数を使って小文字に統一しておく。
コントロールキーを押していたら文字列の先頭に"C-"を追加、などとしておけば、
Ctrl+aのような同時押しも指定可能になる。
最後に予め用意しておいたショートカットと、
イベントから取得した文字列が一致するかどうかを確認する。
当然この方法ではTabキーや矢印キーなどの特殊キーは制御出来ないので、そこは頑張って下さい。
テキストの入力中に無効化
var shortcutKey = 'a'; var INPUTS = ['INPUT', 'TEXTAREA']; // ←入力欄タグ一覧 document.addEventListener('keydown', function (e) { var pressed = String.fromCharCode(e.which).toLowerCase(); pressed = (e.ctrlKey ? 'C-' : '') + (e.altKey ? 'A-' : '') + (e.shiftKey ? 'S-' : '') + pressed; if (INPUTS.indexOf(e.target.tagName) == -1 && pressed == shortcutKey) { // ←入力欄判定 // 処理 } }, false);
文字の入力中にコマンドが暴発しても困るので、入力欄ではコマンドが動かないようにする。
イベントのtarget属性の持つtagNameで、イベント発動時にどこにフォーカスされているかを確認出来る。
入力欄としてはINPUTタグとTEXTAREAタグを指定したけど、他にもあるかも。
デフォルトの動作を無効化
var shortcutKey = 'a'; var INPUTS = ['INPUT', 'TEXTAREA']; document.addEventListener('keydown', function (e) { var pressed = String.fromCharCode(e.which).toLowerCase(); pressed = (e.ctrlKey ? 'C-' : '') + (e.altKey ? 'A-' : '') + (e.shiftKey ? 'S-' : '') + pressed; if (INPUTS.indexOf(e.target.tagName) == -1 && pressed == shortcutKey) { e.preventDefault(); // ← // 処理 } }, false);
例えばCtrl+Pにコマンドを割り当てた場合に、押すたびに印刷画面が出るのを防ぐ。
これはコマンドと一致することを確認した後で処理するようにしないと、
コマンド以外のキー入力も全て防いでしまうので注意。
多重起動を防ぐ
var shortcutKey = 'a'; var disableKey = false; // ← 多重起動無効化フラグ var INPUTS = ['INPUT', 'TEXTAREA']; document.addEventListener('keydown', function (e) { var pressed = String.fromCharCode(e.which).toLowerCase(); pressed = (e.ctrlKey ? 'C-' : '') + (e.altKey ? 'A-' : '') + (e.shiftKey ? 'S-' : '') + pressed; if (INPUTS.indexOf(e.target.tagName) == -1 && pressed == shortcutKey) { e.preventDefault(); if (!disableKey) { // ← 多重起動無効化フラグ確認 disableKey = true; // ← 多重起動を無効化 // 処理 disableKey = false; // ← 多重起動無効化を解除 } } }, false);
keydownはキーを押している間にどんどん発生するので、
処理をする直前に以降の処理を無効化するようにしておけば、多重起動を防げる。
非同期処理(HTTPリクエストなど)を行う場合はそちらの処理が終わった後で無効化を解けば良い。
テンプレ
ここまでをまとめた。
var shortcutKey = ''; var disableKey = false; var INPUTS = ['INPUT', 'TEXTAREA']; document.addEventListener('keydown', function (e) { var pressed = String.fromCharCode(e.which).toLowerCase(); pressed = (e.ctrlKey ? 'C-' : '') + (e.altKey ? 'A-' : '') + (e.shiftKey ? 'S-' : '') + pressed; if (INPUTS.indexOf(e.target.tagName) == -1 && pressed == shortcutKey) { e.preventDefault(); if (!disableKey) { disableKey = true; // 処理 disableKey = false; } } }, false);
以下は今回の方法を使ったスクリプトの例
pixivでブクマ追加時に自動でタグ補完したり、特定のタグを含んでいる場合に自動で非公開ブクマにしたりするGreasemonkeyスクリプト