Adding radio buttons0:03
I want to add two radio buttons to our form so that we can control how we create our game object. So a couple of things to note about these radio buttons. First of all, they have the same name that is so that they are in the same radio group because we want to be able to change the value of these whenever we click on one of them. We want to deselect the other. I mean that's typically normal radio behavior. You typically don't ever have a radio group of one.
I mean that's typically normal radio behavior. You typically don't ever have a radio group of one. You have a radio group of two or more. So they have the same name for that purpose. But then notice their values. So this first one is for what I call the game mode. That is, you know, the easy, the medium, the hard. So this would, uh, whenever we click on it show the UI that has the select box. Whenever we click on the other radio button, it is
whenever we click on it show the UI that has the select box. Whenever we click on the other radio button, it is for the custom options. So that would display our list of input elements so that we can define the custom parameters for that game. So the value of these radio buttons need to match the IDs of the div elements that are going to surround those two sets of form controls. So this div with an ID of options_custom has all of the input elements that we had before.
So this div with an ID of optionsCustom has all of the input elements that we had before. Then we're gonna have another div element where the ID will be optionsMode, but it's gonna have a class of inline so that it will be in line with our buttons. So whenever we hide one of these, they will have the class of hidden, whenever one is shown, it will have the class of inline. So of course, you know, the way that we could do this is by
it will have the class of inline. So of course, you know, the way that we could do this is by whenever we click on the radio buttons, that's going to show and or hide the appropriate user interface. And you know, the most obvious thing to do would be to essentially have two click event handlers. One for the radio button for the mode options, and then the other for the radio button for the custom ui. And we could do that, that's fine, but there's a better way. What we can do is essentially set up a
Global input event listener2:09
And we could do that, that's fine, but there's a better way. What we can do is essentially set up a global event listener. So on the document object we will call addEventListener. For right now we're gonna listen for the click event and then we will have our function that executes when that event occurs. So the idea is that this is global. It doesn't matter where we click on the page, this event listener is going to handle that event.
It doesn't matter where we click on the page, this event listener is going to handle that event. So let's do this. We will write to the console the target. This is the element that received the event. So inside of the browser, if I click on the radio button for the mode, we can see that input element is listed in the console. If I click on custom, we see that element is in the console. If I click on the select element, we see that down there. If I click on one of the buttons,
If I click on the select element, we see that down there. If I click on one of the buttons, we see the button in the console. But it doesn't have to be a form control. Remember this is a global event listener. So I can click on the h1 element. We can see that the h1 element received that event. If I click on anything else, we can see those elements inside of the console as well. So it doesn't matter where we click.
inside of the console as well. So it doesn't matter where we click because it's a global event listener, but I don't necessarily want to handle the click event because notice this custom is selected. If I click on the custom radio button again, we see that the click event fires and there's really no reason to do that because if we are already displaying those input elements, we don't need to show and hide anything else.
because if we are already displaying those input elements, we don't need to show and hide anything else because there's, there's nothing to change. Everything is still the same. So what we want to do then is handle an event called input. So the input event is essentially primarily only for form controls and it only fires when the value of a form control changes. So in the case of our radio buttons, since we have a radio group, the input event is only going
So in the case of our radio buttons, since we have a radio group, the input event is only going to fire when that value changes. So I'm repeatedly clicking on the mode and we can see that nothing is showing up in the console, but whenever I click on custom, the value of that radio group changed. So therefore the input event fired and we handled that. But once again, this is a global event listener. So any form control that changes is going
But once again, this is a global event listener. So any form control that changes is going to fire this event. That means if I change the value of the select, we can see sure enough that value is there and we don't necessarily need to be concerned with any other form control. In this particular case, all we really care about is when the radio buttons change. So what we want to do is filter this down so that if
Filtering for radio group4:49
all we really care about is when the radio buttons change. So what we want to do is filter this down so that if the target's name is, well let's do this. If it's not equal to whatever we have for the name here. And this is one of the few places where the name actually matters in JavaScript because when it comes to radios, if you want to create a radio group, they have to have the same name. So of course names are important in this particular case, but we want to filter out anything
So of course names are important in this particular case, but we want to filter out anything that doesn't have the name of our radio buttons. So if the target's name is not gameTypeSelector, then we're just gonna return because we don't care about this particular event for this particular target. All we care about is if the target is one of our gameTypeSelectors, in which case, well now we care about it.
of our game type selectors, in which case, well now we care about it and we can get the value of the element that we want to show. And because it is an input element, it has a value property. So that's going to give us the ID of the element that we want to show. So whenever we click on mode, we want to show the element with the id of optionsMode. Whenever we click on custom, we want to change that
UI object and closure5:59
with the idea of options mode. Whenever we click on custom, we want to change that to the element with the idea of options custom. So we could do something like this. What I want to do is to start transitioning into more of an object oriented design so that our UI would be essentially controlled by an object that we could call ui. So we could have something like this UI changeGameType, and then we could pass in the ID of the elements.
So we could have something like this UI change game type, and then we could pass in the ID of the elements that we want to change to, which is the value attribute on our radio buttons. Because the values of the value attribute match the IDs of the different UIs that we want to show. So let's do this. Let's create this UI object. And I'm gonna do this at the very top here. So that's, we'll have our UI.
And I'm gonna do this at the very top here. So that's, we'll have our UI have an immediately invoked function and then we will return an object that has that changeGameType method. We have the UI that we want to change, but then the question becomes how do we go about doing this? Well, of course in order to work with and manipulate the elements that we want to work with and manipulate, we need to get them from the document.
and manipulate the elements that we want to work with and manipulate, we need to get them from the document. So what we could do is something like this to where we would have our options custom element to where we would get by. And you know what, I'm gonna do this. You know, eventually we are going to put everything inside of this immediately invoked function. I say everything, we're gonna put a lot of things inside of here because what we want
I say everything, we're gonna put a lot of things inside of here because what we want to do is essentially create a closure, which is, well you'll see here. So we will get by and we want that options custom. And then we have the options mode element, which once again get by the ID is options mode. So inside of this immediately invoked function, we are fetching these element objects. And because we are essentially closing around them,
we are fetching these element objects. And because we are essentially closing around them, we are creating a closure. These are going to remain in memory. So that now anytime that we need to work with these elements from this UI object that we are creating, we don't have to go out and fetch them again, they are already in memory. We have them stored in these constants. So we can just use them as is. This is really the most efficient way of working
So we can just use them as is. This is really the most efficient way of working with DOM objects because once you have them in memory, uh, you don't have to go back into the document and find them again. So it's always best to cache them inside of a variable or a constant so that you can always refer to that variable or constant to work with that element. So in our case, if the given ID is equal to options.customElementId, then we know
So in our case, if the given ID is equal to options.customElementId, then we know that we want to show this options.customElement. So the way that we are going to do that is by changing the class. You know, we have the hidden class for the UI that's hidden. We have the inline class for the UI that is shown. So basically we just want to change the class value from hidden to inline. There are different ways that we can do this,
to change the class value from hidden to inline. There are different ways that we can do this, but the easiest thing to do would be to just use the class property. This is a property that maps directly to the class attributes on that element object. So we can do a lot of things here. If we wanted to clear out all of the classes, we could just assign an empty string and then there are no classes assigned to that element.
we could just assign an empty string and then there are no classes uh, assigned to that element. But in this particular case, we want to inline this because we want to show it, and then we want to take our optionsMode element and we want to make that hidden. But if the ID isn't the same as our optionsCustom element, then we essentially want to do the exact opposite. We want to hide the customSettings so that we can show the gameModeSettings so that now
We want to hide the custom settings so that we can show the game mode settings so that now whenever we are in the browser, if we click on mode and then custom, we see that the game settings changed. We are now displaying all of the custom parameters. But if we click on mode again, we go back to our select box. So this is one of the ways that we can work with radio buttons and JavaScript. Whenever we click on a radio button, we can do something. And that is exactly what we are doing.
Reading radios on submit10:19
Whenever we click on a radio button, we can do something. And that is exactly what we are doing. However, there's another way that we can work with radio buttons, and that would be during the, well, what would essentially be the form submission process. Now of course we're not submitting the form, but whenever we click on play game, we do some normal submission things. Like for example, if the gameMode is custom
we do some normal submission things. Like for example, if the game mode is custom and we have these individual parameters, we need to be able to validate that information and we have the code to validate. But we commented out in the previous episode because, well, we didn't want to make our code not work. So what if we do something like this? If once again we add a property to our ui, we can call it selectedType,
If once again we add a property to our ui, we can call it selectedType, or let's do this selectedGameType. And if it's equal to options.custom, well then we would want to take the data from our form and validate it. So it would look something like this. So that, you know, we, we still need these variables here. So we will start off by getting the values of the input elements so
So we will start off by getting the values of the input elements so that if the game type is the custom game type, then we will validate that information and then play the game. But if it's not the custom game type, then that's when we need to get the selected option so that we can get the appropriate values from the selected option so that then we can create our game and play it.
from the selected option so that then we can create our game and play it. But of course, we need to implement this selected game type property. So let's go back up to where we have created this UI object. And here in our return we are going to create a getter. Now a getter is just a function, but it starts with the get keyword. So we have get, and then the name of our property,
So we have get, and then the name of our property, which is selectedGameType. But this is essentially a function because we need to actually perform some things. We need to get information from our radio buttons. And the way that we do that, well, we could do that in quite a few different ways, but the way that I'm going to do it is by using our form. So let's create a constant so that we can refer to our form.
but the way that I'm going to do it is by using our form. So let's create a constant so that we can refer to our form. I believe the ID is formSettings, but I guess we need to be sure about that. So, oh, it's settingsForm. So that's gonna give us our form because with our form, we can get anything from the form itself. It doesn't matter if it's a radio group, if it's a checkbox, if it's an input element, uh,
It doesn't matter if it's a radio group, if it's a checkbox, if it's an input element, uh, it doesn't matter if it is a form control, we can access that from the form object itself. But since we are working with radio buttons, it's, it's a little bit different. We can use our form, but we have a property called elements. So this elements is just a collection of all of the form controls inside of the form. It doesn't contain any divs or spans or anything like that.
of the form controls inside of the form. It doesn't contain any divs or spans or anything like that. It is strictly form control elements. So input elements, select elements, things like that. And the reason why we want to use this elements property is because it has a method called named item. And we're gonna pass in the name of the Element or the radio group that we want to retrieve. And this is going to return a special kind of collection because we are asking
And this is going to return a special kind of collection because we are asking for essentially a collection of radio buttons. But this is a special collection of radio buttons because it has a value property. And this value property is going to return the value of the selected radio button. So we don't have to check, is this button selected or is this button selected? We don't have to do that. The DOM is automatically going
or is this button selected? We don't have to do that. The DOM is automatically going to give that to us by using named item. We get that special collection of radio buttons that has a value property that returns the value of the selected radio button. So that is basically all we need for the selected game type. So now let's make sure that I haven't forgotten anything. So whenever we submit the form, we prevent the default, we get our elements.
Testing validation and modes14:35
So whenever we submit the form, we prevent the default, we get our elements. Whenever we play the game, we get the values of the input elements, which is fine. If the game type is custom, then we validate that information, otherwise we get the selected option and then we create our game. So yeah, everything should work. Let's go back, let's refresh and we click on custom. We have some things already in there,
Let's go back, let's refresh and we click on custom. We have some things already in there, so I'm just gonna click play game. We can please enter a number between 1 and 1,999. We have 1 attempt, so if this fails, it's over. And sure enough it is. But let's go to our game mode type. Let's select easy. We'll play the game and no, let's, let's do hard because that's easier to see. So if we play the game, pick a number between 1
because that's easier to see. So if we play the game, pick a number between one and a hundred, and yes, everything is working there. So there are essentially two different ways of working with radio buttons with JavaScript. The first is to do something whenever you click on a radio button, which is of course what we do whenever we change the game type. But the second thing is working with that information through a form submission process, which
But the second thing is working with that information through a form submission process, which of course you typically want the value. And while you can retrieve the value of any radio button object, the easiest thing to do is to just use the form object because the form object has an elements property that has a method we can use to get a radio group. And the DOM is going to handle all of the logic of finding the selected value for us.
And the DOM is going to handle all of the logic of finding the selected value for us. So we don't have to do that.
