Practical Problem Solving with Algorithms

Traversing the Tiles

Kyle Simpson

Kyle Simpson

You Don't Know JS
Practical Problem Solving with Algorithms

Check out a free preview of the full Practical Problem Solving with Algorithms course

The "Traversing the Tiles" Lesson is part of the full, Practical Problem Solving with Algorithms course featured in this preview video. Here's what you'd learn in this lesson:

Kyle demonstrates how the querySelectorAll method can be used to traverse the tiles on the chessboard. The querySelectorAll method returns a NodeList of elements matching the supplied pattern. A loop goes through the list of elements and removes the "highlighted" class from each element.


Transcript from the "Traversing the Tiles" Lesson

>> All right, our second task, our much more interesting and important task, is to handle that when we click on one of the tiles, we are going to highlight the two diagonals that that tile participates. Note in this code comment, which is also part of the readme instructions, in case you've deleted it.

But note in this code comment that we are given the tile element reference that has been clicked on that is taken care of by app. So we're not gonna change any of that app code. We are going to be given a tile element. If you are given no tile element, in other words, if it comes in as undefined, that is basically the same thing as clearing the board.

So you saw that there's a clear button. So if tile element comes in as undefined, then we're gonna clear it. In other words, we're gonna need to clear it always and then if tile element has been set, that's when we're going to highlight its diagonals. Okay, so first question is, how do we know what possible, where that tile was on the board?

So that we could possibly start to figure out what diagonals it's in. What does where it is even mean? Well, if you think about the DOM elements as participating in a data structure right now, a two-dimensional data structure where the values are references to DOM elements. We have an array of rows that that array happens to also be a DOM element, but it is conceptually an array of rows.

That's the board element, and then within each one of those, we have an array of DOM elements, which are the tiles. So we have a two-dimensional array, it's a data structure, it just happens to be DOM nodes, but that doesn't make it not a data structure. So how do we find out where in our data structure this specific tile that was clicked is?

And what does where even mean? To answer that question, we're gonna go back to the slides. You'll note that if I clicked on this one, for example, that it has a position that we could think of like a coordinate. Think about this grid as if it's a coordinate system.

You're probably familiar with XY coordinate systems, two-dimensional coordinate systems. We could think about the position of the thing that was collected as having a coordinate, and what would that position be. Well, if we numbered the natural number indexing zero-based as they would be in arrays, if we named numbered the rows and the columns.

And we click on a specific element, then it has a coordinate that corresponds to the row number and to the column number. So we could say that its coordinate is 4,2. Now, some of you might be surprised that I did 4,2 instead of 2,4, because in traditional Cartesian coordinates, we typically list the horizontal component first, and then the vertical component.

And so in a typical Cartesian coordinate system, we would have said 2,4 instead of 4,2, for the same position. There's one key reason why I did the 4,2. And that is because we already made a decision, whether we were cognizant of the decision or not. We made a decision that we were creating rows of columns, rather than columns of rows.

And when we made a decision that we were making rows of columns, then we automatically said that the row index, the vertical index, is the first most important. It is the highest order of the two coordinates. So that's why we got 4,2. Had we gone back and redone that where we did columns of tiles or columns of rows, then it would be 2,4.

But we would have more CSS to deal with to get them to stack properly. It turns out that it's really easy to make them stack the way we wanted to make them stack when we did rows of columns rather than columns of rows. So we made a decision based upon some constraints that the DOM and/or the CSS engine gave us.

And that may or may not have been a good decision, but it's the decision we made nonetheless. At this point, we could be feeding back into as an algorithm just asking questions like, was that a good decision? Should I have made that decision? Should I have made a different decision?

Everybody following me so far? Okay, so if we have the coordinate 4,2, that represents where we have clicked. Let me temporarily switch back to the code for just a moment. How would I get, The tiles that I need to work with? We have this original board element, but that's just a DOM element.

How would I get a two-dimensional array of them? How would I construct the JavaScript data structure that we could interact with? There's a couple of different ways to do it. I'm not gonna suggest that there's one right or wrong way, but let me show you one way of doing it.

origBoardEL, this is, again, some core DOM API stuff that most people never get exposed to. We have this thing called querySelectorAll. Anybody ever heard of querySelectorAll? This is the less powerful built-in version of jQuery, that's how I like to think of it, but only the CSS selector part.

We can give it a CSS selector, and it'll go find matching elements to that CSS selector, so I'm gonna give it div, div. That's gonna say go find me all those tiles and return me an array. It's actually not technically an array, it's technically this nodelist thing, which is array like.

And we'll have a couple places where that's okay and a couple of other places where we turn it into an array in order to use it. Let's clear our currently highlighted items. We don't know where they are, we haven't stored them in any way. So the only dumb approach that we can do to clear them is to go through all of the tiles.

