◆ ショートカットキーを簡単に作るライブラリ
◆ Ctrl キー的なショートカットキーの修飾キーを好きに選べる

好きなキーを修飾キーにしてショートカットキーを作れるライブラリを作ってみました
長くなるのでライブラリ部分のコードは Gist 参照です
特に新しいことなんて何もしてないですから

作った理由は よくあるショートカットキーの Ctrl などとの組み合わせってブラウザ側の機能が優先されたりすることがあったり 優先されなくてもブラウザのショートカットが使えなくなるのは不便なので ページ内専用のショートカットキー用の修飾キーがあったら便利そうと思ったからです

通常版

cmkey.js のものです
モジュールがインポートされると自動でリスナがセットされます
setOptions メソッドで設定を変更できます

import cmkey from "./cmkey.js"

const log = text => {
document.querySelector("#div").prepend(text, document.createElement("br"))
}

cmkey.setOptions({
modifier: "Space",
submodifier: "Home",
action: {
KeyA() { log("m-a pressed") },
KeyB() { log("m-b pressed") },
KeyC: "State1"
},
subaction: {
KeyX() { log("s-x pressed") },
},
stateactions: {
State1: {
"M/KeyA"() { log("m-c m-a pressed") },
KeyB() { log("m-c b pressed") },
"S/KeyC"() { log("m-c s-c pressed") },
KeyD: "State2",
},
State2: {
KeyA() { log("m-c d a pressed") },
},
},
except_selector: "input",
})
cmkey.addStateChangedListener(state => {
const state_elem = document.querySelector("#state")
state_elem.innerHTML = state || ""
state_elem.style.backgroundColor = {
State1: "yellow",
State2: "greenyellow",
}[state]
})

オプションとショートカットキー設定

modifier に修飾キーを設定します
Ctrl-A というショートカットキーの場合の Ctrl にあたるものです
修飾キーは modifier と submodifier の 2 つ設定可能です
今回は Space と Home キーにしてみました
Space-A や Home-Z をショートカットキーとして押したときに実行したい処理を設定できます

単純に Space キーを使いたい場合は Home-Space を入力します
modifier と submodifier のキーを入力するにはもう一方を押しながら入力すれば入力可能です

action には modifier キーを押しながら入力するキーの event.code をキーとしたオブジェクトを設定します
オブジェクトの値には実行する関数を指定します
文字列を指定すると state を切り替えます

subaction は submodifier 版の action のことで値の意味は同じです

stateactions には state に対する action を設定します
state が設定されている状態でのキー入力はここを見ます
state に対する action も action/subaction と基本は同じ意味です
ただしキーの意味が異なります

action のキーは modifier キーと組み合わせるキーでした
state の action でのキーはその state のときに単純に押すキーのことです
「KeyA」 とあれば普通に A キーを押したときの動きを設定します
modifier と submodifier との組み合わせも可能で それぞれ 「M/」 と 「S/」 から始めます

例えば 「M/KeyA」 はその state で modifier キーを押しながら A キーを押した時の処理を記述します
state の action でも値に文字列を書くことで state を切り替えられます
state のループも可能です

また オプションの selector と except_selector というキーに CSS セレクタを書くことでショートカットキーを有効にする場所を選択できます

state changed

state の変更を監視することも出来ます
addStateChangedListener に関数を設定すれば state が変わったときに state が引数に入って関数が呼び出されます

コードの例

上のコードの設定だと

Space-A を押すと 「m-a pressed」 とログが表示されます

Space-C を押すと state が State1 に切り替わります
リスナで state が State1 になると下に黄色いバーを表示するようにしているので 黄色いバーがでてきます
この状態でさらに D を押すと state が State2 に切り替わります
State2 では黄緑のバーを表示するようにしているので色が黄緑に変わります
この状態で A を押せば 「m-c d a pressed」 と表示されます

また except_selector が input なので input の上では Space-C を押しても state は変わらず c が入力されます


Demo

Observer 版

Cmkey_class.js の方です
こっちは Observer 系と使い方を似せてみました

import Cmkey from "./Cmkey_class.js"

const log = text => {
document.querySelector("#div").prepend(text, document.createElement("br"))
}

new Cmkey({
modifier: "Space",
submodifier: "Home",
action: {
KeyA() { log("m-a pressed") },
KeyB() { log("m-b pressed") },
KeyC: "State1"
},
subaction: {
KeyX() { log("s-x pressed") },
},
stateactions: {
State1: {
"M/KeyA"() { log("m-c m-a pressed") },
KeyB() { log("m-c b pressed") },
"S/KeyC"() { log("m-c s-c pressed") },
KeyD: "State2",
},
State2: {
KeyA() { log("m-c d a pressed") },
},
},
except_selector: "input",
onstatechange: state => {
const state_elem = document.querySelector("#state")
state_elem.innerHTML = state || ""
state_elem.style.backgroundColor = {
State1: "yellow",
State2: "greenyellow",
}[state]
}
}).observe(window)

モジュールをロードしただけでは何もしません
インスタンスを作って observe メソッドを実行して初めてリスナがセットされます

オプションは通常版と一緒ですが state 変更を監視するリスナもオプションで設定するようになっています
onstatechange プロパティにリスナ関数を設定します
observe でルート要素を指定してるので selector をオプションで指定する必要はなくなりました
複数箇所を observe せず window だけに observe を実行して selector で絞り込むことも可能です


Demo