コンテンツにスキップする

ユーザースクリプトでショートカットキーを実装してみました

投稿時刻2024年12月5日 16:05

ユーザースクリプトでショートカットキーを実装してみました。

今までは Shortkeys という拡張機能でショートカットキーの処理をしていました。
しばらく前から動作が不安定となっており、リポジトリを半年ぐらい監視していましたが、なかなか更新されない状況が続いています。

ですので、 Violentmonkey というユーザースクリプトの拡張機能を使い始めました。
Tampermonkey という拡張機能もありましたが、 OSS ではなかったので使いませんでした。

目次

ユーザースクリプトでショートカットキーを処理する

下記のコードをユーザースクリプトとして追加します。
それから適当なページを開き、ショートカットキーを押します。

// ==UserScript==
// @name        Example
// @namespace   My Custom Scripts
// @match       *://*/*
// @grant       none
// @version     1.0
// @author      Kouki Itou
// @description 11/30/2024, 12:19:00 PM
// ==/UserScript==

function registerHotkeys(options = []) {
	if (!options?.length) {
		return;
	}

	// 押されたキーの順序を記録する。
	const keySequence = [];

	// 順序の最大キー数をオプションから取得する。
	const maxSequenceLength = Math.max(...options.map((o) => o?.sequence?.length));

	document.addEventListener("keydown", (event) => {
		// console.log(event);
		// console.log(event.key);

		// フォームの要素の場合、処理しない。
		if (
			event?.target?.tagName === "INPUT" ||
			event?.target?.tagName === "TEXTAREA" ||
			event?.target?.tagName === "SELECT" ||
			event?.target?.tagName === "BUTTON" ||
			event?.target?.isContentEditable
		) {
			return;
		}

		// 押されたキーを記録する。
		keySequence.push(event.key.toLowerCase());

		// 配列の長さを制限する。
		if (keySequence.length > maxSequenceLength) {
			// 古いキーを削除する。
			keySequence.shift();
		}

		function isSubarray(baseArray, subArray) {
			if (subArray.length === 0) {
				return true;
			}

			for (let i = 0; i <= baseArray.length - subArray.length; i++) {
				let match = true;

				for (let j = 0; j < subArray.length; j++) {
					if (baseArray[i + j]?.toLowerCase() !== subArray[j]?.toLowerCase()) {
						match = false;
						break;
					}
				}

				if (match) {
					return true;
				}
			}
			return false;
		}

		const option = options?.find(function (option) {
			// console.log(option);
			// console.log(keySequence);

			const result = isSubarray(keySequence, option?.sequence);
			if (result) {
				return option;
			}

			return;
		});

		if (!option || !option?.sequence || !option?.callback) {
			return;
		}
		// console.log(option);

		option?.callback();

		keySequence.length = 0;
		return;
	});
}

registerHotkeys([
	{
		sequence: ["Control", "q", "a"],
		callback: () => {
			console.log("Ctrl + Q, then A detected!");
		},
	},
	{
		sequence: ["Control", "q", "q"],
		callback: () => {
			console.log("Ctrl + Q, then Q detected!");
		},
	},
	{
		sequence: ["Control", "q", "w"],
		callback: () => {
			console.log("Ctrl + Q, then W detected!");
		},
	},
	{
		sequence: ["Control", "q", "e"],
		callback: () => {
			console.log("Ctrl + Q, then E detected!");
		},
	},
	{
		sequence: ["Control", "q", "e", "s"],
		callback: () => {
			console.log("Ctrl + Q, then E and S detected!");
		},
	},
]);

ショートカットキーで前後のページに移動する

下記のようにコードを記述すれば、前後のページに移動するショートカットキーを実装することができます。

registerHotkeys([
	{
		name: "Back to previous page",
		sequence: ["Control", "ArrowLeft"],
		callback: () => {
			window.history.back();
			return;
		},
	},
	{
		name: "Go to next page",
		sequence: ["Control", "ArrowRight"],
		callback: () => {
			window.history.forward();
			return;
		},
	},
]);

おわりに

ユーザースクリプトでショートカットキーを実装することができました。
手動でおこなっているような作業をショートカットキーで自動的におこなうことができるようになりますので便利だと思われます。


参考記事