Thursday, November 2, 2017

Simple Character Viewer Tutorial: writing HTML tables with JavaScript

NOTE: I've been having trouble getting my programming posts together, which should hopefully be fixed now.  I apologize for the lack of code updates over the last few weeks, and things will be more consistent from now on.

    I've found a lot of great sources of information about programming since I started teaching myself a few months ago.  My first idea for the "Thursday Tutorials" section of this blog was to put links to some of that information so it can help others.  But I did have another dream, which I want to realize today: writing my own tutorials.  Now I need to stress again that I am not an expert coder, as mentioned I only started learning this stuff a few months ago - but I have discovered over the years that the best way for me to learn something is to try and teach it to others.  So this is going to be the first post in a series aimed at learning how to do something in HTML/ CSS/ JavaScript.  I have been discussing my code in the Friday Frustrations series (currently working on my project called "Bookworm"), but that series is meant to produce a working application.  This series is meant to look at one specific topic and discuss how to do it; what I'm going to make is not anything really useful (at least not to start, who knows what'll happen as we add features to it?).  Which begs the question: what are we going to make?
    One handy thing to be able to do is to write data to a table.  So here's a screenshot of an HTML table that has some basic character information:




    Instead of hand-coding that table, wouldn't it be nice if we could make a blank table and then write each row dynamically using JavaScript?  It sure would!  So how do we do that?  Well, Grasshopper, let me show you...

Creating The Base Table
    First of all we need the basic table layout, with the header and stuff.  I'm going to add some CSS to make things look pretty.  This is the final blank table...


And here's the HTML code...


And the CSS code...


    That gets us the basic table, now we just need to be able to populate it.
   

Creating the Character Object
    So we have 10 table cells that we need to display on each row.  I'm going to start by doing this the easy way.  The easiest way is to make each cell a string.  So for an attribute, like the "16 (+3)" in the example I'm just going to store that same string in my JavaScript object.  Now, I'm doing that because I want to show you how to write data to a table, and that's the simplest way to do it.  But, in reality that would not be a very useful object to actually write code for in something more interactive.  The main attribute value, "16," and the modifier, "(+3)," should be stored as separate bits of data so they could be read/ interacted with individually.  And we'll see about writing something that will be more useful to program and read down the road.  For now let's start easy.
    That dealt with, basically we just need an object that has 10 values, the string for each cell.  That's a pretty easy object to create...




I'm going to hand-code a few of these to start with, then we'll look at how to let the user create their own...



Writing the object to the table
    Objects in hand, and basic table set up, let's get to the main event and actually write those objects to the table.  I'm going to start by doing this in pure JavaScript (I'll add how to do this with jQuery in a bit).  What we're going to do is create a new table row, add each cell from the character object, and then append that to the table.
    Let's look at the ugly way to do this.
    What we need to do is comprised of several parts.  First, we need to create a "document fragment" - some HTML code that isn't attached to anything.  Our fragment starts with a <tr> to make a new row, then we make a new <td> cell and fill it with the right object property.  We need to add the object's string with a method called "innerHTML" - that's because we're adding <br> HTML tags to the strings for formatting, if we add them as plain text the browser will just display "<br>" instead of actually making a new line.  Let me show you what I mean...


    So, with that in mind, let's look at that ugly code.  Basically, the ugly way is the longest way possible - in this case that's hand-coding each cell.  Here's a screenshot of the code...


And what it looks like...



    As you can see this does work, it adds the data and formats it properly, but it's ugly because we have to write a lot of repetative code for each step.  Instead of writing out each object property by hand, why don't we see if we can use a loop to simplify the process?  Remember, a good programmer is a lazy programmer :)  That said, we can look at our ugly code and see exactly what steps we need to repeat:

//write the object to a document fragment
var tblRow = document.createElement('tr');
   
//create and append each property
var tblName = document.createElement('td');
tblName.innerHTML = CharacterObj.name;
tblRow.appendChild(tblName);
   
var tblStr = document.createElement('td');
tblStr.innerHTML = CharacterObj.str;
tblRow.appendChild(tblStr);
   
var tblDex = document.createElement('td');
tblDex.innerHTML = CharacterObj.dex;
tblRow.appendChild(tblDex);
   
//append the fragment to the table
var domTarget = document.getElementById('tblCharDisplay');
domTarget.appendChild (tblRow);

    The beginning we only need to do once, creating the <tr> for the new row our character will take up.  I'm only going to use one row for each character, though I don't have to.  The name cell has 3 lines, and so do the weapon and armor cells - so I could have each character split across 3 rows.  I just don't think that would be very useful, it would mean even more code to make the extra rows and several of those cells would be empty - I think using the <br> tags is a more convenient way to get the formatting I want.
    Also the ending, appending the fragment to the main table, is something we only need to do once.
    The repeating code that we need a loop to handle is in the middle, creating the individual <td> cells for each of the 10 object properties.  That code is make up of 3 parts, first we create the new <td> cell, which is empty.  Then we fill the cell using innerHTML with the object's property string.  Last we append the cell to the row.  Easy.  So let's look at the loop that's going to handle this for us...

//create and append each property
let prop;
for (prop in CharacterObj) {
    var tblCell = document.createElement('td');
    tblCell.innerHTML = CharacterObj[prop];
    tblRow.appendChild(tblCell);
};

    This is pretty simple.  We made a variable to hold the current property.  Then we use a for-loop to iterate over each property in the object, creating a cell, populating it and adding it to the row.  It looks like this...



    And there you go, we've written some data from a JavaScript object to an HTML table.  Good job us!  Yeah, yeah, I know it's not really that big of a deal, but you have to acknowledge every accomplishment, even the little ones.
    Since this isn't a very impressive app, there is a lot of room for improvement.  Which we'll do next week :)  If you want to play with the code for this yourself, here's a link to it on my Google Drive.


No comments:

Post a Comment