Beginner JavaScript Tutorial: How to build your own Mad Libs game

Jessica Wilkins - Nov 20 '22 - - Dev Community

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

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.

The basic JavaScript functionality for the Mad Libs game

When you open up the pen, you should see the following output.

opening mad lib project

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.

madlibs result

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.

madlibs alert

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);


Enter fullscreen mode Exit fullscreen mode

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");


Enter fullscreen mode Exit fullscreen mode

If you are curious on what this method returns, then I would suggest using console.log like this:



console.log(document.getElementById("people-dropdown"));


Enter fullscreen mode Exit fullscreen mode

Note: To access the console in CodePen, click on the console button in the bottom left hand corner of the screen

CodePen console

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");


Enter fullscreen mode Exit fullscreen mode

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");


Enter fullscreen mode Exit fullscreen mode

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");


Enter fullscreen mode Exit fullscreen mode

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");


Enter fullscreen mode Exit fullscreen mode

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");


Enter fullscreen mode Exit fullscreen mode

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";


Enter fullscreen mode Exit fullscreen mode

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";


Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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*/);


Enter fullscreen mode Exit fullscreen mode

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"));


Enter fullscreen mode Exit fullscreen mode

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.

people dropdown change event

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>


Enter fullscreen mode Exit fullscreen mode

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));


Enter fullscreen mode Exit fullscreen mode

Now when you select a name from the people dropdown list, you should see that name in the console.

logged out name using e.target.value

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));


Enter fullscreen mode Exit fullscreen mode

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));


Enter fullscreen mode Exit fullscreen mode

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
});


Enter fullscreen mode Exit fullscreen mode

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");
});


Enter fullscreen mode Exit fullscreen mode

You can test this out by opening up your console and clicking on the button to see this new message.

clicking mad lib button

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
});


Enter fullscreen mode Exit fullscreen mode

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}.`


Enter fullscreen mode Exit fullscreen mode

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];


Enter fullscreen mode Exit fullscreen mode

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}.`,
  ];
});


Enter fullscreen mode Exit fullscreen mode

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}.


Enter fullscreen mode Exit fullscreen mode

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());


Enter fullscreen mode Exit fullscreen mode

Open up the console and click on the "Generate Mad Lib" button to see the different random numbers it generates.

example of Math.random

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;


Enter fullscreen mode Exit fullscreen mode

Let's modify our console.log to multiple Math.random() by the length of the madLibsArr



console.log(Math.random() * madLibsArr.length);


Enter fullscreen mode Exit fullscreen mode

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.

modified Math.random example

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));


Enter fullscreen mode Exit fullscreen mode

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.

modified Math.random using Math.floor

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);


Enter fullscreen mode Exit fullscreen mode

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
}


Enter fullscreen mode Exit fullscreen mode

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
}


Enter fullscreen mode Exit fullscreen mode

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
}


Enter fullscreen mode Exit fullscreen mode

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");
}


Enter fullscreen mode Exit fullscreen mode

Let's test this out by clicking on the "Generate Mad Lib" button without making any selections from the dropdown menus.

alert dialog

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;
}


Enter fullscreen mode Exit fullscreen mode

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*/


Enter fullscreen mode Exit fullscreen mode

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];


Enter fullscreen mode Exit fullscreen mode

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];
});


Enter fullscreen mode Exit fullscreen mode

Test out your application and you should be able to make four selections and see the Mad Libs results.

Testing out the Mad Libs function

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:

reset button for mad libs

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();
});


Enter fullscreen mode Exit fullscreen mode

Above the generateMadLibBtn event listener, create a new function called resetValues.



const resetValues = () => {
  // reset functionality will go here
};


Enter fullscreen mode Exit fullscreen mode

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;
};


Enter fullscreen mode Exit fullscreen mode

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;
};


Enter fullscreen mode Exit fullscreen mode

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:

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .