JavaScript-30-Day-10
Tags: javascript, html, webdev, github
Published: 2021-06-10 17:27:42

##<center> Hold Shift And Check Checkboxes </center>

### ✨ [Demo](https://cenacrharsh.github.io/JS-30-DAY-10/)

![ss.png](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjpord9sz4z923xzply4.png)

Before we begin today's Blog I would like to Thank You everyone who is consistently reading my Blog and supporting me. This is my 10th day on dev.to and my 10th blog as well and the support I have received is something I never even Imagined. Once again a big **Thank You** to everyone reading this blog.

Today we worked on something very useful, a common layout you would see in an email client.

When a user clicks a checkbox, holds Shift, and then clicks another checkbox a few rows down, all the checkboxes in between those two checkboxes should be checked.

By default some checkboxes were provided and due to this code in CSS we can check any box and the text had a line-through.
```css
input:checked + p {
        background: #f9f9f9;
        text-decoration: line-through;
      }
```

So the very first thing we did was to select all checkboxes where I Learned how to select the elements by the `type` key.
```javascript
const checkboxes = document.querySelectorAll(
        '.inbox input[type="checkbox"]'
      );
```

Now that we have a NodeList of all the checkboxes we will loop through every single one using `forEach()`and add `eventListeners()`.
```javascript
checkboxes.forEach((checkbox) =>
        checkbox.addEventListener("click", handleCheck)
      );
```

One thing to note here is that we use the `click` event instead of   `change` event, because `click` event will fire even if we use the keyboard.

Now we will write our logic inside the `handleCheck` function, which will be called as soon as the user clicks any of the boxes.

Next thing we need to take care of is, when we check the first box, we need to put that into a variable, because when we check our second one (while holding down `shift`) we need to know what the last one was. So we'll create a variable to maintain a reference to it, and after creating the variable we'll update it at the end of the `handleCheck` function.

```javascript
let lastChecked;
function handleCheck(e) {
//rest of the code
lastChecked = this;
```
>Note: We use `let` instead of `const` because this variable is going to update constantly.

Now we need to figure out what checkboxes we need to check based on the checkboxes the user clicks. So rather than trying to find where in the DOM they are and trying to figure out like which elements are in-between and finding it's parents.......
This is vary fragile way to do so because we are dependent on the HTML set and if someone else comes along and changes the HTML a little bit, the code would just break and we do not want that.

What we are going to do instead is we are going to loop over every single checkbox and we are going to create a variable called `inBetween` (set to `false` initially) and what `inBetween` will do is we'll loop over the entire NodeList of checkboxes and as soon as we find a checked checkbox we'll it's value to `true` and the loop will go one and the second time we find the checked element we'll set if back to `false` again.

Now before we code the logic for `inBetweeen` we need to perform another check, first if the `shift` if pressed down and secondly while clicking the checkbox, user is checking it and not unchecking it because the `click` event gets fired on both occasions.

```javascript
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;
            }
          });
        }
```

This `(e.shiftKey && this.checked)` ensures that we do not loop over the checkboxes unless `shift` is pressed and the click was checking and not unchecking.

Using this part we loop over every single checkbox and update `inBetween` accordingly.

```javascript
checkboxes.forEach((checkbox) => {
            if (checkbox === this || checkbox === lastChecked) {
              inBetween = !inBetween;
            }
```

We have used this:
```javascript
if (checkbox === this || checkbox === lastChecked) {
              inBetween = !inBetween;
            }
```
instead of simply setting to `true` or `false` so that our checkboxes work both ways so we do `inBetween` is opposite of itself.

>NOTE: keep in mind checks are always performed top->bottom.

First case is where user clicks a lower checkbox first and then clicks upper checkbox in which case `checkbox === this` is true (here `this` is equal to the one that got checked) and since this checkbox is the one we are currently looping over so condition is true.

Seconnd case is where, first the user clicks a upper box and then clicks a box below it. In this case `checkbox === lastChecked` is true as the upper box is kept in `lastChecked` variable and the lower box is the currently checked box, so we revert the value of `inBetween` using `inBetween = !inBetween` that is set it to true.

Long story short, it will start checking from top and as soon as checked box is found `inBetween` is set to true and second time a checked box is found `inBetween` is set to false again.

Making use of `inBetween` flag this checks all boxes while `inBetween` is true that all the boxes in between
```javascript
if (inBetween) {
              checkbox.checked = true;
            }
```

This is the complete JavaScript code:
```javascript
const checkboxes = document.querySelectorAll(
        '.inbox input[type="checkbox"]'
      );

      let lastChecked;
      function handleCheck(e) {
        //we need to 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;
      }

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

and with this our project for the day was completed.

GitHub repo:
{% github cenacrharsh/JS-30-DAY-10 no-readme %}

###Blog on Day-9 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-9-328i %}

###Blog on Day-8 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-8-4lhj %}

###Blog on Day-7 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-7-dd9 %}

[Follow me on Twitter](https://twitter.com/cenacr007_harsh)
[Follow me on Linkedin](https://www.linkedin.com/in/kumarharsh22/)

**DEV Profile**

{% user cenacr007_harsh %}

You can also do the challenge at [javascript30](https://javascript30.com/)

Thanks @wesbos , [WesBos](https://github.com/wesbos) to share this with us! 😊💖

**Please comment and let me know your views**
##Thank You!