-
Hold Shift to Check Multiple Checkboxes 📦Web/JS30 2020. 11. 9. 23:39반응형
쉬프트 버튼을 누른 채 두 개의 체크박스를 클릭했을 때
그 두 개의 체크박스 사이에 있는 모든 체크박스들까지 전부 체크되도록 하는 예제이다.
* 체크된 체크박스 옆에 있는 설명에 취소선이 그어지게 하는 CSS 코드.
input:checked + p { background: #F9F9F9; text-decoration: line-through; }
우선, 체크박스를 범위로 다루기 위해서 모든 체크박스들을 변수에 담아둬야한다.
그리고, 그 체크박스들에 클릭 이벤트를 붙여준다.
이 예제에서는, 클릭을 할 때 쉬프트 키가 눌렸는지 여부를 검사할 필요가 있다.
그래서 change 이벤트 대신, 그런 키보드 이벤트들까지 체크가 되는 click 이벤트를 사용했다고 한다.
const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]'); checkboxes.forEach(checkbox => { checkbox.addEventListener('click', handleCheck); });
두 체크 박스 사이의 모든 체크박스들을 체크하려면, 첫 번째로 클릭을 하고나서
쉬프트를 누른 채로 두 번째 체크박스를 클릭할 때, 첫 번째에 체크했던 체크박스가
어떤 놈인지를 기억하고 있어야 한다.
그래서 'lastChecked'라는 변수를 만들어, 그 변수에 첫 번째에 체크되었던 체크박스를 담아 두기로 한다.
참고로 이 변수에 let을 사용한 이유는, 체크박스를 클릭할 때마다 계속해서 lastChecked가 바뀌기 때문.
let lastChecked;
이제 handleCheck 함수를 구현할 차례이다.
1) 우선, 쉬프트 키가 눌러져있는지를 검사해야한다.
아까전에 click 이벤트에 키보드 버튼이 눌러지는지 여부까지 함께 인식된다고 했는데,
click 이벤트를 console.log 해보면, altKey나 shiftKey같이, 마우스와 함께 누를 법한 키보드 버튼이
눌러졌는지 여부를 담은 프로퍼티가 있는 것을 확인할 수 있을 것이다.
그래서 쉬프트 키가 눌러졌는지 여부는 e.shiftKey라는 프로퍼티를 활용하면 된다.
2) click 이벤트는 check할 때와 uncheck할 때 모두 발생하기 때문에
체크박스를 check할 때만 기능을 수행하기 위해, 해당 여부를 검사해주면 된다.
* 추가로, checkbox를 click할 때마다 계속해서 해당 checkbox를 lastChecked로 갱신하도록
handleCheck의 마지막에 'lastChecked = this'를 추가시켜준다.
function handleCheck(e) { // Check if they had the shift key down // AND check that they are checking it, not unchecking it. if(e.shiftKey && this.checked) { ... } lastChecked = this; }
첫 번째에 클릭된 checkbox를 담는 변수인 'lastChecked' 일단 모든 체크박스를 loop 돌아야 한다.
그리고 첫 번째로 클릭된 checkbox부터 시작해서, 두 번째로 클릭된 checkbox까지 check를 해주면 된다.
이 때 'inBetween'이라는 변수를 만들어서 활용했는데, 첫 번째와 두 번째로 클릭된 checkbox에서만
inBetween이 true가 되어, 그 사이에 있는 애들을 전부 checked 상태로 만들어주면 된다.
function handleCheck(e) { // Check if they had the shift key down // AND check that they are checking it, not unchecking it. let inBetween = false; if(e.shiftKey && this.checked) { // loop over every single checkbox checkboxes.forEach(checkbox => { if(checkbox === this || checkbox === lastChecked) { inBetween = !inBetween; } if(inBetween) { checkbox.checked = true; } }); } lastChecked = this; }
여기서 'checkbox === this'인 경우가 '두 번째에 클릭한 checkbox인 경우'이고,
'checkbox === lastChecked'인 경우가 '첫 번째에 클릭한 checkbox인 경우'를 의미한다.
추가로, 이를 구현하는 방법중에는 두 checkbox가 각각 DOM Tree의 어디에 위치하는지를 찾아서
그 부모 요소로 간 다음, 부모 요소에서 두 checkbox와 그 사이에 있는 checkbox들의 checked를 바꿔주는 방법도 있다.
하지만 이런 식으로 HTML의 DOM 구조를 이용하여 구현하는 것은 너무 복잡하고 비효율적일 뿐만 아니라
누군가가 HTML 구조를 조금만 바꿔줘도 순식간에 먹통이 되버리기 십상이다.
그래서, checkbox들을 자바스크립트 변수에 담은 후, 자바스크립트를 이용해서 구현해주는 게 훨씬 안정적인 방법.
전체 자바스크립트 코드
<script> const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]'); let lastChecked; function handleCheck(e) { let inBetween = false; if(e.shiftKey && this.checked) { // loop over every single checkbox checkboxes.forEach(checkbox => { if(checkbox === this || checkbox === lastChecked) { inBetween = !inBetween; } if(inBetween) { checkbox.checked = true; } }); } lastChecked = this; } checkboxes.forEach(checkbox => { checkbox.addEventListener('click', handleCheck); }); </script>
사실 이 예제는 몇 가지 보완할 점이 있다.
1) 무조건 두 번째 클릭 시에만 쉬프트 버튼을 눌러야 한다.
첫 번째 클릭때도 쉬프트 버튼을 누르면 이상하게 동작함.2) 쉬프트로 범위 체크는 되지만, 범위 체크 해제는 안 된다.
범위 체크 해제는 좀 이상하게 동작할 우려가 있어서 그렇다 쳐도,
쉬프트 클릭 시기와는 상관없이 범위 체크가 가능하도록은 구현할 수 있을 것 같은데.
시간 나면 한 번 간단하게 시도해봐야겠다.
반응형'Web > JS30' 카테고리의 다른 글
Key Sequence Detection(KONAMI CODE) 🎮🎲 (0) 2020.11.11 Custom HTML 5 Video Player 🎬🎥 (0) 2020.11.10 14 Must Know Dev Tools Tricks 💪 (0) 2020.11.04 Fun with HTML5 Canvas 🎨 (0) 2020.11.01 Array Cardio Day 2 🎈 (0) 2020.10.30