Learn JavaScript by building a Random Quote Machine

In this article, we will tackle another freeCodeCamp project - building a Random Quote Machine with JavaScript.

This tutorial is aimed at folks learning their first programming language.

I assume basic familiarity with HTML (HyperText Markup Language) and CSS (Cascading StyleSheets), but you do not need to have any prior experience with JavaScript to follow this tutorial as I will explain each step as I go.

To complete this tutorial, all you need is a modern web browser (such as Firefox or Chrome) and a working Internet connection.

If you get stuck, leave a comment below and I’ll get back to you as soon as I can.

User Stories

These are the user stories for the app:

  1. I can click a button to show a new random quote.
  2. I can press a button to tweet out a quote.

You can view the completed version of the app here. The code for this project lives on GitHub.

Starting point on JSFiddle

Getting Started

I have created a starting point for this tutorial on JSFiddle. You will see that it already contains some HTML and CSS which is used to markup and style the application.

The JavaScript pane is empty though as that is where we will write the code to fulfill the user stories.

Starting point on JSFiddle

User Story #1 - Display a Random Quote

One of the most basic use cases for the JavaScript programming language is to add interactivity to a web page so that when a user does something, elements on the page will respond by performing an action.

JavaScript is used for just about everything these days, such as server infrastructure, desktop and mobile apps, but this is still the quickest way to put to practice what you learn.

If you look at the application in its current state, you will see that it’s really just a static page that doesn’t respond to user interaction. Clicking on the buttons does not do anything.

