GEOG5870/1M: Web-based GIS A course on web-based mapping

Example JavaScript programs

So far, we have looked at the syntax of JavaScript, at the way in which programs are built from a series of statements, at branching and looping structures, and at some debugging tools. We have used an example program which calculates Fibonacci numbers to look at some of these ideas together. This page and the next show two more example programs to illustrate features of JavaScript.

First we'll look at a program to build a multiplication-table grid. In doing so, we'll look at a) why we might want to use onload; b) nested for loops; and c) how we change webpages after they're on the screen.

In the next page, we'll look at a program that works out the day of the week for a date. In doing so, we'll look at interacting with a form to get user supplied data.

Times-table grid

Our first example uses JavaScript to write a times-table square. It illustrates various principles that we have already discussed, and also illustrates some new language features. The code below shows the code for two files: an HTML document tables.html, and a linked JavaScript file, tables.js.

The HTML document is fairly simple, but contains a number of elements that we have not previously discussed. The <head> section of the document contains a number of pieces of metadata, such as the author and the character set to be used. It is useful to add metadata of this type, but not vital. In terms of this example, the key line in the <head> section is the <script> tag, which links to an external JavaScript file.

HTML file tables.html:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<title>JavaScript example - Times tables</title>
<meta content="Oliver Duke-Williams" name="author">
<script type="text/javascript" src="tables.js">
</script>
</head>

<body onload="load()">
<h1>JavaScript example - Times tables</h1>
<p>This is an example of using JavaScript to add text to a web page in a controlled manner, and of using nested loops.</p>
<div id="ttable"></div>
<p>This is part of GEOG5870/GEOG5871</p>
</body>

</html>

The <body> section features two important features. Firstly, we have added some more text into the <body> section, including a <div> element. The <div> tag defines a section or division of the web document. There are two important features to note in this case. Firstly, that the element is empty – the opening tag is immediately followed by the closing tag. Secondly, you will notice that the starting tag is expanded to include the property 'id="ttable"'. We can attach an ID property to any element, although each such ID should be unique within the document. We will make use of this in the JavaScript program to modify that particular element; specifically, we're going to fill it with a HTML TABLE build by JavaScript.

The second thing to note is that we have extended the definition of the <body> tag, by including the term 'onload = "load()"'. This is an example of defining a JavaScript event handler. We are instructing the browser to run a JavaScript function called 'load()' when the page has loaded into the browser (the onload event). We are doing in this in order to exert finer control over when our JavaScript program is run. In our previous examples, such as the Fibonacci numbers, we placed all our JavaScript code in the header, which caused it to be evaluated – and for text to be written to the document – before the rest of the HTML document had finished loading. Here, we want the page to load before we act on it, so our DIV tag exists. If we try and manipulate it before it has been displayed (before it exists), the code will fail.

Here's the JavaScript external file.

JavaScript file tables.js:
/*
 * Javascript examples - times tables
*/
function load() {

   /*
    * Create a text object containing an HTML table
    * We will repeatedly concatenate strings to build up the table...
   */

   var myTable = "<table>";
   myTable = myTable + "<tr><th>X</th>";

   // The header row
   for (x=1;x<=12;x++) {
      myTable = myTable + "<th>" + x + "</th>";
   }
   myTable = myTable + "</tr>";

   // The main part of the table
   for (y=1;y<=12;y++) {
      myTable = myTable + "<tr>"; // Start each new row
      myTable = myTable + "<th>" + y + "</th>"; // Write the row index

      // Write the table cells
      for (x=1;x<=12;x++) {
         myTable = myTable + "<td>" + (x*y) + "</td>";
      }

      myTable = myTable + "</tr>"; // Write the row ending tag
   }

   myTable = myTable + "</table>"; // The table closing tag

   // Get a reference to the location for the new table.
   document.getElementById('ttable').innerHTML = myTable;

}

The first thing the program does is to initialise a new string variable called myTable. In a series of steps, we increment this variable by adding new pieces to the end, using the '+' operator, in order to build up an HTML TABLE element. The TABLE element is hierarchical, and consists of a number of rows (TR) each containing cells which are either header cells (TH) or standard data cells (TD). Header cells and data cells can be used any where within the table – they are distinguished by the way in which they are rendered by the browser.

