Project #1: How to Create a Random Quote Generator with JavaScript

Mon Aug 05 2019 / tutorials

Create a Random Quote Machine using a public API and JavaScript

This project is based on a project from the Free Code Camp Curriculum that you can find here.

The goals of this project is to be able to fetch random quote from a public api and display them on our page.

It's a simple task suitable for beginners that will help you learn how to interact with public API to fetch and display data.

 

The result

tutorial 5 gif   You can see a live version of this project at this link: https://inspiredwebdev.com/projects/random-quote/

 

The Task

 

The HTML

Let's first start by creating the structure of our project. Open your text editor and create an index.html file.

The project is very simple, we only need a container where to display quotes, a button to fetch them and a twitter button to share them.

First add this to the head of your html file:

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

We are importing font awesome as we are going to use one of their icon for our twitter button.

Next, let's create the structure of our project which will be like this:

  • container div that will change color every time we get a new quote

    • an inner div
    • a div for the quote
    • a div for the two buttons
<div class="page-content randomBgColor">
  <div id="quote-box">
    <div id="text">
      <i class="fa fa-quote-left randomTxtColor" aria-hidden="true" />
      <span id="quoteText" class="randomTxtColor" />
      <br />
      <span id="quoteAuthor" class="randomTxtColor" />
    </div>

    <div id="buttonBox">
      <a  class="twitter-share-button" id="tweet-quote" target="blank" href="twitter.com/intent/tweet" data-text="custom share text">
        <i class="fa fa-twitter randomBgColor" aria-hidden="true"></i>
      </a>
      <button id="new-quote" class="cta randomBgColor">
        New Quote
      </button>
    </div>
  </div>
</div>

As you can see the structure is quite simple, the classes i have added are mostly for styling and for our JavaScript to target the correct elements in the DOM.

 

book banner Get my ebook on Amazon and Leanpub

 

The CSS

You can skip this part if you want the Random Quote Machine to look differently but if you are interested in achieving the same result as mine, here is the style that I have used.

.randomBgColor {
    transition: background-color 1s ease;

}
.randomTxtColor {
  transition: color 1s ease;
}
#quote-box {
  max-width: 400px;
  width:100%;
  min-height: 200px;
  height: auto;
  margin: 10% auto 10% auto;
  background-color: white;
  padding: 10px;
  padding-bottom: 20px;
  border-radius: 5%;
}
#text {
  padding: 25px;

}
.fa-quote-left {
  font-size: 55px;
  padding-right: 15px;
  display: inline-block;
  width: auto;
}
#quoteText {
  font-size: 25px;
  text-align: center;
  width: 70%;

}
#author {
  font-size: 16px;
  text-align: right;
  display: block;
  width: 100%;
}
#buttonBox {
  height:50px;
  padding: 15px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-content: center;
}
.fa-twitter {
  font-size: 40px;
  padding:5px 5px 0 5px;
  color: white;

}
#new-quote {
  padding:0 10px;
  cursor: pointer;
  color: white;
  font-weight: bold;
  border-radius: 5px;
  border:none;
}
#new-quote:hover {
  opacity: 0.5;
}
.fa-twitter {
  border-radius: 20%;
  border: none;
}

#credit {
  display: block;
  margin: 0 auto;
  width: 150px;
  height: 15px;
  color: white;
}
#credit a, #credit a:hover {
  color: inherit;
  text-decoration: none;
}

 

The JavaScript

This is the most important part of the tutorial, we will learn how to fetch data from the Forismatic API and display it in our page.

For simplicity we will create two function, one to get the quote from the API and one to change the color of our container div.

Let's first start with the easiest one, changing color:

const colorRandomizer = () => {
  const myColors = ['#3498db', '#2ecc71', '#9b59b6', '#e74c3c', '#f1c40f'] //array of colors
  const randomNum = Math.floor((Math.random()*myColors.length)); //generate random number

  const randomColor = myColors[randomNum];
  // modify bg and txt color with my random color
  // get the DOM element
  const bg = document.querySelector('.randomBgColor')
  // set the css attribute on it
  bg.setAttribute('style', `background-color: ${randomColor}`);
  
  const text = document.querySelector('.randomTxtColor');
  text.setAttribute('style', `color: ${randomColor}`)
}

myColors is an array of colors and randomNum will be used to generate and store a random index of the myColors array. randomColor is then applied to both our container div and our quote text with .setAttribute.

Now let's move on to fetching data from the API. There are multiple ways we can achieve that, here we are going to look at fetching data via JSONP which will allow us to quickly overcome the problem of getting content from two different origins (in this case our web page and the Forsimatic API). You can read more about the same-origin policy here.

The same-origin policy is a security mechanism that will restrict usage of resources coming from a different origin. To overcome this, we will inject a script tag in our html document and call that function when making a JSONP ('JSON with padding') request.

The response from our JSONP request will contain the JSON response from the API and a callback function to which we can pass any argument we want.

This type of request can be convenient but it also poses issues when the API server get's compromised as it may lead to malicious code being injected in your page so be careful and use it only for trivial projects such as this one.

const getQuote = (data) => {
  // 1) here we are creating the callback function that we will pass to the JSONP request
  const callbackName = 'displayQuote'
  window[callbackName] = function(data) {
  delete window[callbackName]
  document.body.removeChild(script)
  callback(data)
  }

  // 2) we are injecting the script tag into our HTML
  const script = document.createElement('script')
  script.src =
    url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName
  document.body.appendChild(script)
}

As you saw, we called our callback function displayQuote (const callbackName = 'displayQuote') so let's define it. This will be the function called by our JSONP request and it will take care of passing the text and author of the quote to our HTML elements.

const displayQuote = (data) => {
  const currentQuote = data.quoteText;
  const currentAuthor = data.quoteAuthor;
  //add them to my html
  const text = document.querySelector('#quoteText')
  text.innerHTML = currentQuote
  const author = document.querySelector('#quoteAuthor')
  author.innerHTML = `- ${currentAuthor}`;
  const twitter =  document.querySelector('#twitter-share-button');
  twitter.setAttribute('href', 'https://twitter.com/intent/tweet?hashtags=quotes,Fcc&related=freecodecamp&text=' + encodeURIComponent('"' + currentQuote + '" ' + currentAuthor))
}

We are saving the author and text of the quote in two variables and adding it to our HTML element by using .innerHTML. We are also passing those two values to the Twitter url so that when users press the button, the tweet will be pre-filled with our quote.

Awesome, we are just a few steps away from finishing this project.

Currently, if we try to click our button, nothing happens so let's fix this.

document.querySelector('#new-quote').addEventListener('click', () => {
  getQuote(displayQuote);
})

What we did here was to add an event listener to our button which will fire the getQuote function with the displayQuote as a callback.

The last step to do now is to make it so that when the user visits the page for the first time, a quote will be fetched.

document.addEventListener('DOMContentLoaded', () => {
  getQuote(displayQuote);
}

Great, we are waiting for the page to load and then fire our getQuote function. This way, when you land on the page, a quote will already be there without having to press the button.


Follow InspiredWebDev for more tutorials and let me know if there is anything you would like to learn.

  • Project #1: How to Create a Random Quote Generator with JavaScript