Viewing Steem Blockchain Data in a Web Browser. Part 7: HTML tables, javascript for/in loop, CSS in the HTML style element

in #html6 years ago

This is part 7 of a series of posts that describe how to use the Steem Javascript API to display data from the Steem blockchain on a webpage. The first 6 posts are:

  • Part 1: Text editors and minimal HTML
  • Part 2: Metadata, Unicode, and inline CSS
  • Part 3: Metadata, nav and footer bars, divs, and HTML entities
  • Part 4: Forms, scripts, and the developer console
  • Part 5: Using HTML id attributes to modify HTML elements using Javascript
  • Part 6: Using the Steem API CDN and the getAccounts() function, and examining the account data model

This post will describe how to dump a user’s account data into a table displayed in a web browser using a javascript for/in loop and how to put CSS styling instructions into a style element in the head section of the HTML document. The entire text of the resulting HTML document is near the end of this post.

Simple HTML tables

Table markup inside the body section of an HTML document looks like this:

<div id="tableExample" style="background-color: linen">
  <table>
    <tr>
          <th>Column 1</th><th>Column 2</th><th>Column 3</th><th>Column 4</th>
    </tr>
    <tr>
          <td>Row 1, Cell 1</td><td>Row 1, Cell 2</td><td>Row 1, Cell 3</td>
    </tr>
    <tr>
          <td>Row 2, Cell 1</td><td>Row 2, Cell 2</td>
    </tr>
    <tr>
          <td>Row 3, Cell 1</td><td>Row 3, Cell 2</td><td>Row 3, Cell 3</td><td>Row 3, Cell 4</td>
    </tr>
  </table>
</div>

The table is inside a div and the div has an id. There are "table" beginning and ending tags<table></table> and "table row" beginning and ending tags <tr></tr> and "table cell" beginning and ending tags <td></td> or <th></th>. "td" tags instantiate regular table cells while "th" tags instantiate table header cells. The cell tags are nested in the row tags which are nested in the table tags. When the table is loaded into the browser, the browser determines how many rows and columns the table has by determining the maximum number of rows and maximum number of columns. It then arranges the cells inside of a grid.

The table looks like the following image in a browser:
Screen Shot 2018-09-03 at 11.52.46 AM.png

HTML style element with CSS styling instructions

To put borders around the table cells, we will add a “style” element to the head section of the HTML document from Part 6 (the "tableExample" div is inserted in the body of that document after the div with id="formDiv"). The style element will contain CSS styling instructions for the entire document. Usually these instructions are so extensive that they are contained in a separate file but we will start by putting one instruction inside of <style></style> tags like so:

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="description" content="Show a Steemit User's Account Data">
    <title>Show User's Data</title>
    <script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
    <style>
      td,th {
        border: 1px solid black;
      }     
    </style>
</head>

This sets the styling for all td and th elements in the document. “td” and “th” are called element selectors. Instead of putting the styling in-line for each element, we put the styling instructions inside of curly brackets following the element selectors. Because there are nine table cells in the table example and we’d have to put styling instructions in each table cell tag if we used in-line styling, we save ourselves typing and messiness by using the style tag in the head section.

Now the table looks like this in the browser:

Screen Shot 2018-09-03 at 11.49.10 AM.png

We can put multiple styling instructions into the style tag and we will do so now by taking all the in-line styling in the document that we have modified slightly from the one in Part 6 and putting it in the head section. Inserting all the styling in the style tags looks like this:

<style>
      td,th {
        border: 1px solid black;
      } 
      footer,nav {
        border: 1px solid black;
      }
      table {
        width: 100%;
      }
      #dataView {
        background-color: lightsalmon;
        padding: 10px;
        margin: 5px;
      }
      #tableExample {
        background-color: linen;
        padding: 10px;
        margin: 5px;
      }
      #formDiv {
        background-color: lightblue;
        padding: 10px;
        margin: 5px;
      }
</style>

footer and nav both have borders, all the divs have padding, margins, and background colors, and all tables have a width spanning 100% of their parent element. Because the divs have different background colors, we give each div an id attribute and use the CSS #id selector (instead of the element selector) to refer to them. You may notice redundancies between the elements. Getting rid of redundancies makes the style element look like this:

<style>
      td,th,footer,nav {
        border: 1px solid black;
      } 
      table {
        width: 100%;
      }
      div {
        padding: 10px;
        margin: 5px;
        background-color: pink
      }
      #dataView {
        background-color: lightsalmon;
      }
      #tableExample {
        background-color: linen;
      }
      #formDiv {
        background-color: lightblue;
      } 
</style>

The padding and margin CSS attributes for the divs have been set to be the same for all divs using the div element selector. Notice that the background-color for all divs is set to "pink" using the div element selector but the background color for each div is set to a different color in the subsequent instructions that use id selectors. CSS instructions that come after previous instructions for the same element overwrite those previous instructions.

Dumping a user's account data into an HTML table

We will now put the user account data into an HTML table using the table, tr, th,and td tags and put this table inside of the "dataView" div. The table will have two columns corresponding to the keys of the account data and the values of those keys. One key-value pair will be displayed per row of the table.

