Using Loops to Write Out HTML Tables


Exercises

Introduction

Loops are useful for many things. They can be used to check each character in a string, count the occurrences of certain types of characters, and perform numerous calculations. In these exercises loops are used to write out HTML tables that contain information that depends on the row or column of the table. Later we'll use a similar system to draw a game board.

A Simple Table

HTML tables begin and end with the table tag: <TABLE></TABLE>. Within the table tags HTML tables are laid out one row at a time. Each row begins and ends with the table row tag: <TR></TR>. In turn each row may contain a number of table data cells that make up the columns of the table. These are created by <TD></TD> tags. Here is a simple example of a table with two rows. Each row in turn contains two table data cells.

HTML to create a simple table.

What the table will look like.

<table border="1" cellspacing="1" cellpadding="5">
  <tr>
    <td>row 0, column 0</td>
    <td>row 0, column 1</td>
    <td>row 0, column 2</td>
  </tr>
  <tr>
    <td>row 1, column 0</td>
    <td>row 1, column 1</td>
    <td>row 1, column 2</td>
  </tr>
  <tr>
    <td>row 2, column 0</td>
    <td>row 2, column 1</td>
    <td>row 2, column 2</td>
  </tr>
</table>
row 0, column 0 row 0, column 1 row 0, column 2
row 1, column 0 row 1, column 1 row 1, column 2
row 2, column 0 row 2, column 1 row 2, column 2

HTML tables may also contain table header tags (<TH></TH>) often just in the top row that contain headers as opposed to data. However, the table header tags work much like the table data cells in that they are placed within rows and help define the columns of the table.

Writing out the rows of a table using a loop

If you look at the HTML above you'll see that it is quite repetitive. In fact the only thing that seems to change from row to row is the row number inside the table data tags. If you wanted to write out this table using a loop you could write out a row at a time. So lets look at the HTML for a single row but replace the row number with the letter i to remind us it will change with each row.

   <tr>
     <td>row i, column 0</td>
     <td>row i, column 1</td>
     <td>row i, column 2</td>
   </tr>

Translating this to a series of document.write() statements is not too difficult. Assuming there is a variable i that holds the current row number lets start by converting everything into literal strings and the variable i:

   '<tr>'
     '<td>row ' + i + ', column 0</td>'
     '<td>row ' + i + ', column 1</td>'
     '<td>row ' + i + ', column 2</td>'
   '</tr>'

Then we can add the document.write() calls:

   document.write('<tr>')
   document.write('<td>row ' + i + ', column 0</td>')
   document.write('<td>row ' + i + ', column 1</td>')
   document.write('<td>row ' + i + ', column 2</td>')
   document.write('</tr>')

Here is a short loop that writes out three rows of the table and uses a counter to write out the row number correctly.

for(i = 0; i < 3; i++){
   document.write('<tr>')
   document.write('<td>row ' + i + ', column 0</td>')
   document.write('<td>row ' + i + ', column 1</td>')
   document.write('<td>row ' + i + ', column 2</td>')
   document.write('</tr>')
}
Here is a short HTML page that contains nothing but this simple table written out by JavaScript.
<HTML>
<HEAD>
<TITLE>Sample Page that Writes Out an HTML Table</TITLE>
</HEAD>
<BODY>
<SCRIPT Language="JavaScript">
<!-- 

document.write('<table border="1" cellspacing="1" cellpadding="5">')

for(i = 0; i < 3; i++){
   document.write('<tr>')
   document.write('<td>row ' + i + ', column 0</td>')
   document.write('<td>row ' + i + ', column 1</td>')
   document.write('<td>row ' + i + ', column 2</td>')
   document.write('</tr>')
}

document.write('</table>')

//-->
</SCRIPT>
</BODY>
</HTML>

Writing out the cells of the table using a loop inside a loop

In the previous example the loop block contains three statements that actually write out the table data tags that represent the three table cells in each row. Looking at these three statements:

   document.write('<td>row ' + i + ', column 0</td>')
   document.write('<td>row ' + i + ', column 1</td>')
   document.write('<td>row ' + i + ', column 2</td>')

we see they are almost identical. The only change is the number of the column. This kind of repetition is a clue that this too can be replaced with a loop. However, we are already using variable i to loop through each row. So another variable is needed to loop through the cells in each row. Using j to replace each column number and taking just one of these lines:

   document.write('<td>row ' + i + ', column ' + j + '</td>')

and placing this inside a loop using j:
   for (j = 0; j < 3; j++){
      document.write('<td>row ' + i + ', column ' + j + '</td>')
   }

Finally, placing this loop inside the HTML page in place of the three lines it replaces gives:

<HTML>
<HEAD>
<TITLE>Sample Page that Writes Out an HTML Table</TITLE>
</HEAD>
<BODY>
<SCRIPT Language="JavaScript">
<!-- 

document.write('<table border="1" cellspacing="1" cellpadding="5">')

