When you are learning JavaScript, it is really important to continually practice your skills and build projects along the way. That is going to help you solidify your knowledge and make you a stronger developer.
In this article, I will walk you through how to create your own Mad Libs using HTML, CSS and JavaScript. Mad Libs is a popular word game where you have an existing piece of text with blank spaces and you ty to fill in those blanks with verbs, nouns and adjectives. Usually the outcome produces some sort of wacky or funny result.
Our goal with this project is to learn about a few different JavaScript concepts and practice some concepts that you have probably worked with before in the past. When you finish the tutorial, I advise to play around with it and expand on it to make it your own. Feel free to create your own styles for this project or add new features.
We will be building out this project in CodePen. CodePen is a popular online code editor used by many developers around the world. It is free to use and you will need to create an account first and then fork the pen to get started. Here is the pen you will need to fork that has all of the HTML and CSS.
Prerequisites
All of the HTML and CSS has been provided for you and we will not be covering any of that in this tutorial. This tutorial assumes that you have basic working knowledge of HTML and CSS. If you are interested in learning about HTML and CSS, then I suggest you go through freeCodeCamp's Responsive Web Design Course.
Table of Contents
- Topics covered
- The basic JavaScript functionality for the Mad Libs game
- Accessing HTML elements using JavaScript
- Declaring variables using the let keyword
- Adding addEventListeners for the onchange events
- Adding functionality to the Generate Mad Lib button
- Adding a reset function for the user selections
- Conclusion
Topics covered
Here is a list of all of the JavaScript and Web API topics that we will cover in this tutorial. Each topic has a link to a helpful article or MDN page if you are interested in learning more.
getElementById
const
andlet
variable declarationsaddEventListener
- change events
- arrow functions
- undefined
- click events
- arrays
- template strings
if
statementsMath.floor()
andMath.random()
- length property
- the
some
array method - return statement
- alert method
- strict equality
===
- innerText
selectedIndex
The basic JavaScript functionality for the Mad Libs game
When you open up the pen, you should see the following output.
When a user chooses a name, location, verb and food item and clicks on the Generate Mad Lib button, the game should return a text result with their selections.
If the user does not provide all four selections and clicks on the Generate Mad Lib button, then we will show them an alert box.
Accessing HTML elements using JavaScript
Our project has four select
elements and we need to be able to access each of those elements using JavaScript. The reason why we need access to those HTML elements, is because we want to have access to the user's selections so we can show them in the final result.
There are a few ways to access elements using JavaScript. In this project we are going to use the getElementById
method. This method will access the HTML element that matches the id that we specify. Since id names have to be unique in an HTML document, we can be certain that we are getting back the correct element.
Here is the basic syntax for the getElementById
method:
document.getElementById(id);
The first select
element we want to access is the one with the id of people-dropdown
.
Add this line of code to the top of your JavaScript section in CodePen.
document.getElementById("people-dropdown");
If you are curious on what this method returns, then I would suggest using console.log
like this:
console.log(document.getElementById("people-dropdown"));
Note: To access the console in CodePen, click on the console button in the bottom left hand corner of the screen
You can use console.log
to print messages to the console output. This method comes in handy when you need to understand what your code is doing.
Now that we have seen what the getElementById
method returns, we can remove that console.log
and assign the document.getElementById("people-dropdown")
to a variable to use later on. We are going to use the const
keyword here because this const
variable will not be re assigned.
Your first line of the project should look like this:
const peopleDropdown = document.getElementById("people-dropdown");
Just below that line of code, we want to access the other select
elements and assign them to const
variables.
Add these lines of code here:
const verbsDropdown = document.getElementById("verbs-dropdown");
const locationDropdown = document.getElementById("location-dropdown");
const foodDropdown = document.getElementById("food-dropdown");
Next, we need to access this <p id="madlib-text"></p>
element which is responsible for displaying the Mab Lib results on the page.
We can access that element using the getElementById
method again like this:
const madLibTextResult = document.getElementById("madlib-text");
The last HTML element that we need to access is the "Generate Mad Lib" button.
We can access that element using the getElementById
method again like this:
const generateMadLibBtn = document.getElementById("generate-madlib-btn");
Your first six lines of JavaScript code should look like this:
const peopleDropdown = document.getElementById("people-dropdown");
const verbsDropdown = document.getElementById("verbs-dropdown");
const locationDropdown = document.getElementById("location-dropdown");
const foodDropdown = document.getElementById("food-dropdown");
const madLibTextResult = document.getElementById("madlib-text");
const generateMadLibBtn = document.getElementById("generate-madlib-btn");
Declaring variables using the let keyword
We have already started to work with the const
keyword which represents a read-only and immutable variable. This means that we can not re assign the value like this:
const firstName = "Jessica";
// this is not allowed and will return an error
firstName = "Nancy";
But there will times where we will need to re assign a value. That is where the let
keyword comes in. When you declare variables using let
, then you are allowed to assign new values to them like this:
let firstName = "Jessica";
// this is allowed and firstName now holds the value of Nancy
firstName = "Nancy";
In our program, we have four variables that represent the user selections: person, verb, site, and food.
Just below our const
declarations, we will need to add these lines of code:
let person;
let verb;
let site;
let food;
We are going to assign values to these variables later on in the code.
Adding addEventListeners for the onchange events
A large part of this program is having the ability to detect when a user has selected a choice from one of the given dropdowns and save that value to a variable. In JavaScript, there are methods that you can use to detect when a user has done something in your program.
The addEventListener
is used to detect events in your program and execute a function when that event has occurred. The event that we are listening for is the change event to represent when a user makes a selection from the dropdown.
Let's start by adding an event listener for the peopleDropdown
variable.
peopleDropdown.addEventListener("change" /*function goes here*/);
To test out our event listener, let's add an arrow function to log to the console "event fired".
Note: Arrow functions in JavaScript are another way to write function expressions.
peopleDropdown.addEventListener("change", () => console.log("event fired"));
In CodePen, open up your console, choose one of the names from the people dropdown menu and you should see the message "event fired" show up in the console.
Now, that we know our event listener is working we now need to focus on getting the name that the user has chosen. We can start by working with the Event interface. The Event interface represents a list of events that can happen in the DOM(Document Object Model) and it contains its own properties.
In our case, we are interested in getting the person's name from the select
element so we can use event.target.value
. Note: A lot of times, you will see people use e.target.value
too.
The value
in e.target.value
corresponds with the value attributes from the option
elements in our HTML here.
<option value="Susie">Susie</option>
<option value="Zac">Zac</option>
<option value="Amar">Amar</option>
<option value="Naya">Naya</option>
<option value="Ada">Ada</option>
Let's modify our function to log out the event. We are going to add the parameter of e
to our arrow function and console.log(e.target.value)
.
peopleDropdown.addEventListener("change", (e) => console.log(e.target.value));
Now when you select a name from the people dropdown list, you should see that name in the console.
Let's remove that console.log
and instead assign the e.target.value
to the person variable we created earlier.
peopleDropdown.addEventListener("change", (e) => (person = e.target.value));
Let's finish this section out by adding event listeners for the rest of the dropdown menus.
peopleDropdown.addEventListener("change", (e) => (person = e.target.value));
verbsDropdown.addEventListener("change", (e) => (verb = e.target.value));
locationDropdown.addEventListener("change", (e) => (site = e.target.value));
foodDropdown.addEventListener("change", (e) => (food = e.target.value));
Adding functionality to the Generate Mad Lib button
Now that we have the change events setup, we now need to focus on the button functionality that is responsible for generating the new mad lib when the user clicks on the button.
The first step is to create a new event listener for the generateMadLibBtn
variable that will listen for click
events.
generateMadLibBtn.addEventListener("click", () => {
// our main button functionality will go here
});
To test our new click event, let's log to the console.log a message that says "this button was clicked".
generateMadLibBtn.addEventListener("click", () => {
console.log("this button was clicked");
});
You can test this out by opening up your console and clicking on the button to see this new message.
We can remove that console.log
because we know that this click event is working.
generateMadLibBtn.addEventListener("click", () => {
// our main button functionality will go here
});
Creating a Mab Libs text array
Part of the Mab Libs game is to have an existing piece of text to work with. For our program, we are going to create three sentences and add our four variables (person, verb, site, and food) into each of those sentences.
We can use what are called template strings(or template literals) to inject variables inside strings. Remember that these variables represent the values for each of the user's selections from the dropdown menus. When the user clicks on the button, then the real values will be used inside these sentences.
To use template strings, you will need to use backticks instead of double("") or single('') quotes.
Here is what our three sentences will look like:
`${person} was ${verb} in ${site} and had ${food}.`
`While ${verb} in ${site}, ${person} had ${food}.`
`${person} loves to travel to ${site} and eat ${food} while ${verb}.`
We want to be able to store these sentences somewhere so we can use them later. We can use an array
which is a list of ordered values.
Here is the basic syntax for arrays:
[value1, value2, value3];
Inside the function for our click event, let's create a variable called madLibsArr
and store our three sentences in there.
generateMadLibBtn.addEventListener("click", () => {
const madLibsArr = [
`${person} was ${verb} in ${site} and had ${food}.`,
`While ${verb} in ${site}, ${person} had ${food}.`,
`${person} loves to travel to ${site} and eat ${food} while ${verb}.`,
];
});
How to select a Mad Lib sentence at random using Math.random and Math.floor
When the user clicks on the "Generate Mad Lib" button, we want a random sentence from our list to show up each time to help keep the game more interesting. We can achieve this result by getting a random index value back each time the button is clicked. You can access array values by using bracket notation and the index number like this:
//Arrays are zero based indexed which means that the first value of any array will be `arr[0]`.
madLibsArr[0];
// this will return the first sentence in the array: ${person} was ${verb} in ${site} and had ${food}.
The first step is to work with the Math.random()
function. Math.random()
will generate a pseudo random number between 0 and just less than 1.
Let's test this by adding a console.log
just below the madLibsArr
.
console.log(Math.random());
Open up the console and click on the "Generate Mad Lib" button to see the different random numbers it generates.
Our goal is to get a random number of either 0, 1, or 2 so we can use one of those index numbers in our madLibsArr
. But right now we are getting back results of 0.154 or 0.762.
We can multiply Math.random()
by the length of the madLibsArr
to get random numbers between 0 and less than 3. The length
property is used to get the total number of items in an array.
Here is the basic syntax for the length property:
arr.length;
Let's modify our console.log to multiple Math.random()
by the length of the madLibsArr
console.log(Math.random() * madLibsArr.length);
Open up the console and click on the "Generate Mad Lib" button to see the different random numbers it generates. You should now see numbers between 0 and less than 3.
This modification brings us closer to our goal of generating a random number of either 0, 1, or 2 but we are still working with decimal values. We can fix this by using Math.floor
which will round the value down to the nearest whole integer.
Let's modify our console.log
to wrap our Math.random() * madLibsArr.length
inside the Math.floor
method.
console.log(Math.floor(Math.random() * madLibsArr.length));
Open up the console and click on the "Generate Mad Lib" button to see the different random numbers it generates. You should now see numbers of 0, 1 or 2.
The final step, is to assign this random number to a const
variable called randomIndex
so we can use it later on in a our code.
Remove the console.log
and add the following line of code underneath the madLibsArr
.
const randomIndex = Math.floor(Math.random() * madLibsArr.length);
Adding an alert to display when users click on the button without making selections
If the user clicks on the "Generate Mad Lib" button without making selections from the dropdowns, then we want to display a message to let them know that the program requires them to select an option from all four of the dropdown menus.
We first need to add an if
statement below the randomIndex
variable. An if
statement is a type of conditional statement that will run a block of code if the condition is true.
Here is the basic syntax for an if
statement:
if(/*condition is true*/){
// run this code here
}
For the condition in our if
statement, we want to check if any of the four variables(person, verb, site, and food) is undefined
because that means the user has not made a selection from the dropdown. undefined
means that a variable has not been assigned a value.
One way to write this condition would be to use the strict equality and OR operators like this:
if (
person === undefined ||
verb === undefined ||
site === undefined ||
food === undefined
) {
// run this code here
}
While this would technically work, it is a little repetitive and there is another method we could use instead. The arr.some()
method takes in a function and checks if any of the elements in the array will returns true. We can use this method to check if any of the four variables returns undefined.
Here is the modified condition using the some
method:
if (
[person, verb, site, food].some(
(userSelection) => userSelection === undefined
)
) {
// run this code here
}
Inside the {}
for the if
statement, we can add an alert
to display a message to the user.
if (
[person, verb, site, food].some(
(userSelection) => userSelection === undefined
)
) {
alert("Please choose a selection from each of the dropdowns");
}
Let's test this out by clicking on the "Generate Mad Lib" button without making any selections from the dropdown menus.
The last piece we need to add is a return
statement below the alert
function. We need to add this return
statement because we want to exit our function if the user does not make any selections.
Here is the entire if
statement:
if (
[person, verb, site, food].some(
(userSelection) => userSelection === undefined
)
) {
alert("Please choose a selection from each of the dropdowns");
return;
}
Displaying the Mad Libs result on the page
The madLibTextResult
represents the paragraph element in our HTML that will display the Mad Libs result. We can use the innerText
method to render the Mad Libs text with the user's selections on the page.
madLibTextResult.innerText = /*mad libs text goes here*/
When it comes to the Mad Libs text, we want to use the randomIndex
variable that we created earlier, to randomly pull a sentence from our madLibsArr
.
madLibTextResult.innerText = madLibsArr[randomIndex];
Testing out the generateMadLibBtn event listener
Here is what the entire event listener should look like:
generateMadLibBtn.addEventListener("click", () => {
const madLibsArr = [
`${person} was ${verb} in ${site} and had ${food}.`,
`While ${verb} in ${site}, ${person} had ${food}.`,
`${person} loves to travel to ${site} and eat ${food} while ${verb}.`,
];
const randomIndex = Math.floor(Math.random() * madLibsArr.length);
if (
[person, verb, site, food].some(
(userSelection) => userSelection === undefined
)
) {
alert("Please choose a selection from each of the dropdowns");
return;
}
madLibTextResult.innerText = madLibsArr[randomIndex];
});
Test out your application and you should be able to make four selections and see the Mad Libs results.
Adding a reset function for the user selections
We now have a working program but it would be nice if every time we generated a Mad Lib, the text would display and the dropdowns would default to their original state like this:
We can add a reset function to accomplish this result.
Below the madLibTextResult.innerText
, invoke a function called resetValues
.
generateMadLibBtn.addEventListener("click", () => {
const madLibsArr = [
`${person} was ${verb} in ${site} and had ${food}.`,
`While ${verb} in ${site}, ${person} had ${food}.`,
`${person} loves to travel to ${site} and eat ${food} while ${verb}.`,
];
const randomIndex = Math.floor(Math.random() * madLibsArr.length);
if (
[person, verb, site, food].some(
(userSelection) => userSelection === undefined
)
) {
alert("Please choose a selection from each of the dropdowns");
return;
}
madLibTextResult.innerText = madLibsArr[randomIndex];
resetValues();
});
Above the generateMadLibBtn
event listener, create a new function called resetValues
.
const resetValues = () => {
// reset functionality will go here
};
The goal for this resetValues
function is to set all of the dropdowns to their original state of "Please select an option". We can use the selectIndex
property to set each of the dropdowns to the first option in the select list which will be an index of 0.
const resetValues = () => {
peopleDropdown.selectedIndex = 0;
verbsDropdown.selectedIndex = 0;
locationDropdown.selectedIndex = 0;
foodDropdown.selectedIndex = 0;
};
Then we also want to set all of four variables(person, verb, site, and food) back to undefined
.
const resetValues = () => {
peopleDropdown.selectedIndex = 0;
verbsDropdown.selectedIndex = 0;
locationDropdown.selectedIndex = 0;
foodDropdown.selectedIndex = 0;
person = undefined;
verb = undefined;
site = undefined;
food = undefined;
};
Now you can test out your function and you should see that each time you create a new Mad Lib, the select dropdowns will return to their default states.
Here is the entire code for our project. Here is the final working result.
Conclusion
I hope you learned a lot with this beginner JavaScript project. For more JavaScript projects like these, please check out the following article: