So now that we can start a game,
let's work on the actual game logic.
And that starts with making these fields here, clickable.
Now they look like they are clickable,
but of course at the moment nothing happens
also because these fields of course are regular list items
and they should stay list items here.
But we wanna add click listeners
for that of course, we need to get access
to all these list items and then add a click listener
to every single item here.
There also are other patterns in JavaScript
that you could use.
You could add a click listener to the ordered list
and that would actually also then react to any click inside
of the ordered list.
So any click on the list item,
but I'll start with adding individual listeners
to all these list items
so that we can see how we can also process multiple items
at once and add an event listener to multiple items
without repeating a lot of code
and therefore for that,
I wanna select all those lists items
inside my game board here in this ordered list
with ID game board and add click listeners
for this App.js let's get access
to all those list items.
And for it is here where I get access to all the other
non button elements as well, or actually, maybe even here,
when we get access to the buttons
since these list items should act like buttons,
though the exact position doesn't matter here,
we can get access by getting access to the game,
field elements, plural with an S at the end,
by using document query selector all.
And it's important that you use query selector all
because that will select more than one element.
It will select all fitting elements and return you an array
full of all these fitting elements,
query selector without all,
we'll just select the first fitting element
and that's not what we want here.
And the query selector, which I wanna use here.
The CSS selector, which I wanna provide here as a string
should use this ID game board.
So an ID selector to that ID hash game word,
and then all the list items in there
and keep in mind for a query selector
and query selector all you do pass a CSS selector
as a parameter value.
That's why the hash symbol is needed here
for get element by ID,
you just pass the ID itself,
but here we're using query selector all.
And now as mentioned,
this will return an array full of elements in the end.
And we now wanna add click listeners to all those elements
and to do this maybe down here, we can, of course,
simply loop through all these elements as we learned it
in the previous sections
and then performed the same code for every element.
And if we wanna loop through an array of elements,
what we can use as the for of loop
like this, for and then any constant of our choice,
like game field element, singular not plural
of game field elements.
So of the array for which you wanna loop.
And this here of course, is this array,
which we selected up here.
So that's the connection here.
But now with that we can perform code,
we can execute code for every single item in that array
and we get access to these different items in that constant,
which will be different for every iteration off this loop.
And therefore, it's this game field element.
So this constant here, it's this constant,
which will hold a single element,
a different element for every iteration
and we can add our listener to that element
in every iteration
so that ultimately listeners have been added
to all the elements in the end.
And here we can then add a click listener
and then here, we wanna execute a certain function
and this function that should be executed here,
can be added to game jazz and we can name it
select game field, that sounds like a fitting name
because that's what we wanna do.
So I added this function to game.js and back in App.js.
I now pass a pointer at this function
as a second argument here, select game field like this.
Now, what do we wanna do in this function here though?
What's the goal here?
Well, we've got a couple of things to do.
We have to find out which field was clicked.
So which list item was clicked.
And then we wanna add the symbol of the active player
in that list item, so that it's displayed on the screen.
That of course also means that after a field was selected,
we have to switch to the other player.
So that for the next field that is selected,
we place a different symbol.
We also wanna check that we don't select a field
that already does have a symbol inside of it.
We don't wanna do anything if that's the case.
And last but not least,
we also wanna keep track of all the selected fields
and to which player, which field belongs
in our JavaScript code.
So not just here in HTML.
So what did we show it to the end user,
but also in JavaScript code
so that we later can also add another function
or some more logic that allows us to check for a winner.
So really a couple of things that we got to do here,
but let's start simple here and let's get access
to the field on which we clicked
and then output the player symbol there.
For this we can, of course, again,
use this event object, which we get automatically,
and then we get access to the field on which
the click occurred with event target.
Now we can, of course,
manipulate that field and inject the players symbol there
by setting event target text content
equal to the symbol of the player
that clicked on that field.
Now, how do we get that symbol?
Well, keep in mind that an App.js,
I have this players array and there I have the two player
objects where the symbol is stored in the symbol properties.
Hence, we now just also need to keep track
of the active player
and simply assign an index to this active player.
And then say that player one has an index of zero
because player one is the first item in this array
and player two as an index of one.
So I'll add another variable here in App.js
the active player and set this to zero initially
so that we can access the first element initially.
And we'll change this after every turn
to one and back and zero
now initially at zero and therefore in game.js
we can now set the text content of the field
on which we clicked equal to players.
So this players array
and then we dynamically access the active player index.
So active player is that index, that's the variable,
we just add it.
And initially it's zero and therefore for the first round,
we basically access players zero,
but I'm using this dynamic access pattern here
so that we can always run this code
and we just have to change active player
These variable value to access different players
in this array.
And then we just need to access the symbol property,
which is X or O.
So I hope it's clear how that works here
and that we simply use the fact that the number
which we passed here can be dynamic.
You'll learn about that when I introduced you to loops
as well.
Now with that,
if we save everything and we quickly give this a try
by setting up two players, if I click on this field,
the X is added here.
So that is working.
Now, we also wanna add that disabled clause to that field
then once the symbol was placed in there
so that we no longer get the hover effect
after it has been selected.
And then we wanna switch to the different player of course.
So let's start by adding this class.
And for this, we can also access event target here,
class list, and simply add to this disabled class,
which we added in game CSS earlier.
If you have a look at that file,
we did add this disabled class and now I'm adding it
to the list item.
And if we do this here and again give is a try
and since it's annoying that I always have
to enter these players I will temporarily comment out,
display non on active game again,
so that we always see that game field.
And now you'll see this has to disabled class
because now it just looks different
and we no longer get this hover effect.
And we don't have that cursor that implies
that we can click this.
So this is now working.
Of course at the moment we add access to all the fields
on which we click and that is not the goal.
Instead, we wanna switch to player
after we selected a field.
And for that I will simply add a number of function here
in game CSS.
So which player and in here,
I simply wanna check if the active player is zero
at the moment,
and if that's the case, I'll set it to one.
So I switched to the next player with index one,
the second player in our array,
else if active player is not zero,
then it is one and therefore then I'll set it back to zero
and that's all the logic we actually need here.
So therefore now once a game field was selected,
we can just execute, switch player,
execute this function ourselves,
and therefore switched the player.
Of course, we could have all to put
that code right here into select game field,
but this function will grow quite a bit anyways
therefore I did not want to move this logic into this field.
And then with that, you'll see if we save that and go back,
we now place a cross then an O then a cross, O and so on.
So this is not working the way it should.
Now, before we continue with adding logic that we need,
I also wanna show you a different pattern
we can use for listening to clicks.
I showed you how we can add a click listener
to every single game field element.
And this works absolutely fine
and you can leave it like this.
However, I'll comment it out here
and show you an alternative.
Instead of selecting all the game field elements like this,
I'll also comment out this constant
and instead get access to the game board element let's say
so to the ordered list that holds all the list items,
and we can get access to that ordered list
by using the ID that is assigned to it.
So with document, get element by ID,
we get access to the ordered list.
And now that we got access to that list,
I will instead add this listener to this click listener,
to the ordered list,
so to the game board element as a whole,
and then execute select game field
whenever this list is clicked,
notice might sound like it shouldn't work,
but actually it does work because if you think about it,
what does clicking on the ordered list mean in the end?
Well, you will click on one of its items, right?
Because that's the content of the ordered list.
So this still works.
The only problem we face here is if we click in the gap
between two items,
then we replace the overall content with an X,
because our logic is to set an X as content
or a player symbol as content
for the element on which we clicked.
And if we click on a gap then
we didn't click on a list item,
but indeed only the empty space in the ordered list.
So we replaced the entire content of the ordered list
with that player symbol then.
So if we wanna use this pattern here,
where we add the listener to the ordered list,
we would have to indeed validate that we did click
on a list item
and we can do this by for example,
checking for the opposite here with that if case,
we could check if event target dot tag name
is not equal to LI,
because if you do log this event target here.
If we start with that if we log events target,
or to be precise, if we log events target tag name,
then you will see that if you open the developer tools
and you click on a list item, it prints LI,
and if you click on the gap, it prints OL
because then we did indeed click on the ordered list itself
because we didn't hit a list item.
But if we check,
if the element on which we clicked is not a list item,
and we then simply return, then we avoid
that we replace the overall ordered list content
because now by executing return here,
as you'll learn all the other code here won't execute.
So if the element on which we clicked is not a list item,
we don't do anything.
And with that, we avoid the problem from before.
So with this code added, if you save everything,
if you click on a gap nothing happens
and you can continue without issues.
Now, if you're wondering why it works like this,
why events target can be either a list item
or an ordered list.
Then it's important to understand that indeed event target
is not necessarily the element to which you added
your event listener.
If that element to which you added your event listener
doesn't have any average child elements like the buttons,
which only have text inside,
but no other elements then clicking on a button
will always give you that button as an event target
for the submit event on a form,
you will always get the form,
but for a click event on an ordered list,
which has list items, indeed,
if you clicked on the list item, you'll really get the last,
the most specific item on which you clicked
as a value for events target
and that would be the list item.
And it's simply an alternative pattern
for listening to these clicks here and handling them.
You can use either of the two approaches here,
I just also wanted to show this alternative,
which I'll keep for now here,
but you can also go back to the for loop we had before.
Most importantly, with that,
we are now able to display this player symbol,
and we're able to switch players there after.
But of course we're not there yet.
Now that this is implemented,
we also wanna make sure as mentioned before
that we don't just show these symbols here,
but that we also store them internally.
And I also wanna output the player name here.
When we say, it's your turn player name,
now I'll start without putting that player name
for this in index HTML,
we see that here this player name is in a span
that has the active player name ID.
So of course we can simply select that span
as we selected multiple other elements already.
And then just update that whenever we switched around,
hence here in App.js,
where I also select all my other elements, actually here,
I will now select my active player name element,
will store it in a constant of this name
with get element by ID
using that ID that was added to that span.
And with that in game.js, whenever we switched a player,
I wanna update the text shown in that span.
And I wanna set the text content here equal
to players accessing the active player,
which we switched here.
And it's important that we execute this after we switched.
So that we showed a correct new player name here.
And then here we accessed the name property,
which stores the name of the player.
Now very important I also wanna do that
if we just started the game
so copy does line of code and execute the same line
of code here before we showed that game area as a whole,
whenever we start a game
here, I don't always wanna set the text content
to the then active player.
And though with that, if I do enter my player names here,
Max and Manu, and I click start new game, I see max
if I now click here, it switches to Manu
so now it's Manu turn to place his symbol
and then again, it's mine and so on.
So that's how we can now update this.
Now, as I mentioned,
I also wanna store to game state in some variable
or a constant though.
And that will be a bit more tricky
because for this we'll also have to think
about how we determine a winner.