The code below holds the info that is being generated into an HTML table.

Key things to know:

  • < table > creates a TABLE
  • < tr > creates a ROW
  • < th > makes the text a column HEADER
  • < tbody id = "results" > defines an element id, to be used within JavaScript
<!-- HTML table fragment for page -->
<table>
  <thead>
  <tr>
    <th>Joke</th>
    <th>HaHa</th>
    <th>Boohoo</th>
  </tr>
  </thead>
  <tbody id="result">
    <!-- javascript generated data -->
  </tbody>
</table>

Constant variables are declared here with keyword const

Key things to know:

  • The document object "result" represents table body in the HTML above.
  • If you want to access any element in an HTML page in JavaScript, you always start by accessing the document object. In this case, we are accessing "result" and defining a "resultContainer"
  • In the code, in following cells, document elements are created and organized for each Joke, each is added to the "resultContainer" as a row in the table body.
  • Accessing the api is done using the variables url and options, this is setup to fetch the Jokes from the backend
// prepare HTML defined "result" container for new output
const resultContainer = document.getElementById("result");

// keys for joke reactions
const HAHA = "haha";
const BOOHOO = "boohoo";

// prepare fetch urls
const url = "https://flask.nighthawkcodingsociety.com/api/jokes";
const like_url = url + "/like/";  // haha reaction
const jeer_url = url + "/jeer/";  // boohoo reaction

// prepare fetch GET options
const options = {
  method: 'GET', // *GET, POST, PUT, DELETE, etc.
  mode: 'cors', // no-cors, *cors, same-origin
  cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
  credentials: 'omit', // include, *same-origin, omit
  headers: {
    'Content-Type': 'application/json'
    // 'Content-Type': 'application/x-www-form-urlencoded',
  },
};

// prepare fetch PUT options, clones with JS Spread Operator (...)
const put_options = {...options, method: 'PUT'}; // clones and replaces method

The below code uses a function called fetch to gather the data from the backend.

Key things to understand:

  • The "url" "response" is checked in case the site is down and returns an error
  • On successful fetch, the code places each Joke in the HTML table body using a "for" loop and creating document elements from each "row" of the fetched "data".
  • The creation of each Haha and Boohoo "onclick" "button" is also done in the same loop.
  • Updates to backend are setup to occur with each onclick, each click calls the "reaction" function
// fetch the API
fetch(url, options)
  // response is a RESTful "promise" on any successful fetch
  .then(response => {
    // check for response errors
    if (response.status !== 200) {
        error('GET API response failure: ' + response.status);
        return;
    }
    // valid response will have JSON data
    response.json().then(data => {
        console.log(data);
        for (const row of data) {
          // make "tr element" for each "row of data"
          const tr = document.createElement("tr");
          
          // td for joke cell
          const joke = document.createElement("td");
            joke.innerHTML = row.id + ". " + row.joke;  // add fetched data to innerHTML

          // td for haha cell with onclick actions
          const haha = document.createElement("td");
            const haha_but = document.createElement('button');
            haha_but.id = HAHA+row.id   // establishes a HAHA JS id for cell
            haha_but.innerHTML = row.haha;  // add fetched "haha count" to innerHTML
            haha_but.onclick = function () {
              // onclick function call with "like parameters"
              reaction(HAHA, like_url+row.id, haha_but.id);  
            };
            haha.appendChild(haha_but);  // add "haha button" to haha cell

          // td for boohoo cell with onclick actions
          const boohoo = document.createElement("td");
            const boohoo_but = document.createElement('button');
            boohoo_but.id = BOOHOO+row.id  // establishes a BOOHOO JS id for cell
            boohoo_but.innerHTML = row.boohoo;  // add fetched "boohoo count" to innerHTML
            boohoo_but.onclick = function () {
              // onclick function call with "jeer parameters"
              reaction(BOOHOO, jeer_url+row.id, boohoo_but.id);  
            };
            boohoo.appendChild(boohoo_but);  // add "boohoo button" to boohoo cell
            
          // this builds ALL td's (cells) into tr (row) element
          tr.appendChild(joke);
          tr.appendChild(haha);
          tr.appendChild(boohoo);

          // this adds all the tr (row) work above to the HTML "result" container
          resultContainer.appendChild(tr);
        }
    })
})

// catch fetch errors (ie Nginx ACCESS to server blocked)
.catch(err => {
  error(err + " " + url);
});

The below code uses fetch to update backend data using "put_options". The purpose is to update Hahaa and Bohoo counters in backend.

Key things to understand:

  • The "url" "response" is checked to verify update occurred
  • The element id of button clicked is updated with the data returned from the API.
  • Note, the elemID is received as parameter. This data was setup when the button was created in former cell.
