How To Read and Use A RESTful Web API With JavaScript: A Studio Ghibli Example
Tags: javascript, api, webdev, beginners
Published: 2021-08-14 11:19:18

###What is A Web API?
An [API](https://en.wikipedia.org/wiki/API) - Application Programming Interface - is simply a way for other people to use apps you make without actually having access as you do. For example, if you developed an app that could immediately tell where anyone in the world is. You probably wouldn't want people to know how it works, but you'd still want to be able to allow them to use it, say for a fee. The set of instructions and codes given out so people can access your app, that is an API.
A Web API is simply an API setup to work over the web.

###What is A RESTful Web API?
Simply put, A RESTful Web API follows [RESTful Web standards](https://en.wikipedia.org/wiki/Representational_state_transfer). These are meant to make information sharing across the web a uniform activity. Some of the RESTful standards are:
* A client-server architecture that is made up of clients, servers, and resources, with requests managed through HTTP.
* Stateless client-server communication, meaning no client information is stored between GET requests, and each request is separate and unconnected.
You can read the rest here at [Redhat](https://www.redhat.com/en/topics/api/what-is-a-rest-api). But we are going to focus on these for now.

###The Studio Ghibli Web API
The [Studio Ghibli Web API](https://ghibliapi.herokuapp.com/) contains a database of characters (species), places, and vehicles for all films produced by Studio Ghibli. Through its endpoints - links where you access the API functionality - you can get data from the API in stringified [JSON](https://www.json.org/json-en.html) format. The huge advantage of this format is, you can [parse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) the data and manipulate it with code. 

##HTML Code##
```HTML
    <div class="titlebox">
        <h1>日本語タイトル</h1> 
        <select name="movietit" id="movietit" class="movietit">
            <option value="load">Loading ...</option>
            <option value="movie1">I am a Movie Title...</option>
        </select>
    </div>

    <div class="detailscontainer">
        <div class="descriptioncontainer" id="deets"></div>
    </div>
```

##CSS Code##
```CSS
html {
    font-family: "Roboto Condensed" !important;
}

.titlebox{
    padding-top: 18px;
    padding-bottom: 28px;
    box-sizing: border-box;
    height: 120px;
    max-width: 669px;
    width: 55%;
    min-width: 128px;
    background-color: gray;
    margin: 0 auto;
    margin-top: 24px;

    display: flex;
    flex-flow: column;
    align-items: center;
    justify-content: space-evenly;
}

.titlebox h1 {
    font-size: 18px;
    letter-spacing: 1.69px;
    color: white;
    font-family: "Kiwi Maru" !important;
    font-weight: 400 !important;
    margin-block-start: 0px !important;
}

.titlebox select {
    cursor: pointer;
    font: 400 14px "Roboto Condensed";
    letter-spacing: 1.69px;
    width: 85%;
    height: 36px;
}


.detailscontainer{
    padding-top: 18px;
    padding-bottom: 28px;
    box-sizing: border-box;
    height: 469px;
    max-width: 669px;
    width: 55%;
    min-width: 128px;
    background-color: gray;
    margin: 0 auto;
    margin-top: 24px;

    overflow-y: scroll;
    overflow-x: hidden;

}

.descriptioncontainer{
    min-height: 669px;
    background-color: transparent !important;
    color:  white !important;
    height: auto;
    width: 96%;
    margin: 0 auto;

    display: flex;
    flex-flow: column;
    align-items: flex-start;
    justify-content: space-evenly;

    position: relative;
}

.descriptioncontainer .items{
        width: 100%;
        font-size: 12px;
        min-height: 36px;
        letter-spacing: 1.69px;
}
```
##JavaScript Code - Client Side##
```Javascript
const localVar = {}
const detailsContainer = document.getElementById("deets");

window.onload = () => {
    fetchInfoWithFilter().then((ghibliApiObject)=>{
        //console.log(ghibliApiObject);
        localVar["cloudObj"] = ghibliApiObject;
        readStudioGhibliObject(ghibliApiObject);
    });
   
}




async function fetchInfoWithFilter () {

    var myRequest = new Request("https://ghibliapi.herokuapp.com/films?limit=250");
           
    const returnVal = await fetch(myRequest, {
      method: 'GET', 
      mode: 'cors', 
      cache: 'default',
      credentials: 'omit', 
      redirect: 'follow', 
      referrerPolicy: 'no-referrer'
    })
          .then(function(response) {
            if (!response.ok) {
              
              throw new Error("HTTP error, status = " + response.status);
              
            }
            
            return response.text();
          })
          .then(function(myBlob) {
            
            var cloudObject = JSON.parse(myBlob);
            
          
            return cloudObject;
            
          })
          .catch(function(error) {
            var p = document.createElement('p');
            p.appendChild(
              document.createTextNode('Error: ' + error.message)
            );
            document.querySelectorAll(".descriptioncontainer")[0].innerHTML = "";
            document.querySelectorAll(".descriptioncontainer")[0].appendChild(p);
          });
          return returnVal; 
  };


  function readStudioGhibliObject(ghibliApiObject) {
      const ghibliFilms = Object.entries(ghibliApiObject)
      const objectSize =  ghibliFilms.length;
      const itemsContainer = document.getElementById("movietit");
      itemsContainer.innerHTML = "";

     // console.log(ghibliFilms);
      //console.log(objectSize);

      for(i=0;i<objectSize;i++){
          let optionEle = document.createElement("option");
          optionEle.value = ghibliFilms[i][1].title;
          optionEle.innerText = ghibliFilms[i][1].title;
          itemsContainer.appendChild(optionEle);
      }

          upDateDescription("first");

      itemsContainer.addEventListener("input",()=>{
          upDateDescription("update");
      })


  };


  function upDateDescription(context) {
      detailsContainer.innerHTML="";
      if(context==="first"){
          let myKey = document.createElement("p");
          myKey.className = "items";
          let objectEntries =  Object.entries(localVar.cloudObj[0]);
          let objectKeys = Object.keys(localVar.cloudObj[0]);
          document.querySelectorAll("h1")[0].innerHTML = localVar.cloudObj[0].original_title;
          

          for(i=0;i<objectEntries.length;i++){
              let copyKey = myKey.cloneNode(true);
              copyKey.innerHTML = objectKeys[i].toUpperCase()+" : "+objectEntries[i][1];
              detailsContainer.appendChild(copyKey);
          }
      }else{
          let thisFilmObject = searchForFilm(document.getElementById("movietit").value);
          let myKey = document.createElement("p");
          myKey.className = "items";
          let objectEntries =  Object.entries(thisFilmObject);
          let objectKeys = Object.keys(thisFilmObject);
          document.querySelectorAll("h1")[0].innerHTML = thisFilmObject.original_title;
          

          for(i=0;i<objectEntries.length;i++){
              let copyKey = myKey.cloneNode(true);
              copyKey.innerHTML = objectKeys[i].toUpperCase()+" : "+objectEntries[i][1];
              detailsContainer.appendChild(copyKey);
          }
          
      }

  }


  function searchForFilm(searchQuery){
      let obj = {"Not":"Found"};

      for(i=0;i<localVar.cloudObj.length;i++){
          if(searchQuery===localVar.cloudObj[i].title){
              obj = localVar.cloudObj[i];
          }
      }

      return obj;
  };
```

##How Does It Work?
You can preview the setup [here](https://ismailisimba.github.io/studioghibli/index).
In our HTML, we have two containers, one for the film title in Japanese and the dropdown you can pick names from to view details. And the other is where we'll display film details. 

Next, we have to find out how the Studio Ghibli API works. You can view full documentation [here](https://ghibliapi.herokuapp.com/) but in summary:
* There are five main endpoints - access links - one each for films, people, locations, species, and vehicles.
* Through the endpoints, you can search things by id, set response limits - how big the JSON you get should be - and more. But for our purposes, we are simply accessing the film endpoint and setting a limit of 250 so we can get all films - they have 21 films in the database.

In our JavaScript, we have one important constant called localVar. We create this as a global variable so later we can update it with data from the Studio Ghibli JSON we'll receive from the endpoint. The rest of the functionality is spread out over the functions as follows:
* **window.onload** delays our JavaScript from running until all HTML files and CSS files have been loaded, this is especially important as we have to provide support for Japanese characters via special fonts.
* **fetchInfoWithFilter** is based on JavaScript's fetch. It allows us to send and receive HTTP requests, the primary method of communications for Web APIS.
* **readStudioGhibliObject** fills our dropdown with the names of all the films and it adds an input event listener to the dropdown so every time you change the movie name, the details will be updated.
* **updateDescription** is run in two contexts. First, when the data is received for the first time. It'll set the first entry of data as the default film on our dropdown, and it'll update the description. Secondly, every time you change the name in the dropdown, it'll run to update the description and the title of the film in Japanese.
Enjoy playing around!

{% github ismailisimba/studioghibli no-readme %}

Photo credit: [BrickinNick](https://visualhunt.co/a7/d4a24280)on [Visualhunt.com](https://visualhunt.com/re9/a5768a54)