Display random quotes from Chuck Norris API
Tags: webdev, beginners, javascript
Published: 2021-10-09 01:31:16

What a fun way to learn JavaScript than by building projects. In my previous blog post, I showed how one can  [build a random quote generator using arrays](https://dev.to/kritikapattalam/build-a-random-quote-generator-using-javascript-2n5j), it was simple and beginner-friendly. It would have helped one understand how to get started when building projects or how to address a problem. 

I thought let me take this one step above and show how one can create a similar random quote generator using an API, and I am going to be using the famous Chuck Norris API for this. 

Let's get started.

#### What will we learn as part of this blog
- function declaration vs function expression
- window.onload function
- Fetch() method
- attaching onclick eventlistener to an element

### What will be the end result
- Create random quotes on button click. The quotes are going to be from the Chuck Norris API
- Add a dropdown category filter that will display random quotes from the category chosen.

### Project structure
Create the list of files as listed below
1. index.html
2. script.js
3. style.css [ styles if we have any. As part of this blog, I am not going to add any styles.].

### HTML
HTML is going to be very simple

1. **Select field for the category**-  A simple select field with a list of all categories available in the Chuck Norris API. The options from inside the select field are created by the retrieved list from here 
 [Retrieve the categories](https://api.chucknorris.io/jokes/categories)
https://api.chucknorris.io/jokes/categories

2. **Section to display Quotes** - A div "display_facts", is going to have the img tag which is going to have the chuck Norris icon from the API, and a p tag which will be populated with the quote from the API

3. **Generate Quote button** - This is the button onclick of which we will generate/retrieve a new quote from the API.

```` html
<!Doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Random Quote Generator</title>
        <link rel="stylesheet" href="styles.css">
        <script src="script.js"></script>
    </head>
    <body>
       <div class="outer-container">
           <div class="heading">
                   <h3>Chuck Norris Facts - Select category from the dropdown</h3>
                       <select id="category">
                            <option value="all">All</option>
                            <option value="animal">Animal</option>
                            <option value="career">Career</option>
                            <option value="celebrity">Celebrity</option>
                            <option value="explicit">Explicit</option>
                            <option value="fashion">Fashion</option>
                            <option value="food">Food</option>
                            <option value="history">History</option>
                            <option value="money">Money</option>
                            <option value="movie">Movie</option>
                            <option value="music">Money</option>
                            <option value="political">Political</option>
                            <option value="religion">Religion</option>
                            <option value="science">Science</option>
                            <option value="sport">Sport</option>
                            <option value="travel">Travel</option>
                        </select>
           </div>
           <div class="display_facts">
                <img src="" id="icon" />
                <p id="quote">Author</p>
           </div>
            <button id="generate">Generate</button>
       </div>
    </body>
</html>
```
### JavaScript 
Let's break this down into four steps
1. Create an array inside a function and call that function on window load.
2. Check what is Chuck Norris API capable of.
3. Using fetch method retrieve all the results
4. Generate quote on button click
5. Let's generate quotes based on the category selected.

#### 1) Create an array inside a function and call that function on window load.
This can be done in two ways using **function expression** or vs **function declaration**.  Read more about it  [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function) .
The main difference with function expression is they are not hoisted, you cannot call the function expression before they are declared.

- In the below example, I created a function called **generateQuote**, which contains a console.log hi. 
- Next inside window.onload function I call the function generateQuote.

Now save this file, and open index.html in your browser. In the chrome developer tool console, you should see the text "hi". What happens here is,  once the entire window including the DOM & assets is loaded, generateQuote function is called.


> 
As per MDN docs, The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links, and sub-frames have finished loading.


```` javascript
const generateQuote = function() {
     console.log("Hi");
}
window.onload = function() {
    generateQuote();
 }
```
### 2. Check what is Chuck Norris API capable of.

As part of this step, we are going to retrieve the results from the Chuck Norris API

Let's first see go check out the API 

 [ChuckNorris API](https://api.chucknorris.io/) 

An important tip for anyone trying to use an API is to read the documentation of the API, they usually have answers to all your questions as to how to use them and what is the API capable of doing. 

When reading the API docs, what we concur is that the API is capable of doing the following things
- Retrieve random quotes
- Retrieve a list of random quotes based on a list of categories
- Retrieve the list of category
- Retrieve quotes based on the text entered by the user.

### 3. Using fetch method retrieve all the results
As per the docs, the URL to fetch the results in a JSON format is to use the below URL
```
//Retrieve a random chuck joke in JSON format.
GET https://api.chucknorris.io/jokes/random
``` 
Just try opening this URL  [https://api.chucknorris.io/jokes/random](https://api.chucknorris.io/jokes/random) in a browser window, you should see a similar response that is a single random quote with below details 
- The time when the random joke was created
- an icon image of Chuck Norris
- id for that particular quote
- the updated date
- a URL to the quote on the Chuck Norris API page
- value - which is actually the quote that will be displayed on our page.

```` javascript
//The result has been formatted for a better view
{
   "categories":[
      
   ],
   "created_at":"2020-01-05 13:42:24.142371",
   "icon_url":"https://assets.chucknorris.host/img/avatar/chuck-norris.png",
   "id":"DciuboTEQxqEaVG0Qd2T2w",
   "updated_at":"2020-01-05 13:42:24.142371",
   "url":"https://api.chucknorris.io/jokes/DciuboTEQxqEaVG0Qd2T2w",
   "value":"Chuck Norris flashes the peace sign a lot because it's the easiest way to go for the eyes."
}
```
Now try refreshing the API URL and you should see a different response. Let's go ahead and see how to add this via code and display it on the page.

The fetch method accepts one parameter which is the URL and returns a promise, hence we can use "then" which will return as a raw JSON first, and then once that raw JSON retrieve is successful, 
- we then retrieve the icon 

> 
this.data.icon_url

- and the value(which is the quote here)

> 
this.data.value
 

and display it into the respective DOMS using their HTML id. 

If at all there is an error, then the promise will return the console.log inside the catch statement.
```` javascript
const generateQuote = function() {
   let url ="https://api.chucknorris.io/jokes/random";

    fetch(url)
    .then(function(response) {
        return response.json(); 
    }) // Getting the raw JSON data
    .then(function(data) {
  
        // Storing the quotes internally upon 
        // successful completion of request
        this.data = data; 
  
        // Displaying the quote When the Webpage loads
        console.log(this.data);
        document.getElementById("icon").src = this.data.icon_url;
        document.getElementById("quote").innerHTML = this.data.value;
}).catch(function() {
   console.log("error");
});

}
window.onload = function() {
    generateQuote();
}
```
Now, let's run the above piece of code and you should be seeing different quotes every single time you refresh your index.html. When you refresh the page, generateQuote a function inside the window.load gets executed, trying to fetch the new quote every refresh. 

### 4. Generate quote on button click
This can easily be done by adding a click event listener, which calls the generateQuote function onclick.

```` javascript
window.onload = function() {
    generateQuote();
    document.getElementById("generate").addEventListener('click', generateQuote);
}
```
### 5. Let's generate quotes based on the category selected.
To retrieve random quotes the API URL to be used is below

> 
GET https://api.chucknorris.io/jokes/random?category={category}

In this URL, {category} will be the value chosen from the dropdown .e

eg: https://api.chucknorris.io/jokes/random?category=movie

So in order to retrieve the results based on category is going to be done in just a few steps

1. Retrieve the chosen category value from the dropdown
> 
let category =  document.getElementById("category").value;

2. Pass the value of the category to the URL. The URL to use if you see below is decided based on an if/else condition. On the initial page load or if the user decides to view quotes from all the categories then we use the URL from the else condition, if the category chosen is something other than the option "all" eg. movie or sports then we use the URL inside the "if" condition.

```` javascript
 let url;
   let category =  document.getElementById("category").value;

   if(category !== "all") {
     url ="https://api.chucknorris.io/jokes/random?category=" + category;
   } else {
        url ="https://api.chucknorris.io/jokes/random";
   }
```

#### Final JavaScript

```` javascript
const generateQuote = function() {
   let url;
   let category =  document.getElementById("category").value;

   if(category !== "all") {
     url ="https://api.chucknorris.io/jokes/random?category=" + category;
   } else {
        url ="https://api.chucknorris.io/jokes/random";
   }

    fetch(url)
    .then(function(response) {
        return response.json(); 
    }) // Getting the raw JSON data
    .then(function(data) {
  
        // Storing the quotes internally upon 
        // successful completion of request
        this.data = data; 
  
        // Displaying the quote When the Webpage loads
        console.log(this.data);
        document.getElementById("icon").src = this.data.icon_url;
        document.getElementById("quote").innerHTML = this.data.value;
}).catch(function() {
   console.log("error");
});

}
window.onload = function() {
    generateQuote();
    document.getElementById("generate").addEventListener('click', generateQuote);
}
```
### Output - Working Demo
{% codepen https://codepen.io/kpattalam/pen/qBjjqJd %}

### References
-  [Function declaration vs Function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions) 
-  [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) 
- [Fetch Method] (https://developer.mozilla.org/en-US/docs/Web/API/fetch)


Follow me on  [Twitter](https://twitter.com/KritikaPattalam)  | [LinkedIn](https://www.linkedin.com/in/kritika-p-296739155/) for more web development related tips and posts. Feedbacks and suggestions are welcome.