// Reaction function to likes or jeers user actions
function reaction(type, put_url, elemID) {

  // fetch the API
  fetch(put_url, put_options)
  // response is a RESTful "promise" on any successful fetch
  .then(response => {
    // check for response errors
    if (response.status !== 200) {
        error("PUT API response failure: " + response.status)
        return;  // api failure
    }
    // valid response will have JSON data
    response.json().then(data => {
        console.log(data);
        // Likes or Jeers updated/incremented
        if (type === HAHA) // like data element
          document.getElementById(elemID).innerHTML = data.haha;  // fetched haha data assigned to haha Document Object Model (DOM)
        else if (type === BOOHOO) // jeer data element
          document.getElementById(elemID).innerHTML = data.boohoo;  // fetched boohoo data assigned to boohoo Document Object Model (DOM)
        else
          error("unknown type: " + type);  // should never occur
    })
  })
  // catch fetch errors (ie Nginx ACCESS to server blocked)
  .catch(err => {
    error(err + " " + put_url);
  });
  
}
  
// Something went wrong with actions or responses
function error(err) {
  // log as Error in console
  console.error(err);
  // append error to resultContainer
  const tr = document.createElement("tr");
  const td = document.createElement("td");
  td.innerHTML = err;
  tr.appendChild(td);
  resultContainer.appendChild(tr);
}

Hacks

The code below relates to the rapidapi you worked with last week.

  • What are some similarities you see with the javascript for the jokes api?
  • In a blogpost, break up the code in cells like done above and try to describe what this code is doing.
<!-- HTML table fragment for page -->
<table>
  <thead>
  <tr>
    <th>Time</th>
    <th>All-time Cases</th>
    <th>Recorded Deaths</th>
    <th>Active Cases</th>
  </tr>
  </thead>
  <tbody>
    <td id="time"></td>
    <td id="total_cases"></td>
    <td id="total_deaths"></td>
    <td id="active_cases"></td>
  </tbody>
</table>

<table>
  <thead>
  <tr>
    <th>Country</th>
    <th>All-time Cases</th>
    <th>Recorded Deaths</th>
    <th>Active Cases</th>
  </tr>
  </thead>
  <tbody id="result">
    <!-- generated rows -->
  </tbody>
</table>

<!-- Script is layed out in a sequence (no function) and will execute when page is loaded -->
<script>
  // prepare HTML result container for new output
  const resultContainer = document.getElementById("result");

  // prepare fetch options
  const url = "https://flask.nighthawkcodingsociety.com/api/covid/";
  const headers = {
    method: 'GET', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'omit', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
  };

  // fetch the API
  fetch(url, headers)
    // response is a RESTful "promise" on any successful fetch
    .then(response => {
      // check for response errors
      if (response.status !== 200) {
          const errorMsg = 'Database response error: ' + response.status;
          console.log(errorMsg);
          const tr = document.createElement("tr");
          const td = document.createElement("td");
          td.innerHTML = errorMsg;
          tr.appendChild(td);
          resultContainer.appendChild(tr);
          return;
      }
      // valid response will have json data
      response.json().then(data => {
          console.log(data);
          console.log(data.world_total)

          // World Data
          document.getElementById("time").innerHTML = data.world_total.statistic_taken_at;
          document.getElementById("total_cases").innerHTML = data.world_total.total_cases;
          document.getElementById("total_deaths").innerHTML = data.world_total.total_deaths;
          document.getElementById("active_cases").innerHTML = data.world_total.active_cases;

          // Country data
          for (const row of data.countries_stat) {
            console.log(row);

            // tr for each row
            const tr = document.createElement("tr");
            // td for each column
            const name = document.createElement("td");
            const cases = document.createElement("td");
            const deaths = document.createElement("td");
            const active = document.createElement("td");

            // data is specific to the API
            name.innerHTML = row.country_name;
            cases.innerHTML = row.cases; 
            deaths.innerHTML = row.deaths; 
            active.innerHTML = row.active_cases; 

            // this builds td's into tr
            tr.appendChild(name);
            tr.appendChild(cases);
            tr.appendChild(deaths);
            tr.appendChild(active);

            // add HTML to container
            resultContainer.appendChild(tr);
          }
      })
  })
  // catch fetch errors (ie ACCESS to server blocked)
  .catch(err => {
    console.error(err);
    const tr = document.createElement("tr");
    const td = document.createElement("td");
    td.innerHTML = err;
    tr.appendChild(td);
    resultContainer.appendChild(tr);
  });
</script>
  Input In [4]
    <!-- HTML table fragment for page -->
    ^
