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.
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.
[ Next: Second example program]
[Course Index]