I'm gonna just say we'll clear all currently highlighted tiles. If we didn't clear them, each click would highlight a different row, and then eventually the whole board would get read. So we gotta clear it every time. So I guess we could have done the whole react thing, which is to redraw the whole board every time.

I'm not a big fan of that. I'm not a big fan of rerender the whole page with every change, so we're gonna go ahead and just clear them. And here's another DOM API that you maybe haven't worked with. The class list gives us an API for dealing with the classes that are currently on a DOM element.

And we're just gonna remove the highlighted class from any of them. So we're going through all 64 of the tile elements and removing all of the highlighted elements. Here's a quick little quiz to make sure everybody's awake and paying attention. You ready for the quiz? How many DOM elements are we using to represent our chessboard?

I wish I had the Jeopardy theme music to play. I've heard 64.
>> I've heard 65.
>> You said 72?
>> Yeah, like the divs.
>> Okay.
>> 9 plus 1, what's that?
>> It's 8 times 9 plus 1. 8 times 9?
>> 9 elements plus the container for the-

>> 9 elements?
>> Yeah, cuz you have the div container for the row, and you have the div container for each element in the row.
>> Okay.
>> And you have the global container.
>> Okay.
>> So yeah, there's probably more that they stick on us, but that would be the minimum we're creating.

>> Okay.
>> Lots of 65s, a couple of 73s.
>> Yeah, 73 is-
>> 73 is the correct answer. We have 64 tiles, we have 8 parent rows that make 72. And we have one board element that contains all of them. That's 73. You got there with different math, but the same answer.

Okay, so we're going through only the 64 tile elements and removing the highlighted from all of them. That's a bit of a brute force way of doing it. You can already probably imagine that it might be nice if we had a reference to which ones were highlighted and we only removed the class from the ones that had it.

But is it that big of a deal to go through 64 versus 15? Here's another one of the questions that we probably should have asked about this problem before diving into the code. Does our code need to handle arbitrarily sized chess boards? In this particular case, we're gonna say we're only dealing with 8 by 8 chess boards.

But sometimes you get presented with a problem and they're like, well, what about the 317 by 317 chess board? How does it work then? There are problems like that. There's classic algorithmic problems like the n queens problem and stuff like that, that deal with arbitrarily sized boards. That's a question that we need to ask.

Those are fundamental characteristics of the problem that change the way we approach this. If we had to deal with n-sized chessboards, we might not just be willing to do a loop over all the possible tiles if it could be millions. Here, we know it's fixed at 64, so not that big a deal.

We still wanna fix it, but it's not that big a deal. Okay, so fundamentally what we need, if tile element has been clicked, because we're gonna clear it every time, but we're only gonna do highlighting if title element was clicked. Fundamentally, what we need to do here is figure out the coordinate of the tile that was clicked.

Does everybody agree with that? Does that makes sense? I need the rowIndex and the columnIndex of the tile that was clicked. So I need a rowIndex, and I need a columnIndex. How are we gonna figure that out? So let's go back to the slides for a moment, and let's observe the rowIndex.

So that is the 4 here. If that's the thing that we had clicked on, the rowIndex is the position of that tile's row parent in the board element. The board element only has eight children, this one, this one, this one, this one, this one, this one, this one and this one right here.

If you were to do the dominance vector and expand it out, you would see that the board element has eight row elements in it. So if I wanted to know what is the index, then I just need to know what is my row parent? And then I need to ask of the board, what index is this row element in the board's child nodes?

Once I find the row element, the columnIndex is pretty straightforward, because the row element has child nodes in it, and I just need to ask which index are you at within the row elements child? So really, all that we need to do is actually find the row element, rowEl for the tileEl.

Turns out this is quite convenient, there's a thing called parentNode. Just to be slightly more precise here, I'm gonna just change these variable names to rowIndex and columnIndex. Now, remember that I said that this thing is not a real array. But I wanna do some index searching in it, so I'm gonna need to turn it into a real array.

So the way that I'm gonna turn it into a real array is to say, or actually, not that thing into a real array, for the rowIndex, I need to turn origBoard, El.childNodes, I need to turn that into a real array. And then I can call findIndex on it, where the element is equal to the rowEl.

Let's put that into a second line so you can see I'm calling. Do it this way. The first thing I'm doing is trying to get into a real array, and then I'm calling findIndex on it, and I'm giving it a function. That only returns true once I find that particular rowEl.

A smaller, more compact way of doing this is indexOf(rowEl). So whichever one you prefer, we can do that. ColumnIndex is pretty straightforward, we just need to take the rowEl.childNodes and do the same thing. That'll tell us our index, that'll tell us our 4,2 coordinate.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now