Chrome拡張機能でWebページ上の要素を読み取ったり、操作を追加したりする場合に使うのが Content Scripts です。今回のGoogleカレンダー用ショートカット機能では、content.js がメインプログラムになります。
連載第3回では、content.js の基本構造と、キーボード入力を監視する仕組みを解説します。
Content Scriptsとは
Content Scriptsは、指定したWebページの中で実行されるJavaScriptです。今回の例では、Googleカレンダーの画面に挿入され、ページ内のDOMを読み取ったり、予定要素にCSSクラスを追加したりします。
通常のWebページに直接JavaScriptを書くのではなく、Chrome拡張機能の仕組みを使って外側から処理を追加するのがポイントです。
即時実行関数で全体を囲む
content.js の全体は、次のような即時実行関数で囲みます。
(function () {
// ここに拡張機能の処理を書く
})();
これはIIFEと呼ばれる書き方です。関数を定義すると同時に実行することで、変数や関数名がページ本体や他の拡張機能と衝突するリスクを下げられます。
Googleカレンダーのような大きなWebアプリでは、多くのJavaScriptが動いています。拡張機能側の変数をグローバルに置きすぎないことは、安定した動作のために重要です。
キーボード入力を監視する
ユーザーが z キーを押したことを検知するには、keydown イベントを使います。
window.addEventListener('keydown', function (event) {
if (event.key === 'z' || event.key === 'Z') {
navigateToTodayThenFocus();
}
});
event.key には、押されたキーの情報が入ります。小文字の z と大文字の Z の両方を判定しておくと、Shiftキーを押している場合にも対応できます。
入力中の誤作動を防ぐ
ただし、単純に z キーだけを監視すると問題があります。予定のタイトル入力欄や検索ボックスに文字を入力しているときにも、拡張機能が反応してしまうためです。
そこで、現在フォーカスされている要素を document.activeElement で取得し、入力欄であれば処理をスキップします。
window.addEventListener('keydown', function (event) {
if (event.key !== 'z' && event.key !== 'Z') {
return;
}
const activeEl = document.activeElement;
if (
activeEl &&
(
activeEl.tagName === 'INPUT' ||
activeEl.tagName === 'TEXTAREA' ||
activeEl.isContentEditable
)
) {
return;
}
navigateToTodayThenFocus();
});
この判定を入れることで、ユーザーが文字入力をしている最中はショートカット機能が動かなくなります。
event.preventDefaultの使いどころ
ショートカットキーを追加する場合、必要に応じて event.preventDefault() を使います。
event.preventDefault();
これは、ブラウザやWebページ側の標準動作を止めるための命令です。ただし、むやみに使うとGoogleカレンダー本体のショートカットや入力操作を妨げる可能性があります。
今回のように、入力欄では処理をスキップしたうえで、拡張機能が本当に動作する場面だけ preventDefault を使うと安全です。
処理を関数に分ける
キー入力を監視する部分には、できるだけ複雑な処理を書きすぎないようにします。
function navigateToTodayThenFocus() {
// 予定を探す
// 現在時刻と比較する
// 対象要素へスクロールする
// フォーカスとハイライトを行う
}
イベント監視は「いつ処理を始めるか」を担当し、実際の予定探索は別の関数に分けると読みやすくなります。
まとめ
第3回では、content.js の基本構造と、キーボード入力を監視する方法を解説しました。
ポイントは、即時実行関数でスコープを分けること、keydown イベントでショートカットを検知すること、入力欄では誤作動しないようにすることです。
次回は、GoogleカレンダーのDOMから予定要素を取得し、日付や時間を解析する処理を見ていきます。