We start the first row, add an initial cell which contains 'x', and then enter a loop to add a set of header cells. The loop is a "for loop", with the constraints that the counter variable starts at 1, and that the loop will run whilst the counter is less than or equal to 12. Each subsequent cell therefore contains a higher number. Having done this, the table row is closed.

We then use a pair of nested for loops to construct the rest of the table:

   for (y=1;y<=12;y++) {
      myTable = myTable + "<tr>"; // Start each new row
      myTable = myTable + "<th>" + y + "</th>"; // Write the row index

      // Write the table cells
      for (x=1;x<=12;x++) {
         myTable = myTable + "<td>" + (x*y) + "</td>";
      }

      myTable = myTable + "</tr>"; // Write the row ending tag
   }

The outer loop (with the counter variable y) will run 12 times. On each occasion it will start a new row, and add a header cell to the start of that row. Them, an inner loop is run, which will run 12 times and thus add 12 cells to the row that has just been started. Each time the outer loop goes up by one, the inner loop restarts from 1 again and runs til 12. The table cell contents is the result of the calculation x*y. This process illustrates the weakly typed nature of JavaScript: x and y are used as numerical counters, and we assume x*y to have a numerical result. However, we can append that number to a string variable, without having to be concerned that they are different data types.

There is another aspect of this line that may be worth noting: we have placed the calculation x*y inside parentheses. Using parentheses can help to make calculations easier to read. Like all languages, JavaScript has a concept of operator precedence. This means that mathematical (and other) operations will always be carried out in a predictable order. Consider the calculation 2 + 3 * 4. If we carry out the multiplication operation (3 * 4) first, this becomes equal to 2 + 12, or 14. However, if we carried out the addition operation first (2+3), the calculation becomes 5 * 4, or 20. Clearly, we always want our calculations to produce predictable results, and thus there must be defined rules for the order in which operations take place. In JavaScript, as with regular maths, it is the standard behaviour to carry out multiplication and division before addition and subtraction. Of course, this process can be over-ridden by placing parts of a calculation inside parentheses, which will cause them to be evaluated first. In the case of our example above, the parentheses simply endorse the expected order, and don't affect the result. In fact, to make the code more readable, and therefore prevent errors, we recommend you always use paratheses to be explicit about how you want your maths to work.

Having added the data cells for each row, the program appends the table row "TR" closing tag to the string. We then reach the end of the statement attached to the outer loop, and start the next iteration of this outer loop. When the outer loop has been run the required number of times the loop structure is exited, and we add a table closing tag to our string, to complete our syntactically correct HTML table element:

   myTable = myTable + "</table>"; // The table closing tag

So, we now have an HTML page (the original document) and a piece of additional HTML code in a variable that we have created in our JavaScript program. We need to insert our additional code into the original code; when this happens the web browser will be responsible for updating the document that is displayed on screen. We do this by using a function that we have not previously met that modifies a property of the document object:

   document.getElementById('ttable').innerHTML = myTable;

Let's break this down. The first thing we need to do is find our DIV tag. As we have discussed, the document object is a representation of the HTML document that forms the page currently being displayed. Although we've talked about this very vaguely, it is worth knowing that this is structured into something called the Document Object Model or DOM. The DOM is composed of nodes, each of which represents an element of the page, and most of which can contain other nodes to build up a tree structure. In most cases, each node is a tag-pair, so, for example, the <BODY></BODY> tags represent one element/node, which will usually have other nodes contained inside it. The DOM can be navigated in a variety of different ways, but here we use document.getElementById('ttable') to find our DIV.

Once we've found our node, we can then manipulate it, thereby changing the webpage: for example, we can add new nodes to it, delete it, or change the content the equivalent tags contain. To do the latter, we need to get hold of the content between the tags. Each element has a property innerHTML, than can be replaced or modified and which contains the HTML within a pair of tags as a text string (including any other nodes). In order to add our additional table to the web page, we want to update the innerHTML of the empty <div> – we have planned ahead to add the table to this part of the page. We do this, in the line above, by setting the innerHTML to the variable myTable that includes the new HTML as a string.

Notice, this line is an example of the kind of method chaining we were talking about earlier.

The results of this program can be seen in below, and the copies of the file can be seen here: tables.html, tables.js.

Output of times tables program

[ Next: Second example program]
[Course Index]