JS30 全攻略 第10天

前言

JS 30 是由加拿大的全端工程師 Wes Bos 免費提供的 JavaScript 簡單應用課程,課程主打 No Frameworks、No Compilers、No Libraries、No Boilerplate 在30天的30部教學影片裡,建立30個JavaScript的有趣小東西。

另外,Wes Bos 也很無私地在 Github 上公開了所有 JS 30 課程的程式碼,有興趣的話可以去 fork 或下載。


本日目標

在已經勾選一個核取方塊的前提下,按住shift鍵並勾選第二個方塊,最後將第一、二個方塊之間的方塊都勾選起來,實現同時勾選複數方塊的目的。


解析程式碼

HTML 部分

由最外層的 div(.inbox) 包覆住內部多個 div(.item),每個div(.item) 都是以一個核取方塊(checkbox)搭配說明文字(p)組合而成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<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 class="item">
<input type="checkbox">
<p>Good Luck!</p>
</div>
<div class="item">
<input type="checkbox">
<p>Don't forget to tweet your result!</p>
</div>
</div>

JS 部分

首先,宣告一個常數 checkboxes 並取得所有網頁上的核取方塊(checkbox)。

接著,宣告一個變數 lastChecked 用來幫我們記住上一次勾選的核取方塊(checkbox)。

1
2
const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]');
let lastChecked;

我們在每個 checkbox 上都註冊 click 事件監聽器,當事件觸發就以handleCheck()進行事件處理。

handleCheck()裡面,我們可以用lastChecked = this;來記住上一次選取的方塊。

1
2
3
4
5
function handleCheck(e){
lastChecked = this;//更新上次勾選的點
}

checkboxes.forEach(checkbox => checkbox.addEventListener('click',handleCheck));

我們進行多選核取方塊的邏輯是先勾選其中一個作為起始點,之後按住shift鍵勾選終點方塊,而在起、終點之間的方塊都會被勾選。

handleCheck()裡,可以使用 if 判斷現在是不是有按下shift鍵並同時勾選方塊,之後再做勾選間隔方塊的處理。

1
2
3
4
5
6
7
8
function handleCheck(e){
//檢查是否有按下shift鍵並選取方塊
if(e.shiftKey && this.checked){

}

lastChecked = this;//更新上次勾選的點
}

宣告一個變數inBetween判斷checkbox是否處在起、終點的checkbox之間。

checkboxes上呼叫forEach()對其下的每一個checkbox進行判斷。當這個checkbox是剛剛按住shift鍵勾選的checkbox,此時將inBetween設為 true;當這個checkboxlastChecked,此時改將inBetween設為 false。

最後一個 if 判斷用來幫我們將起、終點之間的方塊通通勾選起來。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function handleCheck(e){
let inBetween = false;//用來判斷checkbox是否被夾在起、終點之間

//檢查是否有按下shift鍵並選取方塊
if(e.shiftKey && this.checked){
checkboxes.forEach(checkbox => {
//將起始點的inBetween設為true、結束點的inBetewwn設為false作為斷點
if(checkbox === this || checkbox === lastChecked){
inBetween = !inBetween;
}

if(inBetween){//打勾夾在起點和終點的checkbox
checkbox.checked = true;
}
})
}

lastChecked = this;//更新上次勾選的點
}

舉例說明:

假設現在先勾選第一個方塊,之後按住shift鍵並勾選第八個方塊,此時第一個方塊就會是lastChecked,而第八個方塊則是this剛剛勾選的。

checkboxes上呼叫forEach()對其下的每一個checkbox進行判斷時,遇到第一個方塊也就是lastChecked就將inBetween改成 true,遇到第八個方塊也就是this則將inBetween改成 false。

最後,第一個方塊到第七個方塊的inBetween都會是 true,第八個方塊則是 false。作 if 判斷時,我們將inBetween是 true 的勾選起來,勾到第八個剛好inBetween是 false 成為一個勾選的終止點,成功地一次勾選八個方塊。

補充資料:

KeyboardEvent.shiftKey

範例網頁請點此

分享到