The page contains two buttons, the “New Quote” button which is what will be used to fetch a new quote and display it on the page (user story #1), and a “Tweet” button for sharing a quote on Twitter (user story #2).

The first task specifies that when the “New Quote” button is clicked, a random quote is displayed to the user.

To accomplish this, the first thing to do is to store a reference to the “New Quote” button in our JavaScript code.

If you peer into the HTML pane, you will see the markup for the “New Quote” button as follows:

<button type="button" class="new-quote button">New Quote</button>

The class attribute present is not only useful for styling the element with CSS but also for selecting an element with JavaScript.

There are many ways to select an element in JavaScript but I will show you a way that has some similarities to how you’d do it in CSS.

In CSS, you’d do this:

.classname {
  // style properties go here  
}

In JavaScript, you do this:

document.querySelector(".classname");

Notice that the class selector is enclosed in double quotes in the JavaScript example. You can also use single quotes like this:

document.querySelector('.classname');

I will continue to use double quotes for the remainder of this tutorial.

Here’s how we can select the “New Quote” button with JavaScript:

document.querySelector(".new-quote");

Next, we need to store the reference to the .new-quote button in a variable.

Variables in JavaScript are containers for holding values and other data structures so that you can reuse them as many times as you like.

There are quite a few ways to create variables in JavaScript. Most beginner tutorials will show you how to create variables using the var keyword.

var identifier = value;

Two additional ways to create a variable in JavaScript involve the use of the const and let keywords:

const identifier = value;
let identifier = value;

Variables need to have unique identifiers. These identifiers can consist of letters, numbers, underscores, and dollar signs. However, they cannot start with numbers (only letters, underscores, and dollar signs).

Identifier names are also case sensitive (meaning ziggy and ZIGGY are different variables) and they cannot be keywords (reserved words) in the language.

When you declare a variable, you need to assign it to a value. The equal to sign =, known as the assignment operator, is what is used to assign values to variables.

Here’s how you declare a variable and assign a value to it in JavaScript:

const age = 40;

The variable above has age as its identifier and 40 as its value.

Go ahead and type this into the JavaScript pane in JSFiddle:

const newQuoteButton = document.querySelector(".new-quote");

This assigns a reference to the “New Quote” button to a new variable called newQuoteButton. Now, we can use the newQuoteButton variable anywhere in our application knowing that it will always refer to the “New Quote” button.

Listening for events on an element

Next, we need to listen for the click event on the button so that we can know when the button is clicked by the user.

DOM (Document Object Model) events are signals sent by the browser when specific actions take place on a webpage, usually as a result of user interaction. Developers can setup their code to listen for any of these events and perform certain operations when the events are triggered.

The way we listen for an event on an element is to attach the addEventListener method to the element and pass it two arguments.

Type this under the newQuoteButton declaration:

newQuoteButton.addEventListener("click", getQuote);

Arguments are the values between the parenthesis. The first one, click, is the event we want to listen for and the second one getQuote is the callback function that will be invoked when the click event is triggered on newQuoteButton.

A function is a block of code defined to perform a specific task. It is used to encapsulate code that we want to reuse many times so we don’t have to go through the trouble of duplicating it. This makes code easier to reason about.

The function keyword is used to declare functions in JavaScript. The syntax is as follows:

function name() {}

The above function can be invoked or ‘called’ using name(). When you invoke a function, it executes the code defined in its body (between the two curly braces {}).

We haven’t declared the getQuote function yet so we must do so in the next step, otherwise an error is thrown and the program breaks.

Type this into the JavaScript pane, just before the newQuoteButton declaration:

function getQuote() {
  console.log("newQuoteButton was clicked");
}

Here, we have created a new function, assigned it a name getQuote and logged some text to the console.

Open the console in your browser (Ctrl+Shift+J / Cmd+Opt+J in Chrome and Ctrl+Shift+K / Cmd+Opt+K in Firefox). Now click the newQuote button a few times, you will see “newQuoteButton was clicked” printed to your console.

Using console.log

If you click anywhere else on the page outside the “New Quote” button, nothing happens. This is because we only listened for the click event on the button so getQuote is only invoked when “New Quote” is clicked.

Fetching random quotes using an API

Presently, we are logging some text to the console when the newQuote button is clicked but what we really need to do is to fetch a random quote from somewhere and show it to the user.

One way to do this, and this is the approach I took the first time I did this project, is to hard-code the quotes into your app use it from there.

A more realistic approach is to get the data using an API.

There are several APIs that can help you add this functionality to your application. The one we’ll be working with in this tutorial is What Does Trump Thinks which provides generic Donald Trump quotes.

To receive data from an API, you need to know the endpoint that will return the specific data that you need. You will usually find this information by taking a look at the documentation of the API you wish to use.

What Does Trump Thinks’ API documentation specifies that we use the following endpoint to get a random quote:

https://api.whatdoestrumpthink.com/api/v1/quotes/random

Let’s save this endpoint in a variable. Above the getQuote function, type this:

const endpoint = "https://api.whatdoestrumpthink.com/api/v1/quotes/random";

Next, we need to make a request to What Does Trump Thinks to grab a random quote. To do this, we will use the a mechanism in the browser called fetch.

Modify the getQuote function to look like this:

function getQuote() {
  fetch(endpoint)
    .then(function (response) {
      return response.json();
    })
    .then(function (data) {
      console.log(data);
    });
}

The simplest use of fetch takes a single argument - the path or url to the resource you want to fetch - and returns what is known as a Promise.

The first use of .then() converts the raw response into JSON (since that’s what we are expecting from What Does Trump Thinks). To access the actual data, we need to chain another .then() method and then access the data from there.

Try it out. Open up your browser console and click the “New Quote” button a few times. You will see the JSON object returned by What Does Trump Think API.

Logging JSON Data to the console

If you examine the JSON object, you will see that the quote is stored in the message key and it contains a different quote each time.

Examine JSON

The object contains some other keys such as nlp_attributes which we don’t need for this tutorial. We can access the value in the message key using dot notation like this: data.message.

If we wanted to access the value of the nlp_attributes key, we would use data.nlp_attributes.

Change the getQuote function to look like this:

function getQuote() {
  fetch(endpoint)
    .then(function (response) {
      return response.json();
    })
    .then(function (data) {
      console.log(data.message);
    });
}

Now, click the “New Quote” button a few times once more. You will see that only the quote is logged to the console, instead of the whole JSON object.

Print quote to console

Display the quote on the page

We will create a new function for this purpose. Type this just below the getQuote function:

function displayQuote(quote) {
          
}

The displayQuote function is where we will wrap the code that will display the quote to the user. It takes one parameter, quote which is the quote we will display on the page.

Go ahead and write the code that will display the quote on the page:

function displayQuote(quote) {
  const quoteText = document.querySelector(".quote-text");
  quoteText.textContent = quote;     
}

First, we save a reference to <div class="quote-text"></div> in the quoteText variable which is where we want the quote to be inserted. Next, we assign the textContent of the quoteText element to the quote we want to display.

This replaces the contents of the quoteText element with a single text node that contains the quote we want to display.

At this point, if you click the “New Quote” button again, nothing is shown on the page. This is because, while we have defined the displayQuote function, we have not yet invoked it from anywhere and we have to do that before the code in the body of the function will be executed.

So go back to the getQuote function and change it to look like this:

function getQuote() {
  fetch(endpoint)
    .then(function (response) {
      return response.json();
    })
    .then(function (data) {
      displayQuote(data.message);
    });
}

Now, each time a new quote is received from What Does Trump Thinks, the displayQuote function is summoned and the quote is passed to it. The code we wrote in the body of displayQuote is then executed resulting in the quote being displayed on the page.

Try it out. Click the “New Quote” button a few times. You will see a new random quote displayed on the page each time.

User Story 2 - Tweet out a quote

To complete our application, we need to be able to tweet out each quote that is displayed on the page.

We already have the Tweet button on the page (actually a link which I styled to look like a button) but clicking it does not have any effect.

<a class="twitter button" target="_blank" rel="noreferrer">Tweet</a> 

This is because the link does not have an href attribute so it does not link to anywhere. Our task is to dynamically set this attribute so that it will link to Twitter’s tweet page and pre-populate the text input with the quote we want to tweet out.

We can create another function to do this, but that’s probably overkill. Instead, let’s add that functionality to the displayQuote function:

function displayQuote(quote) {
  const quoteText = document.querySelector(".quote-text");
  quoteText.textContent = quote;
      
  const twitterButton = document.querySelector(".twitter");
  twitterButton.setAttribute("href", `https://twitter.com/share?text=${quote}`);
}

First, as before, we save a reference to the element we want to work with in a variable - in this case the Tweet button.

Next, we set the href attribute using the setAttribute method which takes two arguments: The attribute we want to set (href) and the value of the attribute (https://twitter.com/share?text=${quote}).

You might be wondering why I used backticks for the second argument instead of double quotes. This is because we want to interpolate the value of the quote parameter into Twitter’s share tweet URL.

To interpolate the value of a variable or expression into a string, we use Template Literals which specifies that we enclose the entire string in backticks (``) and insert any placeholders ${expression} anywhere in the string so that the value of the expression is interpolated into the string and replaces the placeholder.

So if the value of quote is “Today, Iraq is Harvard for terrorism.” for example,${quote} will be replaced by the value and the twitter share url becomes “https://twitter.com/share?text=Today, Iraq is Harvard for terrorism.”

This is how we are able to dynamically set the href attribute of the Tweet button to the share url that is pre-populated with any quote that is received from What Does Trump Think.

Now, click the Tweet button. This will open Twitter’s share tweet page in a new tab and you will see that the contents of the text box is pre-populated with the displayed quote.

Tweet quote

One improvement we can make is to specify Donald Trump as the author of the quote in the tweet message. Change the second argument of setAttribute to this:

https://twitter.com/share?text=${quote} - Donald Trump
function displayQuote(quote) {
  const quoteText = document.querySelector(".quote-text");
  quoteText.textContent = quote;
      
   const twitterButton = document.querySelector(".twitter");
   twitterButton.setAttribute("href", `https://twitter.com/share?text=${quote} - Donald Trump`);
}

Now try to tweet out a quote, it should indicate Donald Trump as the author.

Tweet quote

The second user story is thus fulfilled!

One more thing…

You may notice that, on a fresh load of the application, no quotes are displayed and the tweet button does not work.

We can fix this easily by adding the following line to the end of the program:

getQuote();

This invokes getQuote once so that a quote is displayed to the user immediately. New quotes will then be requested and displayed once the user clicks the “New Quote” button.


That concludes my tutorial. I hope it has helped you learn the basics of JavaScript and how you can use it to build simple web applications.

If you have a question or feedback about this tutorial, leave a comment below and I’ll get to it as soon as possible.