1. 배경
Shift 키를 누른 상태로 두 개의 체크박스를 클릭하면, 그 사이에 있는 체크박스도 모두 체크되도록 하는 기능을 만들기로 했다.
2. HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hold Shift to Check Multiple Checkboxes</title>
</head>
<body>
<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>
</body>
</html>
3. 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:checked + p {
background: #F9F9F9;
text-decoration: line-through;
}
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;
}
4. Javascript
const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]');
console.log(checkboxes);
checkboxes.forEach(checkbox => checkbox.addEventListener('click', handleCheck));
먼저 checkboxes 변수를 설정하여, 모든 checkbox들을 선택한다. 변수 checkboxes에는 아홉 개의 input으로 이루어진 Nodelist가 반환된다.
그리고 이 체크박스들이 각각 클릭 이벤트에 반응하여 handleCheck라는 함수가 실행되도록 한다.
let lastChecked;
function handleCheck(e) {
console.log(e);
console.log(this);
console.dir(this);
let inBetween = false;
if(e.shiftKey && this.checked) {
checkboxes.forEach(checkbox => {
console.log(checkbox);
if(checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween;
console.log("starting to check them inBetween!");
}
if(inBetween) {
checkbox.checked = true;
}
});
}
lastChecked = this;
console.log(lastChecked);
}
handleCheck는 구체적으로 위와 같이 정의한다. 먼저 inBetween의 초기값을 false로 정의한다. 이는 클릭된 두 개의 체크박스 사이의 체크박스들을 컨트롤할 것이다. 그리고 if문을 사용하여, 전달된 마우스 이벤트(e)의 shiftKey 값이 true이고, 동시에 전달된 인풋(this)의 checked 값이 true인 경우에만, 즉, shift를 누른 채로 클릭을 했을 경우에만 모든 체크박스들에 대하여 콜백 함수가 시행되도록 하였다. 마우스 이벤트의 shiftKey의 값은 console.log(e)로, 인풋의 checked 값은 console.dir(this)로 확인할 수 있다.
콜백함수는, 모든 체크박스에 대해 각각 시행되는데, 각각의 체크박스들 중, 이벤트를 통해 전달된 this, 즉 클릭한 인풋이거나 마지막으로 체크된 인풋인 경우, inBetween 값을 true로 변경하게 될 것이다.
첫 번째 클릭 시에는 lastChecked 값이 초기값인 undefined이고, inBetween 값 역시 초기값인 false인 상태이다. 첫 번째 클릭은 시프트를 누르지 않아도 상관없기 때문에, if문을 지나치고 lastChecked에 this를 할당한다. 이로써 lastChecked에 클릭된 체크박스가 할당된다.
Shift 키를 누른 채로 두 번째 체크박스를 클릭한다면, handleCheck의 첫 번째 if문을 작동시키게 되는데, 이는 모든 체크박스들 각각에 대하여 두 가지 if문을 실행시키는 것이다.
첫 번째 if문은, 해당 체크박스가 this이거나 lastChecked인 경우, 즉, 두 번째로 클릭된 체크박스이거나 첫 번째로 클릭된 체크박스인 경우에 inBetween의 값을 반대로 바꿔 준다. 모든 체크박스에 대하여 이를 확인하므로, 첫 번째로 클릭된 체크박스부터 inBetween은 true가 될 것이고, 이에 따라 두 번째 if문에 의해 checked 상태가 true로 바뀌어 체크가 될 것이다. inBetween은 계속 true로 유지되다가, 두 번째로 클릭된 체크박스의 차례에서 false로 바뀐다. 결국 첫 번째로 클릭된 체크박스부터, 두 번째로 클릭된 체크박스의 이전 체크박스까지 checked 상태가 true로 바뀌게 되는 것이고, 두 번째로 클릭된 체크박스는 직접 클릭했으므로 checked는 이미 true인 상태이다.
[Javascript] 12. Key Sequence Detection (0) | 2021.04.22 |
---|---|
[Javascript] 11. Custom Video Player (0) | 2021.04.22 |
[Javascript] 09. Dev Tools Domination (0) | 2021.04.20 |
[Javascript] 08. Fun with HTML5 Canvas (0) | 2021.04.20 |
[Javascript] 07. Array Cardio Day 2 (0) | 2021.04.18 |
댓글 영역