予定要素から開始時刻と終了時刻を取得できたら、次は「どの予定へ移動するか」を決める必要があります。
連載第5回では、現在時刻と予定時刻を比較し、最も適した予定を選んでフォーカスするロジックを解説します。
予定の候補を分類する
まず、画面上に表示されている予定を現在時刻との関係で分類します。
- 現在進行中の予定
- これから始まる予定
- すでに終わった予定
たとえば、現在時刻が10:30の場合、10:00から11:00の予定は現在進行中、13:00から14:00の予定は未来の予定、9:00から10:00の予定は過去の予定です。
優先順位を決める
今回の拡張機能では、次の優先順位でフォーカス対象を決めます。
- 現在進行中の予定があれば、その中で最も開始時刻が遅い予定を選ぶ
- 現在進行中の予定がなければ、これから始まる予定の中で最も開始時刻が早い予定を選ぶ
- 未来の予定もなければ、過去の予定の中で最も終了時刻が遅い予定を選ぶ
- 対象がなければ何もしない
この順番にすることで、「いま見るべき予定」に自然に移動できます。
判定ロジックの例
予定データが startTime、endTime、element を持っているとすると、次のように分類できます。
const activeEvents = events.filter(function (event) {
return event.startTime <= now && now <= event.endTime;
});
const futureEvents = events.filter(function (event) {
return event.startTime > now;
});
const pastEvents = events.filter(function (event) {
return event.endTime < now;
});
現在進行中かどうかは、開始時刻と終了時刻の間に現在時刻が入っているかで判断します。
現在進行中の予定を選ぶ
現在進行中の予定が複数ある場合は、最も開始時刻が遅い予定を選びます。
activeEvents.sort(function (a, b) {
return b.startTime - a.startTime;
});
const target = activeEvents[0];
同時刻に重なる予定がある場合でも、直近で始まったものを優先できます。
未来の予定を選ぶ
現在進行中の予定がない場合は、これから始まる予定を探します。未来の予定では、最も開始時刻が早いものを選びます。
futureEvents.sort(function (a, b) {
return a.startTime - b.startTime;
});
const target = futureEvents[0];
これにより、次に始まる予定へ移動できます。
過去の予定を選ぶ
現在進行中の予定も未来の予定もない場合は、直近で終了した過去の予定を選びます。
pastEvents.sort(function (a, b) {
return b.endTime - a.endTime;
});
const target = pastEvents[0];
一日の予定を振り返りたい場合や、最後に終わった予定を確認したい場合に役立ちます。
対象の予定へスクロールする
対象が決まったら、scrollIntoView() で画面中央へスクロールします。
target.element.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
behavior: 'smooth' を指定すると、急に画面が切り替わるのではなく、滑らかに移動します。
フォーカスを移す
スクロールしただけでは、キーボード操作の対象が移らないことがあります。そこで、対象要素に focus() を実行します。
target.element.setAttribute('tabindex', '-1');
target.element.focus();
要素によってはそのままではフォーカスできないため、必要に応じて tabindex を付与します。
ハイライトを付ける
最後に、対象の予定へCSSクラスを追加して見た目を変えます。
target.element.classList.add('gcal-shortcut-active-highlight');
以前にハイライトした予定がある場合は、先にクラスを外してから新しい予定に付与すると、常に1つの予定だけを目立たせることができます。
document
.querySelectorAll('.gcal-shortcut-active-highlight')
.forEach(function (element) {
element.classList.remove('gcal-shortcut-active-highlight');
});
target.element.classList.add('gcal-shortcut-active-highlight');
まとめ
第5回では、現在時刻を基準に予定を分類し、最も適した予定を選ぶロジックを解説しました。
現在進行中、未来、過去の順に判定することで、ショートカットキーを押したときに自然な移動先を決められます。
次回は、拡張機能をChromeに読み込む方法、デバッグ方法、開発時の注意点を解説します。


