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

Adding JavaScript to a web page

We saw our first example of embedding JavaScript in a web page earlier, which is repeated below:

<html>
<head>
<title>A simple web page</title>
<script type="text/javascript">
alert("Hello world!");
</script>
</head>

<body>
Page body text
</body>

</html>

As we saw before, the actual JavaScript code in this example consists of the single statement 'alert("Hello world!");'. This is placed in a <script> tag in the header. The tag includes the additional term "type=text/javascript", which tells the web browser what sort of script is going to be included. Scripts can be placed anywhere in the document, although are usually placed in the <head> section. It is possible to have more than one script tag in any HTML page.

Have a go at copying the code from above into a file, save it as a html and open it.

Embedded scripts

The code shown above is an example of embedded JavaScript. The code is contained within the same file as the host HTML document, and is separated from the rest of the document through the use of the <script> tag.

Note that HTML has a markup for comments:

<!-- comment -->

Occasionally you'll see code inside script tags further nested inside HTML comments. This was to allow browsers that couldn't cope with JavaScript to ignore it quietly. It is no longer needed, as JavaScript is ubiquitous; however, you will still see it in legacy code. An alternative – and preferred – technique for handling situations in which a user has not got JavaScript enabled (for example, because they have noscript installed) is to use the <noscript> tag (the name of which is unrelated to the browser addin). This allows a message to be displayed to the user if JavaScript is not available:

<html>

<head>
<title>A simple web page</title>
<script type="text/javascript">
  alert("Hello world!");
</script>
<noscript>Your browser does not support JavaScript!</noscript>
</head>

<body>
Page body text
</body>

</html>

Note that even though this is in the HEAD area, it will usually be displayed at the top of the page when JavaScript isn't available. If you want to test this, here's how to turn off JavaScript in the major browsers.

Linking to external scripts

The above figures show examples of using inline JavaScript code – code that is contained within the same document as the HTML page that will use it. This is useful for initial development, as it keeps all parts of the page together. However, as programs become more complex, it can make sense to store the JavaScript code in a separate file (or set of files) to the HTML source. There is an alternative form of usage of the <script> tag, that allows us to do this, by including a src clause, and identifying a file containing the JavaScript source code. An example of this is shown below. The code is split into two parts.  First, there is an HTML file, called fib.html. In the head section, there is a script tag, which has the clause (or, as we call them tag "property") src="fib.js". This instructs the web browser to attempt to load a file called fib.js, and to treat it as JavaScript code. The web browser will try to load the file from the same location from which it loaded the HTML file (and thus the file should be placed in the same directory).

HTML document fib.html:
<html>

<head>
<title>Fibonacci sequence</title>
<script type="text/javascript" src="fib.js"></script>
</head>

<body>
Page body text
</body>

</html>

The remaining part of the code shows the source code that is contained in the file fib.js:

External JavaScript file fib.js:
/*
 * Calculating the first few numbers of the Fibonacci sequence
 *
 * f(n) = f(n-1) + f(n-2)
*/

var count;
var f_2 = 0;
var f_1 = 1;
var f_n;

document.write("<h1>Fibonacci numbers</h1>");
document.write("<ol>"); // start an html list

// Write the start of the sequence
document.write("<li>" + f_2 + "</li>");
document.write("<li>" + f_1 + "</li>");

// Loop to calculate some more values
for (count=1;count<10;count++) {

   f_n = f_1 + f_2; // Calculate f(n)
   document.write("<li>" + f_n + "</li>"); // Write the latest value

   f_2 = f_1;
     // Next iteration, f(n-2) will have the value of the current f(n-1)
   f_1 = f_n;
     // And f(n-1) will have the value of the current f(n)
}

document.write("</ol>");

It is a short program that calculates the first few values of the Fibonacci sequence, and it uses several of the language features that have been described in this introduction. The Fibonacci sequence is a series of numbers, in which the first two values are 0 and 1, and then further values are the sum of the two preceding values. The sequence is widely used in mathematics and has been applied in many areas, and the pattern has also been observed occurring naturally.

Copy the js and html code from above into two separate files, appropriately named, and see if you can get the example working. If you want to see it running, a version of this example is linked here: fib.html.