for(i = 0; i < 3; i++){
   document.write('<tr>')
   for (j = 0; j < 3; j++){
      document.write('<td>row ' + i + ', column ' + j + '</td>')
   }
   document.write('</tr>')
}

document.write('</table>')

//-->
</SCRIPT>
</BODY>
</HTML>

Note that we now have a loop inside another loop. For every value of i in the outer loop, the inner for loop will run through all the values of j.

for(i = 0; i < 3; i++){
   document.write('<tr>')
   for (j = 0; j < 3; j++){
      document.write('<td>row ' + i + ', column ' + j + '</td>')
   }
   document.write('</tr>')
}

In this case for each row all the table cells will be written out. Of course writing out a table that contains text that numbers each row and column is only interesting for working out the idea of using loops to write out a table. Here is a slightly different table. In each cell the row and column numbers are added together and written into each cell. The result is looks very much like an addition table. WARNING: This script takes a while to run - be patient..

<HTML>
<HEAD>
<TITLE>Sample Page that Writes Out an HTML Addition Table</TITLE>
</HEAD>
<BODY>
<SCRIPT Language="JavaScript">
<!-- 

document.write('<table border="1" cellspacing="1" cellpadding="5">')

for(i = 0; i < 13; i++){
   document.write('<tr>')
   for (j = 0; j < 13; j++){
      document.write('<td>' +  (i + j) + '</td>') //Parenthesis to avoid concatenation
   }
   document.write('</tr>')
}

document.write('</table>')

//-->
</SCRIPT>
</BODY>
</HTML>

Cleaning up the script

Before moving on to adapting this script to the exercises below, it is always a good idea to review it to see if the script can be improved in some way. For example what if we want to change the size of the table? What changes are needed in the script? Is this the best way to do this? Also, the script seems to take a long time - what can be done to improve the speed at which the table appears? Is the script readable? Can what it does be made clearer?

First, the limits of the loops have been set using a literal value inside each for loop. It might be a small improvement to set variables with explict names to act as the limits for each loop. They might simply be called rows and columns. This trades off the use of a small amount of extra memory, for two more variables, to produce more easily readable and hopefully more easily adaptable code in the future. To change the number of rows or columns, set these two variables to different values. For example:

rows = 13
columns = 13

document.write('<table border="1" cellspacing="1" cellpadding="5">')

for(i = 0; i < rows; i++){
   document.write('<tr>')
   for (j = 0; j < columns; j++){
      document.write('<td>' +  (i + j) + '</td>')
   }
   document.write('</tr>')
}

document.write('</table>')

Second, though the variable names of i and j are often used we might consider replacing them with something more descriptive such as row and col. This is more a matter of style however and there is no absolutely right way. Third, and finally, you may have noticed that the table takes a long time to appear in the preceding script where 169 cells are drawn. Part of the reason for this is that each document.write() is a fairly slow operation. To improve things for large tables like this, we can collect the text to be written into the document into one string and then write the large string all out at once to speed things up. Here is an example - trying running it see if the table appears sooner than in the previous example.

<HTML>
<HEAD>
<TITLE>Sample Page that Writes Out an HTML Addition Table</TITLE>
</HEAD>
<BODY>
<SCRIPT Language="JavaScript">
<!-- 
rows = 13
columns = 13
str = ""
str += '<table border="1" cellspacing="1" cellpadding="5">'

for(i = 0; i < rows; i++){
   str += '<tr>'
   for (j = 0; j < columns; j++){
      str += '<td>' +  (i + j) + '</td>'
   }
   str += '</tr>'
}

str += '</table>'
document.write(str)

//-->
</SCRIPT>
</BODY>
</HTML>

The str variable initially holds an empty string. Instead of immediately writing out text into the document every bit of new text is appended on to the end of the str string. This is done using the += operator. For example:

str += '<tr>'

This is the short form way of writing:

str = str + '<tr>'

Writing out a multiplication table

Adapt the script above to produce a multiplication table. Your first step might be to change (i + j) to i * j. However you will also need to replace all the zeros in the top row and left-most column with the numbers 1 though 12. While we're at it lets remove the 0 in the upper left cell and put a multiplication symbol there. You table should look like this:

1 2 3 4 5 6 7 8 9 10 11 12
1 1 2 3 4 5 6 7 8 9 10 11 12
2 2 4 6 8 10 12 14 16 18 20 22 24
3 3 6 9 12 15 18 21 24 27 30 33 36
4 4 8 12 16 20 24 28 32 36 40 44 48
5 5 10 15 20 25 30 35 40 45 50 55 60
6 6 12 18 24 30 36 42 48 54 60 66 72
7 7 14 21 28 35 42 49 56 63 70 77 84
8 8 16 24 32 40 48 56 64 72 80 88 96
9 9 18 27 36 45 54 63 72 81 90 99 108
10 10 20 30 40 50 60 70 80 90 100 110 120
11 11 22 33 44 55 66 77 88 99 110 121 132
12 12 24 36 48 60 72 84 96 108 120 132 144