1. はじめに
今回は、純粋な JavaScript(ライブラリなし) で、メールクライアント風のチェックボックスリストで、Shiftキーを押しながらチェックすると中間の項目もまとめてチェックできる機能を作ります。
デモ⬇️
2. 実装
html部分
<div class="inbox">
<div class="item">
<input type="checkbox" />
<p>This is an inbox layout.</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Check one item</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Hold down your Shift key</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Check a lower item</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Everything in between should also be set to checked</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Try to do it without any libraries</p>
</div>
<div class="item">
<input type="checkbox" />
<p>Just regular JavaScript</p>
</div>
</div>
CSS部分
html {
font-family: sans-serif;
background: #ffc600;
}
.inbox {
max-width: 400px;
margin: 50px auto;
background: white;
border-radius: 5px;
box-shadow: 10px 10px 0 rgba(0,0,0,0.1);
}
.item {
display: flex;
align-items: center;
border-bottom: 1px solid #f1f1f1;
}
.item:last-child {
border-bottom: 0;
}
input[type="checkbox"] {
margin: 20px;
}
p {
margin: 0;
padding: 20px;
transition: background 0.2s;
flex: 1;
font-family: 'helvetica neue';
font-size: 20px;
font-weight: 200;
border-left: 1px solid #d1e2ff;
}
/* チェックされたら背景色と取り消し線を追加 */
input:checked + p {
background: #f9f9f9;
text-decoration: line-through;
}
JavaScript部分
// すべてのチェックボックス要素を選択(NodeListとして取得)
const checkboxes = document.querySelectorAll(".inbox input[type='checkbox']");
// 最後にチェックしたチェックボックスを保持するための変数(初期値はundefined)
let lastChecked;
function handleCheck(e) {
// 中間範囲のフラグ:false時は範囲外、true時は範囲内
let inBetween = false;
// Shiftキーが押されていて、現在のチェックボックスがチェック状態の場合のみ、範囲選択を実行
if (e.shiftKey && this.checked) {
// すべてのチェックボックスを順番にループ(DOMの順序で並んでいるため、インデックス順に処理)
checkboxes.forEach((checkbox) => {
// 現在のチェックボックスまたは前回のチェックボックスに到達したら、範囲フラグをトグル
if (checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween;
console.log("中間のチェック開始!"); // デバッグ用:範囲開始/終了をログ出力
}
// 範囲内(inBetweenがtrue)の場合、そのチェックボックスを強制的にチェック状態にする
if (inBetween) {
checkbox.checked = true;
}
});
}
// 現在のチェックボックスを「前回チェック済み」として更新(次回の範囲選択に使用)
lastChecked = this;
}
// 各チェックボックスにクリックイベントリスナーを追加(ハンドラ関数はhandleCheck)
checkboxes.forEach((checkbox) =>
checkbox.addEventListener("click", handleCheck)
);
3.コードのポイント
チェックボックスと段落を隣接させる
<input type="checkbox" /><p>テキスト</p>
CSSで input:checked + p を使うと、チェック時に取り消し線を表示可能
Shiftキー判定
if (e.shiftKey && this.checked)
Shift の大文字 K に注意!
Shift押下時のみ「中間まとめチェック」を有効化。
中間チェックの範囲指定
inBetween = !inBetween;
前回クリックした checkbox (lastChecked) と今回の checkbox の間を判定。
4.まとめ
- ライブラリ不要で Shiftキーによる複数選択 を実装可能。
- CSSの
input:checked + pで 取り消し線などの視覚効果 を簡単に追加。 - JSは イベントと簡単なフラグ管理 で実装できる。
GitHubでのソースコード⬇️