Breakdown of the code

The code starts with a multi-line comment noting what the program will do, and a number of variables are then declared, with two of them also being initialised.

/*
 * Calculating the first few numbers of the Fibonacci sequence
 *
 * f(n) = f(n-1) + f(n-2)
*/

var count;
var f_2 = 0;
var f_1 = 1;
var f_n;

The program uses the document.write() method to write new text to the web page, for example:

document.write("<h1>Fibonacci numbers</h1>");
document.write("<ol>"); // start an html list

// Write the start of the sequence
document.write("<li>" + f_2 + "</li>");
document.write("<li>" + f_1 + "</li>");

If you run the code, you will discover that the new elements are written before the remaining text ("Page body text") in the body section of the HTML page. This is standard behaviour, although, as we'll see, you can also change the content of pre-existing HTML elements after they have been displayed. The first two uses of document.write() add fixed elements to the HTML page – firstly an H1 level heading, and then an <ol> element. The <ol> tag in HTML indicated the start of an ordered (i.e. numbered or lettered) list; it is closed at the end of the script with the </ol> tag.

The next two statements again use document.write(), but in this case they use the '+' operator to join two strings. This is also known as concatenation:

document.write("<li>" + f_2 + "</li>");
document.write("<li>" + f_1 + "</li>");

The <li> tag in HTML signifies a list element: the <ol> list consists of a number of <li> components. In each case, we use '+' to join the value of one of our variables to the '<li>' stub.

The central part of the program is a for loop.

// Loop to calculate some more values
for (count=1;count<10;count++) {

   f_n = f_1 + f_2; // Calculate f(n)
   document.write("<li>" + f_n + "</li>"); // Write the latest value

   f_2 = f_1;
     // Next iteration, f(n-2) will have the value of the current f(n-1)
   f_1 = f_n;
     // And f(n-1) will have the value of the current f(n)
}

As described on the last page, the three operations controlling the loop are placed together - we set the count variable to an initial value of 1, we set an expression to signify when the loop should run (count < 10), and we set an incremental statement (count++). Inside the for loop we have a series of statements, so these are grouped together using '{}' to form a compound statement. In the compound statement, we first calculate the next value in the sequence, as f_n = f_2 + f_1 (note that the variable names include underscores, not the minus character). We then write out that value. Next, we need to update our variables for the next iteration of the loop. We set f_2 (two values ago, in the sequence) to the current value of f_1 (one value ago in the sequence), using the assignment operator '='. Then, we set f_1 to the current value f_n that we have just calculated. The order here is important: we must set f_2 from f_1 before we set about modifying f_1. Having reached the last sub-statement in out compound statement, the for loop is now repeated, having incremented the value of count.

Other ways of adding JavaScript

This page has explained two ways of embedding JavaScript code in a web page: inline embedding, and linking to an external source file. Using an external file is better for code maintenance, and has the distinct advantage that when a single piece of JavaScript code is used by more than one HTML file, you only need to fix bugs in the JavaScript code once. However, inline placement of code is useful for development and testing of new ideas, by keeping all the required parts in one file.

