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.
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.
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.
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)
}
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.
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.
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>
<script>
tag.
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.
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:
var x = 1;
var window.x = 1;
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).
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.