To access all the keys in the table we will use a for/in loop in the showUserData() function (see Part 6) that is executed when a form is submitted. The javascript for/in loop extracts the keys of an Object and loops through them. It is written like this:

for(var key in Object){
  console.log(key);
}

This will display a list of the Object’s keys in the developer console (see Part 4 to learn about the developer console). We can use the keys to extract the values of each key in the account data object by calling getAccounts() like so:

steem.api.getAccounts(userName, function(err,result){
  var accountData = result[0];
  for(var key in accountData]{
    console.log(key,accountData[key]);
  }
});

This prints out two columns in the console. The first column contains the keys of the accountData and the second column contains the values corresponding to those keys.

Instead of printing to the console, we would like to put the accountData in a table by generating a marked-up string and putting it in the dataView div's innerHTML property by modifying our showUserData() function from the previous post in this series like so:

<script>
      function showUserData() {
        var inputForm = document.getElementById("nameForm");
        var uName = inputForm.elements["sUser"].value;
        var dataViewEl = document.getElementById("dataView");
        steem.api.getAccounts([uName],function(err,result){
          var accountData = result[0];
          var theText = "<table>";
          theText = theText+"<tr><th>keys</th><th>values</th></tr>"
          for (var key in accountData){
              theText = theText+"<tr><td>"+key+"</td><td>"+accountData[key]+"</td></tr>";
          }
          theText = theText+"</table>";
          dataViewEl.innerHTML = theText;
          console.log(Object.keys(result[0]));
        });
      }
</script>

Each key value pair is a row in a table. The key goes in the first cell of the row and the value goes in the second cell. Notice that we use the square brackets to access the values. We do it this way as opposed to using "accountData.key" because we don’t know the names of the keys in advance. We build up the table by concatenating the HTML markup for the rows as we loop through the keys. After the loop is finished, we put the closing table tag on the table and then we set the innerHTML of the dataView div to the text string.

The account data table is quite long, so we will allow its div to scroll by putting a height and overflow attribute in it's styling like so:

#dataView {
        background-color: lightsalmon;
        overflow: auto;
        height: 300px;
}

Here is the final HTML document:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <meta name="description" content="Show a Steemit User's Account Data">
    <title>Show User's Data</title>
    <script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
    <style>
      td,th,footer,nav {
        border: 1px solid black;
      }
      table {
        width: 100%;
      }
      div {
        padding: 10px;
        margin: 5px;
        background-color: pink;
      }
      #dataView {
        background-color: lightsalmon;
        overflow: auto;
        height: 200px;
      }
      #tableExample {
        background-color: linen;
      }
      #formDiv {
        background-color: lightblue;
      }
    </style>
  </head>
  <body>
    <nav>
    </nav>
    <br>
    <div id="formDiv">
      <br>
      <form action="#" onsubmit="showUserData();return false;" id="nameForm">
        Enter your steemit userName: <input type="text" name="sUser" id="userNid">
        <input type="submit" value="Submit">
      </form>
      <br>
    </div>
    <div id="tableExample">
      <table>
        <tr>
          <th>Column 1</th><th>Column 2</th><th>Column 3</th><th>Column 4</th>
        </tr>
        <tr>
          <td>Row 1, Cell 1</td><td>Row 1, Cell 2</td><td>Row 1, Cell 3</td>
        </tr>
        <tr>
          <td>Row 2, Cell 1</td><td>Row 2, Cell 2</td>
        </tr>
        <tr>
          <td>Row 3, Cell 1</td><td>Row 3, Cell 2</td><td>Row 3, Cell 3</td><td>Row 3, Cell 4</td>
        </tr>
      </table>
    </div>
    <div id="dataView">
      <br>
      <p></p>
      <br>
    </div>
    <br>
    <footer>
    </footer>
    <script>
      function showUserData() {
        var inputForm = document.getElementById("nameForm");
        var uName = inputForm.elements["sUser"].value;
        var dataViewEl = document.getElementById("dataView");
        steem.api.getAccounts([uName],function(err,result){
          var accountData = result[0];
          var theText = "<table>";
          theText = theText+"<tr><th>keys</th><th>values</th></tr>"
          for (var key in accountData){
              theText = theText+"<tr><td>"+key+"</td><td>"+accountData[key]+"</td></tr>";
          }
          theText = theText+"</table>";
          dataViewEl.innerHTML = theText;
          console.log(Object.keys(result[0]));
        });
      }
    </script>
  </body>
</html>

(The "console.log(Object.keys(accountData));" statement is another way of extracting the keys from an Object. If you don't understand any of the commands in the showUserData() function, read previous posts in this series.)

If you save this document using a text editor, load the file (with a .html suffix) into your web browser, enter a steemit user's name in the text field, and push the submit button, the result looks like this:

Screen Shot 2018-09-03 at 1.18.03 PM.png

Notice that the HTML table example is displayed in the browser. If you don't want to see it, delete its div. The dataView div is scrollable. If you want to see more of it, change its height in the style element in the head section of the HTML document.