Beginner JavaScript Tutorial: How to build your own Mad Libs game
Tags: webdev, javascript, beginners, tutorial
Published: 2022-11-20 18:21:31

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](https://en.wikipedia.org/wiki/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](https://codepen.io/) 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](https://www.freecodecamp.org/news/how-to-use-codepen/#how-to-sign-up-for-a-free-account) first and then [fork the pen](https://www.freecodecamp.org/news/how-to-use-codepen/#how-to-fork-a-pen) to get started. Here is the [pen](https://codepen.io/jessica-wilkins/pen/rNKpxqV) 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](https://www.freecodecamp.org/learn/2022/responsive-web-design/).

## Table of Contents

- [Topics covered](#topics-covered)
- [The basic JavaScript functionality for the Mad Libs game](#the-basic-javascript-functionality-for-the-mad-libs-game)
- [Accessing HTML elements using JavaScript](#accessing-html-elements-using-javascript)
- [Declaring variables using the let keyword](#declaring-variables-using-the-let-keyword)
- [Adding addEventListeners for the onchange events](#adding-addeventlisteners-for-the-onchange-events)
- [Adding functionality to the Generate Mad Lib button](#adding-functionality-to-the-generate-mad-lib-button)
  - [Creating a Mab Libs text array](#creating-a-mab-libs-text-array)
  - [How to select a Mad Lib sentence at random using Math.random and Math.floor](#how-to-select-a-mad-lib-sentence-at-random-using-mathrandom-and-mathfloor)
  - [Adding an alert to display when users click on the button without making selections](#adding-an-alert-to-display-when-users-click-on-the-button-without-making-selections)
  - [Displaying the Mad Libs result on the page](#displaying-the-mad-libs-result-on-the-page)
  - [Testing out the generateMadLibBtn event listener](#testing-out-the-generatemadlibbtn-event-listener)
- [Adding a reset function for the user selections](#adding-a-reset-function-for-the-user-selections)
- [Conclusion](#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`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById)
- [`const` and `let` variable declarations](https://www.freecodecamp.org/news/javascript-variables-beginners-guide/)
- [`addEventListener`](https://www.freecodecamp.org/news/javascript-addeventlistener-example-code/)
- [change events](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event)
- [arrow functions](https://www.freecodecamp.org/news/arrow-function-javascript-tutorial-how-to-declare-a-js-function-with-the-new-es6-syntax/)
- [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)
- [click events](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event)
- [arrays](https://www.freecodecamp.org/news/how-to-declare-an-array-in-javascript-creating-an-array-in-js/)
- [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
- [`if` statements](https://www.freecodecamp.org/news/javascript-if-else-and-if-then-js-conditional-statements/)
- [`Math.floor()` and `Math.random()`](https://www.freecodecamp.org/news/generate-random-whole-numbers-within-a-range-javascript/)
- [length property](https://www.freecodecamp.org/news/javascript-array-length/)
- [the `some` array method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
- [return statement](https://www.freecodecamp.org/news/javascript-return-statements/)
- [alert method](https://www.freecodecamp.org/news/how-to-build-a-javascript-alert-box-or-popup-window/)
- [strict equality `===`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality)
- [innerText](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
- [`selectedIndex`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedIndex)

## The basic JavaScript functionality for the Mad Libs game

When you open up the [pen](https://codepen.io/jessica-wilkins/pen/rNKpxqV), you should see the following output.

![opening mad lib project](https://i.imgur.com/gtYtYOs.png)

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](https://i.imgur.com/B15boMu.png)

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](https://i.imgur.com/I3ZdRW3.png)

## 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:

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

```js
document.getElementById("people-dropdown");
```

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

```js
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**

![CodePen console](https://i.imgur.com/xgeQuvt.png)

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:

```js
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:

```js
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:

```js
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:

```js
const generateMadLibBtn = document.getElementById("generate-madlib-btn");
```

Your first six lines of JavaScript code should look like this:

```js
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:

```js
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:

```js
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:

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

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

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

![people dropdown change event](https://i.imgur.com/a5gxSFv.png)

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](https://developer.mozilla.org/en-US/docs/Web/API/Event). The Event interface represents a list of events that can happen in the [DOM(Document Object Model)](https://developer.mozilla.org/en-US/docs/Web/API/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.

```html
<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)`.

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

![logged out name using e.target.value](https://i.imgur.com/A0Euu3R.png)

Let's remove that `console.log` and instead assign the `e.target.value` to the person variable we created earlier.

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

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

```js
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".

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

![clicking mad lib button](https://i.imgur.com/hbb1xMA.png)

We can remove that `console.log` because we know that this click event is working.

```js
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:

```js
`${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:

```js
[value1, value2, value3];
```

Inside the function for our click event, let's create a variable called `madLibsArr` and store our three sentences in there.

```js
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:

```js
//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`.

```js
console.log(Math.random());
```

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

![example of Math.random](https://i.imgur.com/5DLtQ7q.png)

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:

```js
arr.length;
```

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

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

![modified Math.random example](https://i.imgur.com/Ny7GmVq.png)

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.

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

![modified Math.random using Math.floor](https://i.imgur.com/G3jAojf.png)

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

```js
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:

```js

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:

```js
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:

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

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

![alert dialog](https://i.imgur.com/NUULezl.png)

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:

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

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

```js
madLibTextResult.innerText = madLibsArr[randomIndex];
```

### Testing out the generateMadLibBtn event listener

Here is what the entire event listener should look like:

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

![Testing out the Mad Libs function](https://i.imgur.com/TtdTYFc.png)

## 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](https://i.imgur.com/6AeT2Lq.png)

We can add a reset function to accomplish this result.

Below the `madLibTextResult.innerText`, invoke a function called `resetValues`.

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

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

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

```js
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](https://codepen.io/jessica-wilkins/pen/vYrpgaO) for our project. Here is the [final working result](https://codepen.io/jessica-wilkins/full/vYrpgaO).

## Conclusion

I hope you learned a lot with this beginner JavaScript project. For more JavaScript projects like these, please check out the following article:

- [40 JavaScript Projects for Beginners – Easy Ideas to Get Started Coding JS](https://www.freecodecamp.org/news/javascript-projects-for-beginners/)