1. Overview
Challenge & starter files: Advent of JS
Full codes: nilstarbb/advent-of-js/5-multiple-checkboxes
Live Demo: 05 - Multiple Checkboxes || Advent of JavaScript
Preview:
2. Details
Users should be able to:
- See the list of podcast episodes
- Check one episode, shift-click to select all the episodes in between
3. Coding
大致步骤如下:
- 读取全部的 checkbox DOM。
- 设置
lastChecked
,用于记录上一次 check 的 checkbox。 - 当用户 check 某个 checkbox 时,检测是否摁着 shift 键,若是,则用一个遍历将
lastChecked
和当前 checkbox 之间的 checkbox 全部 check。
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
let lastChecked;
const shiftCheck = (e) => {
let inBetween = false;
if (e.target.checked && e.shiftKey) {
checkboxes.forEach((checkbox) => {
if (checkbox.name == e.target.name || checkbox.name == lastChecked.name) {
inBetween = !inBetween;
}
if (inBetween) {
checkbox.checked = true;
}
});
}
lastChecked = e.target;
};
checkboxes.forEach((checkbox) => {
checkbox.onclick = shiftCheck;
});
不过这里遇到一个问题。按 shift 后单击会默认选取两次点击之间的文字,想正确执行 onClick
得双击才行。
将 document.onselectstart
设置为 false
后可以阻止 shift 的默认功能,但这样的话,这个页面都不能进行选择,选取文字得开 inspector 去 HTML 里选,不方便实际使用。
document.onselectstart = () => false;
const shiftCheck = (e) => {
...
if (e.target.checked && e.shiftKey) {
...
}
...
};
斟酌一番后,决定改为使用 ctrl 而不是 challenge 里原本要求的 shift。
const shiftCheck = (e) => {
...
if (e.target.checked && e.ctrlKey) {
...
}
...
};