SyntaxError: invalid syntax

This code is about HTML and it builds a table and you need the part in the beginning because it is put into a JavaScript Cell, but needs to be HTML in order to properly build the table and really show what exactly it needs to do in order to make the table. This really just sets up the code for the table so later the segments can format the data and help it ot understand what exactly is going on.

< table > makes a table, < tr > makes a row, < th > makes a column header, and < thead > is tag for the group header, and < tbody > is a tag used later to define an element id

<!-- HTML table fragment for page -->
<table>
  <thead>
  <tr>
    <th>Time</th>
    <th>All-time Cases</th>
    <th>Recorded Deaths</th>
    <th>Active Cases</th>
  </tr>
  </thead>
  <tbody>
    <td id="time"></td>
    <td id="total_cases"></td>
    <td id="total_deaths"></td>
    <td id="active_cases"></td>
  </tbody>
</table>

<table>
  <thead>
  <tr>
    <th>Country</th>
    <th>All-time Cases</th>
    <th>Recorded Deaths</th>
    <th>Active Cases</th>
  </tr>
  </thead>
  <tbody id="result">
    <!-- generated rows -->
  </tbody>
</table>

This part of the code basically just preparing the code and the table before the code actually fetches the API and outputs it as well as formats it. It is basically just a sequence. I do not know exactly what each line of code does, but I thin this whole cell is just making the headers for the table so later segments of code can reference it and use it to make a table.

<!-- Script is layed out in a sequence (no function) and will execute when page is loaded -->
<script>
  // prepare HTML result container for new output
  const resultContainer = document.getElementById("result");

  // prepare fetch options
  const url = "https://flask.nighthawkcodingsociety.com/api/covid/";
  const headers = {
    method: 'GET', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, *cors, same-origin
    cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'omit', // include, *same-origin, omit
    headers: {
      'Content-Type': 'application/json'
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
  };

I think this is the base code and the main part of the program that really shows what is going on and really explains what and how the API is being formatted. First it will fetch the API, and then it will organize it into headers. Before proceeding it checks for any errors and if there are no errors then it will probably run the top part with the if statement. After that it will take the data from the API and start the organization process. This also puts data and data.world_total in the console log. It also takes each specific part of the API and chooses how to format it. It grabs specific parts of the data and this helps the code to realize where specifically the code goes in the table and what exactly to do with it. Also for each time the code makes a row depending on the data, it sends the message row to the console. The last part kind of appends some child nodes so that way it follows a specific data system and puts the information of each cell along the rows.

  // fetch the API
  fetch(url, headers)
    // response is a RESTful "promise" on any successful fetch
    .then(response => {
      // check for response errors
      if (response.status !== 200) {
          const errorMsg = 'Database response error: ' + response.status;
          console.log(errorMsg);
          const tr = document.createElement("tr");
          const td = document.createElement("td");
          td.innerHTML = errorMsg;
          tr.appendChild(td);
          resultContainer.appendChild(tr);
          return;
      }
      // valid response will have json data
      response.json().then(data => {
          console.log(data);
          console.log(data.world_total)

          // World Data
          document.getElementById("time").innerHTML = data.world_total.statistic_taken_at;
          document.getElementById("total_cases").innerHTML = data.world_total.total_cases;
          document.getElementById("total_deaths").innerHTML = data.world_total.total_deaths;
          document.getElementById("active_cases").innerHTML = data.world_total.active_cases;

          // Country data
          for (const row of data.countries_stat) {
            console.log(row);

            // tr for each row
            const tr = document.createElement("tr");
            // td for each column
            const name = document.createElement("td");
            const cases = document.createElement("td");
            const deaths = document.createElement("td");
            const active = document.createElement("td");

            // data is specific to the API
            name.innerHTML = row.country_name;
            cases.innerHTML = row.cases; 
            deaths.innerHTML = row.deaths; 
            active.innerHTML = row.active_cases; 

            // this builds td's into tr
            tr.appendChild(name);
            tr.appendChild(cases);
            tr.appendChild(deaths);
            tr.appendChild(active);

            // add HTML to container
            resultContainer.appendChild(tr);
          }
      })
  })

I think this code just tries to refetch the API if something does not work. I am not completely sure, but my best guess is that it just uses that and then creates elements based on what it has in the API. It will make a constant number of rows and cells to format the data into.

  // catch fetch errors (ie ACCESS to server blocked)
  .catch(err => {
    console.error(err);
    const tr = document.createElement("tr");
    const td = document.createElement("td");
    td.innerHTML = err;
    tr.appendChild(td);
    resultContainer.appendChild(tr);
  });
</script>KeyboardEvent