Note that external files don't have to be written by you; they may be a library of code you've downloaded (in JavaScript a library is a collection of useful code, usually presented as one huge JavaScript file – if it is more than one, you'll usually need to load in each file separately, as imports are generally not yet supported). Libraries don't even need to be on your local server – the src can be a URL to somewhere else on the web (provided the person storing the library is happy for their site to be hit with requests). There are pros and cons to the latter – the pros are that someone else will maintain the library for you; the cons are that any changes they make may break your code. For an example, see what happened during the 2016 left-pad incident, where code was removed from a library, and the removal propagated (through automatic code building frameworks) to other libraries.

Event driven programming

There are additional ways in which JavaScript can be linked into pages, notably as inline methods attached to events that might occur on the web page.

The example program shown above is a very simple program. It runs once – stepping through a sequence of instructions – and is then complete; it has no interactive elements in which it gets inputs from the user. Historically, this is the way that programs were designed: they read in some input data, processed it, calculated some results, and then finished. Over time, interactive elements became more common: programs would halt and wait for input from the user. A simple game might be written as a loop which incorporated a test to see whether the user was pressing any keys, as well as steps such as moving items on the screen, checking to see whether a laser bolt had hit an enemy spaceship, and so on.

Modern programs are typically written with graphical user interfaces (GUIs) in mind, which could receive user input (key strokes or mouse clicks, for example) at almost any time, and they have a very different structure. We write a collection of pieces of code, and assign them to various events such as keystrokes and mouse clicks, or the page being loaded. Rather than a single program, we end up with a group of interacting sub-programs. We do not need to worry about checking for user input: the web browser is responsible for running the appropriate event handler when an event occurs; it is the programmer's responsibility to indicate which of the various event handling pieces of code they have written should be triggered at which event.

All (or most) HTML page elements have associated events they generate, and their tags can be written so as to attach JavaScript to these events (you can find a list of events on w3Schools). The most commonly used events are onclick and onload. Onload is generated when the element (often the BODY) has finished loading, and is especially useful when you want to change HTML knowing the page has been fully loaded and the HTML elements are present. It is usually used to call a function from the HTML BODY tag:

<body onload="initialize()">

Note that JavaScript hides a lot of the complexity seen with registering handlers as event listeners in other languages, but, ultimately, what's happening here is not so different from event handling in other languages. The HTML elements (e.g. BODY) generate events, and we register a listener with them. The only difference is that the listener's name is pre-determined (e.g. onload) so the brower knows what to look for when senting out events. We then attach this name to the event handling function we actually want to run (remembering from the JavaScript introduction that we can attach names to functions).

The onclick event is triggered when an element is clicked. We'll come back to user-driven event programming a couple of times, but for now, a typical approach is to attach a JavaScript function call as the onclick code:

<img src="button.gif" onclick="buttonClick()">Do something</button>

This function must have been defined in JavaScript code attached to the document through the <script> tag.

The browser environment

We have discussed above different ways of adding JavaScript to web pages. We will now briefly consider the environment in which we will be running JavaScript programs – a web browser. There are a number of important aspects of this. First, it is important to understand the global 'Window' object and one of its properties, the 'Document' object, and secondly it is important to understand the way in which the browser structure leads to event driven programming.

As we have discussed in this introduction, JavaScript is an object oriented language, and many features are provided through methods associated with objects. Variables such as numbers and strings are themselves objects with methods; for example, the string objects have a method toLowerCase(), so any string can be written in lowercase, by using this method, e.g:

document.write("ABCDEF".toLowerCase());

Similarly, there are various methods associated with the Number object.

The Window object

In fact, all of these fundamental objects and functions etc are descended from a global Window object. All the variables that we use are members of the Window object, and methods such as alert() are methods of the Window object, although we can generally get away with not referring to the Window object. The following are essentially the same:

In general, when programming code that will run inside another application (in this case the web browser), you need some kind of "hook" that gives you initial access to the running application, and the ability to then drill down into it and access its sub-components (for example, a specific paragraph on a webpage). For JavaScript, that hook is the Window object. The Window object is associated with a distinct browser window or frame. As applications become more complex, it is possible that they might use multiple frames. When this is the case, then further considerations arise, as each frame will have its own Window object, and global variables in one frame are not global in another frame. There are techniques for accessing objects in other frames, but that is rather beyond the scope of this introductory lecture (more here if you need it).

The Document Object Model

One of the features of the Window object is that it includes a number of built in child objects. One of these is the Document Object Model, which we discussed briefly earlier. We have already seen this in our examples, as we have used the write() method to display text on screen, e.g:

document.write("Hello");

As noted above, the object document is a property of the global object window, formally window.document. Provided there's no other document object in scope, the browser will find it just using its short name. Note that whilst we refer to these objects in a descriptive manner using the capitalised words 'Window' and 'Document', we use all lower-case terms in our programs.

As the document object represents the HTML document in the browser window, we can add extra text to that HTML document through its write() method, and we also have access to elements within the HTML, such as forms, which permits actions such as form entry error checking.


[ Next: Debugging JavaScript]
[Course Index]