Viewing Steem Blockchain Data in a Web Browser, Part 12: Splitting the HTML file into multiple files by numberjocky

View this thread on steempeak.com
· @numberjocky ·
$49.58
Viewing Steem Blockchain Data in a Web Browser, Part 12: Splitting the HTML file into multiple files
This is Part 12 of a series of posts describing how to use the [Steem Javascript API](https://github.com/steemit/steem-js) to view data from the Steem blockchain in a web browser. The previous 11 posts were:

* [Part 1:](https://steemit.com/steem-js/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-1-very-basic-html) Text editors and minimal HTML
* [Part 2:](https://steemit.com/html/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-2-very-basic-html-utf-8-meta-tag-and-inline-css) Metadata, Unicode, and inline CSS 
* [Part 3:](https://steemit.com/html/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-3-very-basic-html-meta-tags-nav-and-footer-bars-divs-and-entities) Metadata, nav and footer bars, divs, and HTML entities
* [Part 4:](https://steemit.com/html/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-4-basic-html-forms-scripts-and-the-developer-s-console) Forms, scripts, and the developer console
* [Part 5:](https://steemit.com/html/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-5-input-text-into-a-form-and-use-html-id-attributes-to-access-and-modify) Using HTML id attributes to modify HTML elements using Javascript
* [Part 6:](https://steemit.com/javascript/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-6-using-the-steem-api-cdn-and-the-getaccounts-function-and-examining-the) Using the Steem API CDN and the getAccounts() function, and examining the account data model
* [Part 7:](https://steemit.com/html/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-7-html-tables-javascript-for-in-loop-css-in-the-html-style-element) HTML tables, javascript for/in loop, CSS in the HTML style element
* [Part 8:](https://steemit.com/javascript/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-8-html-css-and-javascript-comments-and-organizing-javascripting-using) HTML, CSS, and Javascript comments; Javascript functions and MVC
* [Part 9:](https://steemit.com/javascript/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-9-compute-the-voting-power-and-reputation-score-of-a-user-javascript-const) Compute Voting Power and Reputation Score, Javascript "const" and "let" with block scope and loop scope
* [Part 10:](https://steemit.com/steem-js/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-10-calculating-the-steem-power-and-javascript-asynchronous-vs-synchronous) Calculating the Steem Power and Javascript asynchronous vs. synchronous execution
* [Part 11:](https://steemit.com/steem-js/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-11-javascript-switch-statement-and-computing-owned-delegated-and-received) Javascript "switch" statement and computing owned, delegated, and received Steem Power

The previous post described a function that computes different types of Steem Power using a Javascript "switch" statement.  The HTML document shown in that post is a bit unwieldy as is the code in the callback to the Steem Javascript API getAccounts() function.  In this post, I will first clean up the code in the callback by writing a new function that generates the output table Object which is called "dataToTable{}" in the previous post and then we will break out some of the code into other files in a directory structure and link to those files in the HTML document.

### Write a function that assembles the table data

Because our code in the steem.api.getAccounts() callback in the [previous post](https://steemit.com/steem-js/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-11-javascript-switch-statement-and-computing-owned-delegated-and-received) is not structured properly, let's write a new function to fill the "dataToTable{}" Object that is passed to the function that writes the table's HTML markup ("generateTable()").  We will take all the instructions for generating the table Object out of the getAccounts() callback and put them in their own function.  The function looks like this:
```
function generateTableData(userAccountData,steemPerVests){
        var userData = userAccountData;
        var dataToTable = {
          User_Name:userData.name,
          STEEM_Balance: userData.balance,
          SBD_Balance: userData.sbd_balance,
          Voting_Power: 0,
          Reputation_Score: 0,
          Reputation_Score_Formatter: 0,
          Steem_Power: 99999,
          Steem_Power_Delegated: 99999,
          Steem_Power_Received: 99999,
          Steem_Power_Effective: 99999
        };
        dataToTable.Steem_Power = computeSteemPower(userAccountData,steemPerVests,'vested').toFixed(3);
        dataToTable.Steem_Power_Delegated = computeSteemPower(userAccountData,steemPerVests,'delegated').toFixed(3);
        dataToTable.Steem_Power_Received = computeSteemPower(userAccountData,steemPerVests,'received').toFixed(3);
        dataToTable.Steem_Power_Effective = computeSteemPower(userAccountData,steemPerVests,'effective').toFixed(3);
        dataToTable.Voting_Power = computeVotingPower(userData);
        dataToTable.Reputation_Score_Formatter = steem.formatter.reputation(userData.reputation);
        dataToTable.Reputation_Score = computeReputationScore(userData);
        return dataToTable;
 }
```
"generateTableData()" takes the "userAccountData{}" Object and the "steemPerVests" value as parameters and returns an Object containing the keys and values of the items to put in the HTML table.  First we declare the "dataToTable{}" Object with values from the userAccountData and specify keys and placeholders for values that need to be calculated.  Then we calculate the values that need to be calculated using other functions that we have written like "computeSteemPower()",  "computeVotingPower()", and "computeReputationScore()".  Then "generateTableData()" returns the "dataToTable{}" Object.  Notice that generateTableData() uses the javascript [Number.prototype.toFixed() method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) to format the SP.

Our "showUserData()" function now looks like this:
```
function showUserData() {
        getElementReferences(['nameForm','dataView']);
        getUserInput(htmlElements.nameForm.elements);
        steem.api.getDynamicGlobalProperties(function(err,result){
            computeSPV(result);
            steem.api.getAccounts([userInputs.sUser], function(err,result){
              var userData = result[0];
              var dataToTable = generateTableData(userData,computedValues.steemPerVests);
              var theText = generateTable('Metric', 'Value',dataToTable);
              htmlElements.dataView.innerHTML = theText;
            });
        });
 }
```
This is much better than [before](https://steemit.com/steem-js/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-11-javascript-switch-statement-and-computing-owned-delegated-and-received).

### Splitting the HTML file into multiple files
The HTML file has gotten quite long so we are now going to rearrange the code by breaking it into several files in a directory structure.  We will make a new file folder named after the project.  I call my file folder “steemAPIDemo”.  Inside of that folder, will be an HTML file called “index.html”.  This is the main html file that will be loaded into the browser.  Then I make two folders.  One is called “scripts” and the other is called “stylesheets”.  I will make three files in the “scripts” folder called “controlFuncs.js”, “modelFuncs.js”, and “viewFuncs.js” and one file in the “stylesheets” folder called “steemAPIDemo.css”.  The files in the “scripts” folder will contain javascript functions and the file in the stylesheets folder will contain css styles for the html document.  The file directory structure looks like this:

<div class = "pull-left">https://cdn.steemitimages.com/DQmdxU2vjdx4Lzek4qLM1yXtWzPq7Q1ME1B1EDE52EerU2g/Screen%20Shot%202018-10-12%20at%2012.53.33%20PM.png</div><div class = "pull-right"> https://cdn.steemitimages.com/DQmPjNCjuxxyL5YTePDcQ2VV7KAsKcTsGgdwYC3sKkA8eiD/Screen%20Shot%202018-10-12%20at%2012.53.52%20PM.png</div>
<div>-</div><br>

##### Javascript files
The names of the javascript files follow the MVC framework discussed in [part 8 of this series](https://steemit.com/javascript/@numberjocky/viewing-steem-blockchain-data-in-a-web-browser-part-8-html-css-and-javascript-comments-and-organizing-javascripting-using) .  The functions and object declarations that will be put in the files are grouped according to whether they describe or fill a data model (modelFuncs.js), act on the HTML view (viewFuncs.js), or take some data and do a calculation on it (controlFuncs.js).  modelFuncs.js will contain the "computedValues{}" Object declaration and the "generateTableData()" function.  viewFuncs.js will contain the "htmlElements{}" and "userInputs{}" Object declarations and the "generateTable()", "getElementReferences()", and "getUserInput()" functions.  controlFuncs.js contains the "computeVotingPower()", "computeReputationScore()", "amount()", "computeSteemPower()",  and "computeSPV()" functions.  The functions in controlFuncs.js all use data from one data model (e.g. userAccounts and/or dynamic global properties), compute a value, and pass the value to another data model (e.g. dataToTable).

##### <i>modelFuncs.js file</i>:
```
// modelFunc.js
  var computedValues = {vestsDelegated: 0,steemPerVests: 0.005};

  function generateTableData(userAccountData){
    var userData = userAccountData;
    var dataToTable = {
      User_Name:userData.name,
      STEEM_Balance: userData.balance,
      SBD_Balance: userData.sbd_balance,
      Voting_Power: 0,
      Reputation_Score: 0,
      Reputation_Score_Formatter: 0,
      Steem_Power: 99999,
      Steem_Power_Delegated: 99999,
      Steem_Power_Received: 99999,
      Steem_Power_Effective: 99999
    };
    dataToTable.Steem_Power = computeSteemPower(userAccountData,computedValues.steemPerVests,'vested').toFixed(3);
    dataToTable.Steem_Power_Delegated = computeSteemPower(userAccountData,computedValues.steemPerVests,'delegated').toFixed(3);
    dataToTable.Steem_Power_Received = computeSteemPower(userAccountData,computedValues.steemPerVests,'received').toFixed(3);
    dataToTable.Steem_Power_Effective = computeSteemPower(userAccountData,computedValues.steemPerVests, 'effective').toFixed(3);
    dataToTable.Voting_Power = computeVotingPower(userData);
    dataToTable.Reputation_Score_Formatter = steem.formatter.reputation(userData.reputation);
    dataToTable.Reputation_Score = computeReputationScore(userData);
    return dataToTable;
}
```
##### <i>viewFuncs.js file</i>:
```
//viewFuncs.js
  var htmlElements = {};
  var userInputs = {};
  function generateTable(header1,header2,objectToTable){
    var tableText = "<table>";
    tableText = tableText+"<tr><th>"+header1+"</th><th>"+header2+"</th></tr>";
    for (var key in objectToTable){
        var keyStr = key.replace(/_/g," ");
        tableText = tableText+"<tr><td>"+keyStr+"</td><td>"+objectToTable[key]+"</td></tr>";
    }
    tableText = tableText+"</table>";
    return tableText;
  }
  function getElementReferences(elementNames){
    for (index in elementNames){
      var name = elementNames[index];
      htmlElements[name] = document.getElementById(name);
    }
  }
  function getUserInput(formElements){
    for( var i=0;i<formElements.length;i++){
      if(formElements[i].name !== ""){
        userInputs[formElements[i].name]=formElements[i].value;
      }
    }
}
```
##### <i>controlFuncs.js file </i>:
```
//controlFuncs.js
  function computeVotingPower(userAccountData){
    var lastVoteTime = userAccountData.last_vote_time;
    var votingPower = userAccountData.voting_power;
    var timeBeforeNow = (Date.now() - new Date(lastVoteTime+"Z"))/1000;
    var votingPowerNow = Math.min(votingPower/100+timeBeforeNow*20/86400,100).toFixed(2);
    return votingPowerNow+"%";
  }
  function computeReputationScore(userAccountData){
    var repScore = Math.sign(userAccountData.reputation)*userAccountData.reputation;
    repScore = Math.log10(repScore);
    if(isNaN(repScore)){repScore = 0};
    repScore = Math.max(repScore-9,0);
    repScore = Math.sign(repScore)*repScore;
    repScore = (repScore*9)+25;
    repScore = repScore.toFixed(2);
    return repScore;
  }
  function amount(labeledValue){
    return parseFloat(labeledValue.split(" ")[0]);
  }
  function computeSteemPower(userAccountData,steemPerVests,powerType){
    switch(powerType){
      case 'vested':
        return amount(userAccountData['vesting_shares'])*steemPerVests;
        break;
      case 'delegated':
        return amount(userAccountData['delegated_vesting_shares'])*steemPerVests;
        break;
      case 'received':
        return amount(userAccountData['received_vesting_shares'])*steemPerVests;
        break;
      case 'effective':
        return (amount(userAccountData['vesting_shares'])+
        amount(userAccountData['received_vesting_shares'])-
        amount(userAccountData['delegated_vesting_shares']))*steemPerVests;
        break;
      default:
        return 9999;
    }
  }
  function computeVestsDelegated(gvdRecords){
    for(var recNum in gvdRecords){
      var vestingShares = amount(gvdRecords[recNum]['vesting_shares']);
      computedValues.vestsDelegated = computedValues.vestsDelegated + vestingShares;
    }
  }
  function computeSPV(gdp){
    var tvfs = amount(gdp['total_vesting_fund_steem']);
    var tvs = amount(gdp['total_vesting_shares']);
    computedValues.steemPerVests = tvfs/tvs;
  }
```
##### CSS file
The .css file in the stylesheets directory will contain a copy and paste of the selectors and their instructions already in the \<style> tags in the \<head> of the HTML document.  

##### <i>steemAPIDemo.css file:</i>
```
/* steemAPIDemo.css */

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;
}
#formDiv {
  background-color: lightblue;
}
```

#### Modifying the HTML document to use external files
To use the javascript files in the HTML document, we replace their code (which has been copied and pasted into the files) with links in  \<script> tags in the HTML document like so:
```
    <script src="scripts/modelFuncs.js"></script>
    <script src="scripts/viewFuncs.js"></script>
    <script src="scripts/controlFuncs.js"></script>
```
The functions in the files will be loaded when the HTML document is loaded and are therefore available anywhere in the document but it is good practice to put them above the "showUserData()" function which depends on them.

To use the css file in the HTML document, we replace the \<style> tags in the \<head> section with a \<link> tag that links to the css file like so:
```
<link rel="stylesheet" type="text/css" href="stylesheets/steemAPIdemo.css">
```

The linking to the .css and .js files depends on the directory structure and won't work unless the <i>stylesheets</i> and <i>scripts</i> directories are in the folder with the HTML document.

Now, our entire HTML document looks like this:
```
<!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>
    <link rel="stylesheet" type="text/css" href="stylesheets/steemAPIdemo.css">
  </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="dataView">
      <br>
      <p></p>
      <br>
    </div>
    <br>
    <footer>
    </footer>
    <script src="scripts/modelFuncs.js"></script>
    <script src="scripts/viewFuncs.js"></script>
    <script src="scripts/controlFuncs.js"></script>
    <script>
      function showUserData() {
        getElementReferences(['nameForm','dataView']);
        getUserInput(htmlElements.nameForm.elements);
        steem.api.getDynamicGlobalProperties(function(err,result){
          computeSPV(result);
          steem.api.getAccounts([userInputs.sUser], function(err,result){
            var userData = result[0];
            var dataToTable = generateTableData(userData);
            var theText = generateTable('Metric', 'Value',dataToTable);
            htmlElements.dataView.innerHTML = theText;
          });
        });
      }
    </script>
  </body>
</html>
```
👍  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and 5 others
properties (23)
post_id64,134,845
authornumberjocky
permlinkviewing-steem-blockchain-data-in-a-web-browser-part-12-splitting-the-html-file-into-multiple-files
categorysteem-js
json_metadata{"links":["https:\/\/github.com\/steemit\/steem-js","https:\/\/steemit.com\/steem-js\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-1-very-basic-html","https:\/\/steemit.com\/html\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-2-very-basic-html-utf-8-meta-tag-and-inline-css","https:\/\/steemit.com\/html\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-3-very-basic-html-meta-tags-nav-and-footer-bars-divs-and-entities","https:\/\/steemit.com\/html\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-4-basic-html-forms-scripts-and-the-developer-s-console","https:\/\/steemit.com\/html\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-5-input-text-into-a-form-and-use-html-id-attributes-to-access-and-modify","https:\/\/steemit.com\/javascript\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-6-using-the-steem-api-cdn-and-the-getaccounts-function-and-examining-the","https:\/\/steemit.com\/html\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-7-html-tables-javascript-for-in-loop-css-in-the-html-style-element","https:\/\/steemit.com\/javascript\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-8-html-css-and-javascript-comments-and-organizing-javascripting-using","https:\/\/steemit.com\/javascript\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-9-compute-the-voting-power-and-reputation-score-of-a-user-javascript-const","https:\/\/steemit.com\/steem-js\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-10-calculating-the-steem-power-and-javascript-asynchronous-vs-synchronous","https:\/\/steemit.com\/steem-js\/@numberjocky\/viewing-steem-blockchain-data-in-a-web-browser-part-11-javascript-switch-statement-and-computing-owned-delegated-and-received","https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Number\/toFixed"],"format":"markdown","tags":["steem-js","programming","steemiteducation","link","html"],"app":"steemit\/0.1","image":["https:\/\/cdn.steemitimages.com\/DQmdxU2vjdx4Lzek4qLM1yXtWzPq7Q1ME1B1EDE52EerU2g\/Screen%20Shot%202018-10-12%20at%2012.53.33%20PM.png"]}
created2018-10-12 18:45:18
last_update2018-10-12 18:45:18
depth0
children1
net_rshares36,537,299,372,707
last_payout2018-10-19 18:45:18
cashout_time1969-12-31 23:59:59
total_payout_value37.276 SBD
curator_payout_value12.307 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length16,812
author_reputation2,524,772,331,601
root_title"Viewing Steem Blockchain Data in a Web Browser, Part 12: Splitting the HTML file into multiple files"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (69)
@postpromoter ·
re-numberjocky-viewing-steem-blockchain-data-in-a-web-browser-part-12-splitting-the-html-file-into-multiple-files-20181015t004651251z
You got a 3.43% upvote from @postpromoter courtesy of @numberjocky!

Want to promote your posts too? Check out the [Steem Bot Tracker website](https://steembottracker.com) for more info. If you would like to support the development of @postpromoter and the bot tracker please [vote for @yabapmatt for witness!](https://v2.steemconnect.com/sign/account-witness-vote?witness=yabapmatt&approve=1)
properties (22)
post_id64,261,213
authorpostpromoter
permlinkre-numberjocky-viewing-steem-blockchain-data-in-a-web-browser-part-12-splitting-the-html-file-into-multiple-files-20181015t004651251z
categorysteem-js
json_metadata{"app":"postpromoter\/2.1.1"}
created2018-10-15 00:46:51
last_update2018-10-15 00:46:51
depth1
children0
net_rshares0
last_payout2018-10-22 00:46:51
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length394
author_reputation21,053,937,692,175
root_title"Viewing Steem Blockchain Data in a Web Browser, Part 12: Splitting the HTML file into multiple files"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000