4 minutes
Javascript 30 Day 10: Hold Shift to Check Multiple Checkboxes
Today is day 10, one third of the way through Javascript 30. Today’s less is called “Hold Shift to Check Multiple Checkboxes” and in this one Wes encourages you to try out a solution on your own before coming back to the video. So that’s what I did, and surprise! They are a little different.
The idea is that you’ve got a bunch of checkboxes, representing a todo list or an inbox or whatever and you want to click one of them, then hold shift and click another, and all of them in between should be checked. Here’s the approach I took.
As with other lessons, I went to document.querySelectorAll
and grabbed all the checkboxes using input[type="checkbox"]
. I then added a click event handler to each of them using a forEach loop. And similar to previous lessons, I console logged to make sure things were hooked up correctly and I was getting clicks. I was not. So I tried change
and onclick
and then I found I had actually used document.querySelector
instead of querySelectorAll
and once that was in place, clicks where getting logged.
Next, I figured I’d need to keep track of which was the previously clicked checkbox, so I used checkboxes.findIndex
to store which checkbox in the array of checkboxes I had clicked, but that doesn’t work. So I turned my NodeList
of checkboxes into an array and then it was fine. After that I added a keyup
and keydown
event listener for key === 'Shift'
and used that to turn on and off a groupSelect
boolean variable I wanted to use to select more than one thing. My logic was something like “if the thing that was clicked is checked and I either don’t have something previously checked or we’re not in groupSelect
mode, then record the index of the thing I checked. Then if we’re in groupSelect
mode, then figure out the newly clicked index number and then figure out if it’s a higher or lower number than the previously clicked one. Once we know that call another function I wrote that loops over the checkboxes from the lower index up to and including the higher index and check everything.
That’s the main difference in the solution I made compared to Wes’. Well, one of a few. In the solution in the video he doesn’t use key handlers to figure out if shift is down or not and toggle a mode variable. Turns out it’s just part of the event, even on the click events. So that definitely simplifies things and it was a thing I wasn’t aware of. The other difference though, is that he has an inBetween
mode which toggles a variable that indicates if we’re checking or not checking checkboxes. This means it loops over all the checkboxes, even the ones that aren’t going to be checked.
So I don’t think either is better or worse, just different. I’d probably use a bit of what I had and a bit of the new stuff I learned from watching the rest of the video… Maybe. I’m thinking out loud here on this and the efficiency of each solution. The downside with mine is that each time you click and you’re not in the mode that checks everything in between, my code is using findIndex, which I’m pretty sure is visiting every checkbox until it finds one that is right. So I’m paying that tax every time even if I’m just clicking a bunch of different things until I finally figure out the one I want for multi-select.
In Wes’ code, he’s doing one or two equivalency comparisons per node, but only if the code goes into multi-select mode. One minor optimization could be to bail out of the loop once multi-select mode is turned back off. This would prevent you from visiting every checkbox once you’d found the last (in the DOM) clicked checkbox.
Another potential way to handle this could be that when we loop over the checkboxes to add the click event handler, having it “know” which indexed value is clicked so that we don’t need to figure out where in the array of checkboxes it lies and we don’t have to do any equivalency checking withing the check loop. Of course, all bets are off if you have code where the DOM order of the checkboxes can change. In that scenario, I think Wes’ code is going to be best, and having the listener know the position of the checkbox in the array won’t help since it’s not fixed.
I liked this one a lot and I’m looking forward to the Day 11 exercise!