You are on page 1of 42

JavaScript

for
Beginners
Copyright © 2005 Jerry Stratton
http://www.hoboes.com/NetLife/Web_Scripting/
http://www.hoboes.com/NetLife/Web_Scripting/Web_Scripting.pdf
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free
Documentation License, Version 1.1. A copy of the license is included in the section entitled “GNU Free
Documentation License”
October 7, 2008
Getting Started 2

Getting Started
JavaScript allows you to create ‘dynamic, interactive’ web pages: web pages that do things in
response to what your readers do, without having a separate page for each possible response. In
this tutorial, I’m going to cover some of the very basics of using JavaScript in your web pages. I’m
going to assume that you know a little bit about HTML, but nothing about programming or
JavaScript. If you aren’t familiar with HTML, you’ll want to go over the Web Writing Guide at
http://www.hoboes.com/NetLife/Web_Writing/ first.

First, JavaScript has nothing to do with Java. Java is a separate programming language. JavaScript
is a language for scripting web browsers and web servers, although it is seeing other uses as it
becomes popular. Java was created by Sun and is designed for complete software applications,
while JavaScript was created separately by Netscape Corporation and is designed for modifying
(and “scripting”) web pages.

The Basic Web Page


The first thing we need to do is create two files for the tutorial: a web page, and a JavaScript file.
You can call them anything you want. I’m going to call the web page “basicscripting.html” and the
JavaScript file “scripts.js”.

basicscripting.html
<html>
<head>
<title>Basic JavaScript Tutorial</title>
<script src="scripts.js" language="JavaScript"></script>
</head>
<body>
<h1>Basic JavaScript Tutorial</h1>
<p>We will use this page to test out our dangerously revolutionary JavaScript programs.</p>
</body>
</html>

This is about as simple a web page as you’ll ever make. The only thing out of the ordinary is the
<script> tag inside the ‘head’ portion of the web page. Even that looks familiar if you’ve used the
<img> tag. The “script” has a “source” and a “language”. The language is obvious: we’re using
JavaScript. The “source”, or “src” is a file or URL to a file that stores scripts this page will use. In
this case, we’re telling the browser that the scripts this page uses are stored in a file called
3 Getting Started

“scripts.js”. The browser will go to our site and ask for that file in the same directory as the web
page. You can put any URL inside the “src” modifier, as long as it points to a valid JavaScript file.

scripts.js
//these are my basic javascripts

That’s it for “scripts.js”: we haven’t created any JavaScripts yet! In a JavaScript file, two slashes
(“//”) tell the web browser to completely ignore that line. Every line that begins with a “//” is a
“comment”. It isn’t JavaScript, and the browser would likely get in trouble if it tried to be dynamic
with that line.

JavaScript is line oriented. Unlike HTML, which uses opening tags and ending tags, such as
<head> and </head>, to identify the beginning and ending of things, JavaScript uses semicolons
and carriage returns. So, if you have the following file as a JavaScript file:

//this is a comment
this is another line

You are going to get an error. The browser is going to assume that the second line, “this is another
line” is some JavaScript code, but it isn’t.

Always be careful with carriage returns when writing JavaScript.

Alerts
One of the easiest and most useful things done with JavaScript is to alert you, the programmer, to
some aspect of your script, or alert the viewer that they’re possibly about to do something wrong.
You might display a warning if they didn’t fill in some required portion of a form, for example.

The JavaScript “code” for an alert is very simple. It is “window.alert” and then the alert message
you want to display. If you write “window.alert("Paul is sleeping")” in your JavaScript, a window
will pop up and display the phrase “Paul is sleeping”.

Let’s go ahead and write our first bit of JavaScript code. Add the following to your “scripts.js” file:

//displays message in alert window


function w_alert(w_message) {
window.alert(w_message);
return false;
}
Getting Started 4

The first line is a comment. The browser will ignore the line “displays message in alert window”,
but you won’t. You’re who its there for. A few months later when you look at the “scripts.js” file, you
will know what this JavaScript code does: it displays a message in an alert window. That’s what
comments are for. They “comment” your JavaScript code to remind you what this code does.

The second line tells the browser that we are creating a “function” called “w_alert”, and when we
use “w_alert”, we’re going to give it one thing to work with, which it will store in “w_message”.

By calling this a “function”, we are telling the browser not to perform these lines of JavaScript until
we ask it to perform the function called “w_alert”. By giving it one “parameter”, or “thing to work
with”, we are making it more useful to us. We can have it display any message we want, rather than
having to write one function for “hello” and another function for “goodbye”.

When we use this function, we “call” it by writing “return w_alert("The Message we want");”. If we
want it to say “hello”, we would write “return w_alert("hello");”. We put the message in quotes
between the two parentheses.

The third line, “window.alert(w_message);”, tells the browser to pop a message up with the
“variable” w_message. A variable is a place to store information. Because w_message was listed on
the “function” line, anything we write between the parentheses when we “call” w_alert will be
stored in “w_message”. So, whatever is in “w_message” gets displayed in the alert window.

The fourth line is “return false;”. Functions do not have to return anything, but usually they do.
And, usually, functions that get used on web pages return either “true” or “false”. In this case,
“false” tells the browser that the function handled everything, so that the browser doesn’t follow
that link. If we wrote “return true” here instead, our function would display the alert message, and
then after the viewer clicked to dismiss the message, the browser would follow the link. Often when
you display an alert, it is because you don’t want the browser to do what it normally would have
done (such as submit a form).

You’ll notice that each of the lines that does something ends in a semicolon. JavaScript requires
this. Each JavaScript step must end in a semicolon.

The function itself is surrounded by two curly brackets (“{ }”). Curly brackets in Javascript
surround chunks of JavaScript code that belong together. In this case, our two lines of JavaScript
are surrounded by curly brackets to indicate that they belong in the function called “s_display”.
5 Getting Started

We are ready to use our first JavaScript. Go back to “basicscripts.html” and add the following link:

<p><a href="http://www.hoboes.com/" onClick="return w_alert('You are not allowed to visit Negative


Space!');">Negative Space</a></p>

Remember that carriage returns are important, so everything between “onClick” and the final “)'”
need to be on the same line!

If you save this file, reload the page in your browser, and click the link, you should see a message
pop up saying “You are not allowed to visit Negative Space!”. See an example of how this should
work at http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson1.html.

The “pieces of information” that we send to functions are called “parameters” or “arguments”.
Functions don’t have to take parameters, in which case the parentheses after the function name will
be empty. Later on we’ll get to functions that take multiple arguments.

Image Placeholder
That’s all very simple. But it doesn’t make any fundamental changes to the web browsing
experience. Let’s go ahead and make something that displays images without traveling from page to
page. We’ll make a single page, with a single image, but that image will change depending on what
‘link’ the user chooses.

First, we need to add another “function” to our “scripts.js” file:

//changes an image to another image


function change_img(imgName,imgFile) {
document[imgName].src = imgFile;
return false;
}

What’s different about this function than our previous two?

First, it has a different name: “change_img”.

Second, this function takes two arguments instead of one or none. It calls these arguments
“imgName” and “imgFile”.

It has a completely different middle line: “document[imgName].src=imgFile”. What does that


mean? Well, “document[imgName]” is the image that we want to change. In order to use the
function “change_img”, our images have to be able to be identified to the web browser. They have
to have a name. You’ll give your images names by adding “name=something” to the HTML code for
Getting Started 6

the <img> tag. Once your image has a name, JavaScript can do things to that image by calling it
“document[the name]”. In this case, we’ve stored the name inside “imgName”, so
“document[imgName]” is the image that we’re going to change. If you’ll recall from HTML, each
<img> tag has a “src=” option that gives the URL where the web browser can find the image. We’re
changing the “src” for our named image to whatever is inside “imgFile”.

Let’s say we have an image on our web page called “gallery”. If we want to change the image inside
“gallery” to the image at
“http://www.hoboes.com/jerry/Gallery/Lego_Thumb.jpg”. We would call our “change_img”
function as: change_img("gallery", "http://www.hoboes.com/jerry/Gallery/Lego_Thumb.jpg").

Go ahead and make up a new web page:

<html>
<head>
<title>JavaScript Image Tutorial</title>
<script src="scripts.js" language="JavaScript"></script>
</head>
<body>
<h1>JavaScript Image Tutorial</h1>
<img
name="gallery"
border="2"
src="http://www.hoboes.com/jerry/Gallery/Christmas_Thumb.jpg"
width="160"
height="120"
align="right"/>
<ul>
<li><a onClick="return change_img('gallery',this.href);"
href="http://www.hoboes.com/jerry/Gallery/Christmas_Thumb.jpg">Christmas</a></li>
<li><a onClick="return change_img('gallery',this.href);"
href="http://www.hoboes.com/jerry/Gallery/Lego_Thumb.jpg">Legos</a></li>
<li><a onClick="return change_img('gallery',this.href);"
href="http://www.hoboes.com/jerry/Gallery/Gender_Thumb.jpg">Lenses of Gender</a></li>
</ul>
</body>
</html>

Save this file, and try clicking on the links. Instead of changing pages, what you should see is that
only the image on the right changes when you click on the link. See the example at
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson4.html.

You’ve probably already guessed that “onClick” is the “event” that happens when someone clicks on
a link. The function we call is “change_img”. We give change_img the arguments “gallery”, which is
the name of the image that we want to change, and “this.href”, which is… well, what is it? In
JavaScript, “this” refers to the current object. An “object” is a part of your web page. In this case,
7 Getting Started

the current object is the link to the image. That URL to the image is stored in the option called
“href”. So, “this.href” is the URL to the image that this link points to.

Because we “return false”, the web browser never actually follows the link. If, of course, the person
viewing your page has JavaScript turned off, their browser will completely ignore our JavaScript,
and it will simply visit the image the “old-fashioned way”. This is important: we have provided an
improved means of viewing our images for those who want it, but those who don’t want it can still
view the images, with no added work on our part. When designing JavaScript for your web pages,
remember that not everyone has JavaScript, and not everyone who has JavaScript wants to use it.
(Unfortunately, some commercial pages do annoying things with JavaScript, like pop up windows
in front of the page you’re trying to read. This causes many people to turn JavaScript off
completely, avoiding those annoyances, but also avoiding your tastefully presented JavaScript.)

By using “this.href” to reference our image, we allow non-JavaScript readers to view our images,
without any added work on our part. Always remember to keep things as simple as possible.
JavaScript allows you to make your web pages impossible to manage if you aren’t careful.

If you play around with the above and plug in some differently-sized images, you’ll notice that some
image(s) have to be stretched or squeezed to match the dimensions of the first image. That’s one of
the constraints on changing images: the web browser makes space for the image based on the first
image, and then forces all subsequent images to change their size to match.
Understanding JavaScript 8

Understanding JavaScript
Now that you have a good idea about some specifics of JavaScript, and how useful it is, its time you
learned a bit about how it works.

The Object Model


JavaScript assumes that there are “objects” on your page. Each part of your web page is an object
that JavaScript can use. An image is an object, a link is an object, and the web page itself is an
object. So is the window that the web page is in. Some objects have to be named: images and links,
for example, if you want to access them from another object on the page, will have to have a “name”
set with “name="something"”.

The web page is called “document”. You can always access the current web page by calling for the
“document”. The window is called “window”; you can access that by calling for “window”. Objects
can contain other objects. The “window” object contains an object called “history” that has
information about the web pages you’ve been to recently. If you want to access the “history” object,
you use “window.history”.

Objects have properties and functions built in to them. Usually, you will recognize the properties as
corresponding to the things that are inside the object’s tag. An <img> object, for example, has a
“src” property. An <a> tag has a “href” property. You use these properties with object.property. So
if you are working inside of a link (as we do above), and you want the “href” property, you would
use “this.href”. “This” is always the “current” object. The one we are inside.

Objects also have properties that you don’t normally set. The web page, for example, has a “last
modified” property, that tells the web browser when the page was last changed. The web browser
uses this information to know whether or not to reload the page or use the “cached” version of the
page. Because you call the web page “document”, you can access the time the page was last changed
as “document.lastmodified”. We’ll be using this in the next section to create an automatic “time
stamp” for our web pages.

We haven’t used any object functions yet. We’ve only created our own, standalone functions. When
we do use object functions, they look a lot like a cross between functions and object properties. The
“window” object, for example, has an object built into it called “history”, which contains the list of
9 Understanding JavaScript

pages that the browser has been to recently. If you want to tell the browser to go back to the
previous web page, you would use the “back()” function on the “history” object of the “window”
object: “window.history.back()”.

You can give object functions “arguments” just like we’ve already done with our custom functions.
For example, the “window” object has a function called “alert”. The “alert” function pops up a
dialog box with a message on it. We need to tell “alert” what that message is: “window.alert("If you
leave this page, I will no longer like you.")”.

The Event Model


“Events” are “things that happen on a web page”. If you click the mouse on a link, an “onClick”
event takes you to the new page. If you move the mouse over a link, an “onMouseOver” event
displays the URL in the status bar, and then when you move the mouse away, an “onMouseOut”
event clears the status bar. Events get “sent” to objects, and then the object decides what to do with
that event.

What we’ve been doing is intercepting events. The web browser already had something in mind for
all the events we’ve intercepted. On “mouseover” a link, it shows the URL; on “click”ing a link, it
moves to that link. We’ve intercepted those events (“onMouseOver”, “onClick”) so that the web
browser does something different.

JavaScript normally works almost exactly opposite HTML. HTML does something and that’s it. It
displays a page and it is done. The only thing the reader can do is read this static page, or click a
link and go to another page. With JavaScript, you can react to what the user does: as long as you
can find an event that corresponds to what the use has done and an object to intercept that event.

Scripting
JavaScript is a programming language. It is generally much less forgiving than HTML. Commands
end with semi-colons. Carriage returns are important. Curly brackets enclose blocks of JavaScript
code. You can’t play around with those rules and expect to get a working JavaScript web page.

You will also notice that I “indent” parts of JavaScript code. Usually, anything inside of curly
brackets gets indented by one tab more than the line just above it:
Understanding JavaScript 10

function bless_me(saintname) {
if (saintname == "Helena") {
window.alert("You are blessed by the shroud. ");
} else {
window.alert(saintname + " blesses you. ");
}
}

This indentation is not necessary. If you leave it out, your programs will work just fine. However,
indenting like this makes it much, much easier to see what your program is doing. You will always
want to indent in a standard format (which usually means using tabs).

Loops
One of the advantages of using a programming language is its ability to automate tasks that would
otherwise require repetitious typing. For example, suppose we have several different sets of images
to display, and we often add or subtract an image from the list. Rather than adding a new line to
our list each time, as we did above, we could keep a list of just the images, and create a JavaScript
function to turn our simple list of images into an HTML list.

Remove the list from your HTML code: everything from the opening “<ul>” to the ending “</ul>”.
Replace it with:

<script language="JavaScript">
imageList = {
"Christmas_Thumb": "Christmas",
"Lego_Thumb": "Legos",
"Gender_Thumb": "Lenses of Gender"
};
listImages('http://www.hoboes.com/jerry/Gallery', 'gallery', imageList);
</script>

Even though this is a programming language rather than HTML, it already looks easier to create
and easier to understand than the previous, HTML list with embedded JavaScript events. If we
choose to add a fourth image to this list, we need only add a line with the image’s filename and the
image’s title text. Note that each line except for the final line ends with a comma. This is an
“associative array”, which means that this is a list where the first item in each pair is “associated
with” the second item in the pair. Lego_Thumb is associated with Legos, for example.

This is only half of the solution, however. The last line inside the script tag calls a function named
“listImages()” that takes three options: the base of each image’s URL (most likely the folder the
images are stored in if you were to use this on your own site), the name of the image display img
tag, and the list of images we want the reader to choose from.

//imgFolder is the base of the URL for the images


11 Understanding JavaScript

//imgName is the name of the img tag that will display the images
//imgList is the list of image files we want to display, in the form "image name":"image filename"
function listImages(imgFolder, imgName, imgList) {
document.write("<ul>");
for (currentImage in imgList) {
aText = imgList[currentImage];
aHREF = imgFolder + "/" + currentImage + ".jpg";
onClick = "onClick=\"return change_img('gallery', this.href);\"";
aTag = '<a href="' + aHREF + '" ' + onClick + '>' + aText + '</a>';
listItem = "<li>" + aTag + "</li>";
document.write(listItem);
}
document.write("</ul>");
}

See the example at http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson4a.html. You’ll


see a lot of “document.write()” in these examples. That’s something that documents—that is, web
pages—can do in JavaScript: insert text into themselves. Wherever document.write() is called,
some HTML is being inserted into the web page. At the beginning of this function we write an
opening list tag and at the end we write the closing list tag.

for (currentImage in imgList) {


}

The meat of this function is inside a “for” loop. Loops begin and end with { and }, just as functions
do. The stuff inside the loop gets done over and over again. We’ll see different kinds of loops later,
but the “for” loop goes through its contents once for every item in the list. The list is the container
after the keyword “in”. In this case, it is our list of images and image titles. The word listed before
the “in” keyword is a container that contains each item of the list as we go through it. In this case,
the first time we go through the loop, “currentImage” contains one item; the next time, it contains
another item; and so on, until we have looped once for every item the imgList list contains.

aText = imgList[currentImage];

Recall that when we created the image list, we did so using pairs: the image’s file name (without the
“.jpg”) and the text that we want to appear on the link that displays the image. The currentImage
container contains only the first item in that pair. To get the second item, we need to ask the list for
it. When we use “listname[keyword]” we are asking the list for the item that is paired with that
keyword. The keyword is always the first item in the pair of items. The result is always the second
item which is associated with that keyword.

aHREF = imgFolder + "/" + currentImage + ".jpg";


onClick = "onClick=\"return change_img('gallery', this.href);\"";
aTag = '<a href="' + aHREF + '" ' + onClick + '>' + aText + '</a>';
listItem = "<li>" + aTag + "</li>";
Understanding JavaScript 12

These four lines construct the list item, what in our original HTML was “<li>…</li>”. The first two
lines construct the parts of the link (the “a” tag). The third line constructs the “a” tag from those
parts. The fourth line constructs the full “li” tag.

Each line does this by adding together the pieces. The third and fourth lines use the parts that were
constructed in the preceding lines.

document.write(listItem);

Finally, we use another “document.write()” to write out the list item. Thus, for each image in the
list we will write one “<li>…</li>” tag.

By construction our list using a function, we not only make it easier to add and remove images from
the list, we can also more easily change our mind later. For example, we might choose to display
them as a table, with thumbnails. Rather than modifying each page that displays a set of images, we
need modify only the function that each page calls.

Note also, of course, that by doing it this way anyone who does not have JavaScript will not be able
to see that list of images displayed on their browser.
13 Basic JavaScript

Basic JavaScript
You should play around with the previous JavaScripts. Incorporate them into a “real” web page or
two. When you feel familiar with them, we can start doing some more intensive programming.

A Smart “File Stamp”


It is very useful to have a “generic” part for your web pages, something that stays basically the same
throughout each page. This “footer” or “header” can include a link back to your home page, the last
date the page was updated, perhaps a link to the parent page if this is a subsidiary page on your
web site. Let’s create a JavaScript that creates a table of this information on our web page. Add the
following function to your “scripts.js” file:

function filestamp() {
homePage=new String('/NetLife/');
document.write('<table border="1" align="right">');
document.write('<tr><th align="right">', document.title, '</th></tr>');
document.write('<tr><td align="right"><a href="', homePage, '">Home</a></td></tr>');
document.write('</table>');
}

The first line creates a “String” object, calls it “homePage”, and gives it the value “/NetLife/”. What
does that mean? Remember that JavaScript deals with objects. A “String” object is a collection of
text. Your name could be a String object; your home town; just about anything normal that isn’t
something which you can add or subtract. Things you can add, subtract, multiply, etc., are
“Numbers”. Your income and your height in inches are numbers. Your phone number or social
security number are strings.

In this case, we made a new String and we put “/NetLife/” into it. You will actually want to put your
own home page path into. This tutorial site’s home page is http://www.hoboes.com/NetLife/ and
the path is the part after the hostname, that is, /NetLife/. If your home page is
http://www.sandiego.edu/~brunetti/, your home page path is /~brunetti/.

We will use the “homePage” String later in this program.

document.write('<table border="1" align="right">');

If you remember your HTML code for tables, you’ll recognize the part inside the straight quotes as
the beginning of a right-aligned table with a thin border. “write()” is a function on the “document”
object. It inserts HTML code into the web page (the “document”). What does it write? It writes
Basic JavaScript 14

whatever arguments you give it. You can give it as many arguments as you want. It will write each
one, in order, to your web page.

document.write('<tr><th align="right">', document.title, '</th></tr>');

If you count them, you’ll see three arguments given to “document.write()”. The first argument
opens the table row and the table header; the second argument is something called
“document.title”, and the third argument closes the table header and the table row. What is
“document.title”? Remember that “document” is our web page. So “document.title” is the title of
our web page. It is whatever we put between the “<title>” and “</title>” in the “<head>” area of
the web page.

The next line is just like the previous one, except that it puts a link to the home page inside of a
normal table cell. The last line closes the table.

Now, let’s make a web page to put use this script on. Call it “advanced.html”:

<html>
<head>
<title>JavaScript Programming Tutorial</title>
<script src="scripts.js" language="JavaScript"></script>
</head>
<body>
<script language="JavaScript">
filestamp();
</script>
<h1> Making a Global File Stamp</h1>
<p>Of course the unexpected often looks as if it were expected. Some indeed expect the
unexpected. Such is life. This leaves me in a pretty pickle and I hope you won’t refer me and my questions to
Sheet, for Sheet, according to this paper has been silent since last night.</p>
<p>Your questions? You know the loan was given to the shipyard don’t you?</p>
</body>
</html>
Scripting Your Web Pages
And you should get a ‘file stamp’ on the right, top of Home
your page, much like I have one to the right of this
paragraph. See http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson5.html for the
example.

Last Update
Many web pages on the net tell you when they were last updated. This is commonly done by the
web designer actually typing in the new date whenever they make a change. But that’s prone to
failure, because it is easy to forget. The better way is to use “server-side includes” to have the web
server automatically add this information. If you don’t want to or can’t use server-side includes
15 Basic JavaScript

(most free web hosts don’t support them, for example), you can do the same thing with javascript.
So, let’s add a “Last Updated On” line to our file stamp.

We’ve already used one property of our web page: document.title. The date and time that the web
page was last changed is in another property, document.lastModified. So, let’s add another line to
our “filestamp” script function:

function filestamp() {

document.write("<tr><th align=\"right\">",document.title,"</th></tr>");
document.write("<tr><td align=\"right\">Last Updated: ",document.lastModified,"</td></tr>");

}
Scripting Your Web Pages
If you’re doing this from your local hard drive, you Last Updated: Wed, 29-May-2002 17:06:15 GMT
might see a really old date or no date at all. That’s Home

because browsers get this information from the server,


and if you’re doing this from your hard drive, there is no server. If that happens, upload the script
to your web account and try from there. See
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson6.html for the example.

Suppose we want to reformat the date to something smaller? Let’s change it so that it just gives the
month/day/year. This requires creating a function that takes a date as its “argument” and returns
the date in the format we want, in this case just month/day/year.

JavaScript has a number of built-in functions that give us the information we need. There is a
“getFullYear()” function, a “getMonth()” function, and a “getDate()” function to get the year,
month, and day of the month from a date. That’s all the information we need, but it isn’t quite as
easy as that. You may have heard about javascript being “object oriented”. That means that it has
“objects” that can do things. A date is also an object, and it can do things to itself: such as give you
the year, month, and day of the month for that date. The “getFullYear()” function is attached to all
date objects, and you need a date object in order to use it.

Even though it looks like one, document.lastModified is not a date. It is a bunch of text that looks
like a date. To get the year, month, and day out of it, we need to convert the text into what
JavaScript recognizes as a date. The command to do this is:

myDate = new Date(document.lastModified);

The “new” function creates a new object. This is going to be a “Date” object, so the full command is
“new Date()”. And the “new” command, with respect to “Date” is very intelligent: it can take a text
Basic JavaScript 16

string that looks like a date, and create a date object from that text string. By using “new
Date(document.lastModified)”, we are getting a date object that is the exact date and time that our
web page was last changed.

In order to use this new date object, we have to give it a name, so we can refer to it later. Like our
“homePage” string, we will use “changeDate = new Date(document.lastModified);” to create a Date
object called “changeDate”.

Let's go ahead and add that line to our filestamp() script. Put it above all the “document.write()”
lines, below the “homePage=” line.

homePage=new String('/NetLife/');
changeDate = new Date(document.lastModified);

Now, you can’t just replace “document.lastModified” in the document.write line with “changeDate”.
Well, you can, but you’ll get an even longer date line than you had before (go ahead and try!). We
need to make a function that takes our new date object and returns just the month, day of month,
and year. Let’s call it formatDate(). Change “document.lastModified” in the “document.write()” line
that includes it to “formatDate(changeDate)”:

document.write('<tr><td align="right">Last Updated: ', formatDate(changeDate), '</td></tr>');

Next, we have to write the “formatDate()” function:

function formatDate(theDate) {
thisyear = theDate.getFullYear();
thismonth = theDate.getMonth();
thismonth++;
thisday = theDate.getDate();
dateformatted=thismonth + '/' + thisday + '/' + thisyear;
return dateformatted;
}

And that should give you a date line in your “stamp” that looks like, for example, 6/29/2008! See
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson7.html for the example.

Some of our new “formatDate()” function (in fact, probably most of it) is a bit confusing. Let’s take
this function on, one step at a time.

function formatDate(theDate) {

This creates the function called formatDate, and specifies that it can receive one “argument”, which
will be called “theDate” inside of this function. When we call the “formatDate()” function, we might
call it with “formatDate(changeDate)” or “formatDate(currentDate)” or even
17 Basic JavaScript

“formatDate(birthDate)”. But whatever “argument” we send “formatDate()”, it will be called


“theDate” inside of the function.

thisyear = theDate.getFullYear();

This creates a number called “thisyear” which is the “year” portion of “theDate”. You might expect
this function to be “getYear()”, but due to historical reasons, getYear() is “deprecated”, which
means, don’t use it.

thismonth = theDate.getMonth();

Next, we get the month, as a number, from theDate.

thismonth++;

Computers have a tendency to start at 0 whenever they can. In JavaScript, months go from 0 to 11,
not 1 to 12. Humans, of course, go from 1 to 12. The line “thismonth++;” adds one to the variable
“thismonth”. (You could also use “--” to reduce a number by one.)

thisday = theDate.getDate();

And we get the day of the month. Even in JavaScript, the day of the month starts at one, so we don’t
need to use “++” to increase it by one. Believe it or not, this is consistent. It makes sense to start the
month at 0, but the day of the month at one. We’ll get to why this is consistent later, when we talk
about keeping lists of items. For now, just remember that the months start at 0, and the days start
at 1.

dateformatted=thismonth + '/' + thisday + '/' + thisyear;

We create a line of text that has the month, a slash, the day, a slash, and the year. We put this line
of text into a line of text called “dateformatted”.

return dateformatted;

We return that line of text to whatever part of our script called the “formatDate()” function.

The final “}” ends the function.

You should have a script file that looks sort of like this:

//time stamp functions


function filestamp() {
homePage = new String('/NetLife/');
changeDate = new Date(document.lastModified);
document.write('<table border="1" align="right">');
document.write('<tr><th align="right">', document.title, '</th></tr>');
document.write('<tr><td align="right">Last Updated: ', formatDate(changeDate), '</td></tr>');
document.write('<tr><td align="right"><a href="', homePage, '">Home</a></td></tr>');
Basic JavaScript 18

document.write("</table>");
}
function formatDate(theDate) {
thisyear = theDate.getFullYear();
thismonth = theDate.getMonth();
thismonth++;
thisday = theDate.getDate();
dateformatted=thismonth + '/' + thisday + '/' + thisyear;
return dateformatted;
}

Smart Date
Now that we’ve created a “formatDate()” function, we can make that function smarter. Why not
have it say “Today” if the date we sent it (the date we last modified our web page) is today? And
“Yesterday” for yesterday? This is easy to do, but we need to do a lot more “checking” inside of our
“if” statement. We’ve already used “if” to do something if a certain condition is met. But we can also
do one thing if one condition is met, otherwise do a second thing if a second condition is met, and if
neither of those conditions are met, do a final thing instead.

Change the top and bottom of your formatDate() function to:

function formatDate(theDate) {
today = new Date();
oneDay = 24*60*60*1000;
UTCDiff = today.getTimezoneOffset()*60*1000;
msToday = today.getMilliseconds() + today.getSeconds()*1000 +
today.getMinutes()*60*1000 + today.getHours()*60*60*1000 - UTCDiff;
if (theDate >= (today - msToday)) {
dateformatted = 'Today';
} else if (theDate >= today - msToday - oneDay) {
dateformatted = 'Yesterday';
} else {
thisyear = theDate.getFullYear();

dateformatted=thismonth + '/' + thisday + '/' + thisyear;
}
return dateformatted;
}

Our original “formatDate()” function is now within the last “else do this” section of our “if”
statement. Determining whether a file was last modified “today” or “yesterday” is not as easy as it
sounds at first: we can’t just check to see if the file was modified within the last 24 hours–24 hours
ago is usually yesterday, not today. We need to determine when today started, and then see if the
file was modified after today started. If so, the file was modified today. If not, we see if the file was
modified in the 24-hour period before today. If so, it was modified yesterday. Otherwise, we create
19 Basic JavaScript

the date it was modified and show that. See


http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson8.html for the example.

Dates in most programming languages are stored as numbers: they are usually stored as a certain
number of days, seconds, or milliseconds from some arbitrary starting point. JavaScript uses
milliseconds. Any date in JavaScript can be represented by the number of milliseconds that date is
from the “starting date”. (The date of the starting date is immaterial, since you will always be
calculating “off of” it. It might even change from client to client, but you don’t care.)

today = new Date();

If you ask for a new Date and don’t specify what that date is, you get right now. In JavaScript, a
“Date” is really a date and a time. You’ll recall from our first timestamp that the date modified
included the actual time the file was modified.

oneDay = 24*60*60*1000;

In order to determine whether the file was modified yesterday, we need to know what number
makes up a day. Since JavaScript stores dates in milliseconds, we ask for 24 (hours per day), times
60 (minutes per hour), times 60 (seconds per minute), times 1000 (milliseconds per second). You
could simply calculate that number on your calculator and then use it directly, but storing the
number in a variable called “oneDay” makes it easier to remember what that number means when
you look at your code later on.

UTCDiff = today.getTimezoneOffset()*60*1000;

Web page dates are stored in Universal Time (GMT: Greenwich Mean Time). If we want to know
when the file was modified in the client’s local time, we need to determine the time zone offset. The
time zone offset is given in minutes, so we need to multiply by 60 to get the seconds, and then by
1000 to get the milliseconds.

msToday = today.getMilliseconds() + today.getSeconds()*1000 +


today.getMinutes()*60*1000 + today.getHours()*60*60*1000 - UTCDiff;

Our “today” contains the date and time right up to now. This line determines what we need to
remove from “today” to get the beginning of today. If it is 5:40 AM and 17 seconds and 553
milliseconds, this will (before the “UTCDiff”) give us 553 milliseconds plus 17 seconds plus 40
minutes plus 5 hours, converting each number into milliseconds. The calculation then removes the
time zone difference. If we substract our “msToday” from our “today”, we get the beginning of
today in local time.

if (theDate >= (today - msToday)) {


dateformatted = 'Today';
Basic JavaScript 20

Our first “if” checks to see if “theDate” (which you’ll recall is the date our file was modified) is after
or equal to the beginning of today. If so, it sets “dateformatted” to the word “Today”.

} else if (theDate >= today - msToday - oneDay) {


dateformatted = 'Yesterday';

If the first condition does not match, we check to see if “theDate” is after or equal to the beginning
of today minus 24 hours. If so, we set “dateformatted” to the word “Yesterday”.

} else {
thisyear = theDate.getFullYear();

Finally, if neither of the first two conditions match, we do our previous calculation to create a string
that represents the date that the file was modified.

It’s a good idea to test more than one condition. Right now, since we’re editing this page, we should
expect it to say “Today”. But we should also test what’s going to happen tomorrow and the day
after.

After the line that says “oneDay = …”, add these two comments:

//today = new Date(today.getTime() + oneDay)


//today = new Date(today.getTime() + oneDay*2)

Remove the slashes in front of the first line to check what will happen tomorrow; remove the
slashes in front of the second line to check what will happen the day after tomorrow. Put the
slashes back once you’re done testing. The “getTime()” function returns the number of milliseconds
since JavaScript starts counting time. By adding oneDay to it or twice oneDay to it, we can pretend
that it is tomorrow or the day after tomorrow.

Current Time
It can be useful, especially for dynamic pages, to show the current time on the web page. This lets
the viewer know how up to date the information is—when they last reloaded the web page. We can
format a “current time” date just like we formatted a date-only date. Add the following line to your
“filestamp”:

document.write('<tr><td align="right">Current Time: ', formatTime(new Date()), '</td></tr>');

This calls a function called “formatTime()” with an argument of “new Date()”. We already know
what “new Date()” does: it gets the current time. So we’re sending the current time to our new
formatTime() function. Let’s create the function.
21 Basic JavaScript

function formatTime(theDate) {
thishour = theDate.getHours();
thisminute = theDate.getMinutes();
if (thishour > 11) {
thishalf='PM';
} else {
thishalf='AM';
}
if (thishour > 12) {
thishour -= 12;
}
if (thisminute < 10) {
thisminute = '0'+thisminute;
}
timeformatted = thishour + ': ' + thisminute + ' ' + thishalf;
return timeformatted;
}

You should be able to follow this from the description of “formatDate()”. It does the same thing, but
with hours and minutes instead of month, day, and year. We check the hour to see if it is AM or PM
(and then substract 12 from the hour if the hour is 1 PM or later). We make sure the minutes are
zero-padded on the left. And then we return a string that looks like “5:32 PM”. See
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson9.html for the example.

Using Lists
Our smart “formatDate()” function tells us if the date was yesterday or today. Why not also make it
return the name of the weekday if the date is within six days past? This is relatively simple to check
for: all we need to do is add an extra “else if” to our list of conditions, and see if the document’s
modification date is within the last six days.

We could use one “else if” for each possible day, but this is time consuming and prone to error—and
we don’t even really know what day three days past was. A better choice will be to determine what
the current day is, offset this by the number of days past, and then check a list of weekdays to get
the weekday name. That is, we’ll work with numbers first, because that’s what computers are good
at. Once we get the number (i.e., the second day, third day, etc, of the week) we’ll look at a list and
get the appropriate item from the list.

Add our new JavaScript code after the part where we check for yesterday:

} else if (theDate >= today - msToday - oneDay) {


dateformatted = 'Yesterday';
} else if (theDate >= today - msToday - oneDay*6) {
weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
Basic JavaScript 22

theWeekDay = theDate.getDay();
dateformatted = weekDays[theWeekDay];
} else {

This is pretty simple. The new part is the list of weekdays.

} else if (theDate >= today - msToday - oneDay*6) {

If “theDate” isn’t today and it isn’t yesterday, we see if it is one of the last six days, by multiplying
“oneDay” by 6 and subtracting it from today. If theDate is greater than the result, we know that
theDate is within six days of today.

weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

Computers tend to work with numbers, but telling people that this page was last modified on
weekday “6” isn’t very user-friendly. Here, we create a list of weekdays in English (more advanced
JavaScript programmers would check the user’s language and create the list in that language).

Once we have a “list” (they’re usually called “arrays” by programmers), we can ask the computer for
the first, second, third, etc., item from the list. The trick is that JavaScript, like many computer
languages, starts counting from zero instead of from one. The first item in a list is item 0. The
second item is item 1. As you get into more advanced programming you’ll find that this is a useful
feature. For now, though, it’s probably confusing. Just remember that JavaScript starts counting at
zero and you’ll be okay.

When you ask for an item from a list, you do so with the list’s name (in this case, “weekDays”) and
the number of the item in brackets: “weekDays[3]” is the same as “Wednesday”. Wednesday is item
3 (the fourth item) in our list of weekdays. Where lists really become useful is that we can do that
asking with a variable. If we have a variable called “payday” and it has “5” in it,
“weekDays[payday]” will give you “Friday”. And that’s what we’re about to do.

theWeekDay = theDate.getDay();
dateformatted = weekDays[theWeekDay];

When we ask the “theDate” object to “getDay()”, it will return a number from 0 to 6, with zero
being Sunday and 6 being Saturday. So we take that number and ask our “weekDays” list for the
corresponding item in the list. That gives us the weekday when our web page was last modified. See
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson10.html for the example.
23 Advanced JavaScript

Advanced JavaScript
Working With Strings
So far we haven’t done much with strings except to add them together (“concatenate” them in
programmers’ parlance) to make larger strings. We can also take them apart to make smaller
strings, and look inside them to see what they contain.

It is useful to always show the user a “parent” page for the page they’re currently viewing. Often
your viewers come to your site from a search engine, and they don’t necessarily come in to your
site’s main page. By providing a parent page link, you give the viewer the option of switching “up”
to a more general view of your site, without going all the way up to the home page and then
navigating back down again (assuming they even know how to navigate back down).

Every page except for your home page has a “parent” page, and if you have designed your site well,
the “parent” page is in the same folder as the current page, or is in one folder up if your visitor is
already visiting your main page for that folder. For example, the parent page of
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson5.html is
http://www.hoboes.com/NetLife/Web_Scripting/lessons/. And the parent page of that is
http://www.hoboes.com/NetLife/Web_Scripting/. The parent page of that is
http://www.hoboes.com/NetLife/ and that has no parent page, since it is the tutorial section’s
home page.

Of course, we wouldn’t want to show the parent page if it is the same as the home page. (In looking
at your filestamp, you might or might not want to show the “Home” link if you are on the home
page. It is up to you, and I’ll leave the JavaScript code for checking it up to you as an exercise.)

What we can do is check the current page—the one we’re viewing—against the home page, the one
we created in the “homePage” string.

Add a line to get the parent page’s URL just after you set the homePage string:

homePage = new String('/NetLife/');


parentPage = findParent(document.location, homePage);
Advanced JavaScript 24

This calls a subroutine called “findParent()” which will give us the parent URL of the document’s
URL. We’ll write that subroutine in just a bit. Change the document.write line that prints the Home
link to:

document.write('<tr><td align="right">');
if (parentPage) {
document.write('<a href="', parentPage, '">Parent</a> | ');
}
document.write('<a href="', homePage, '">Home</a>');

We’re going to put the “parent” link on the same line as the “Home” link. So we break out the part
where we create the table cell, and if the “parentPage” string has anything in it, we put that on the
line in front of “Home”, with a vertical bar to separate the two words.

function findParent(childPage, homePage) {


childPage = new String(childPage);
homeLocation = childPage.indexOf(homePage);
if (homeLocation >= 0) {
//first, chop off everything in front of the homePage
parentPage = childPage.slice(homeLocation);
//second, find the location of the final / and chop to it
//but first, if the last character is a /, get rid of it
if (parentPage.charAt(parentPage.length-1) == "/") {
parentPage = parentPage.slice(0, -1);
}
slashLoc = parentPage.lastIndexOf('/');
if (slashLoc > 0) {
parentPage = parentPage.slice(0, slashLoc+1);
} else {
parentPage = '';
}
} else {
//the home page is not contained in the child page
parentPage = '';
}
return parentPage;
}

This is probably looking pretty complicated. We haven’t done this sort of thing to strings before.

function findParent(childPage, homePage) {

We are creating a function called “findParent()” that takes two arguments: the page we’re trying to
find the parent of (we’re calling it “childPage”) and the ultimate parent (the “homePage”).

childPage = new String(childPage);

First, we ensure that the “childPage” variable is in fact a string object, because we are going to need
to use some serious string functions on it.

homeLocation = childPage.indexOf(homePage);
if (homeLocation >= 0) {
//first, chop off everything in front of the homePage
parentPage = childPage.slice(homeLocation);
25 Advanced JavaScript

When you ask for string.indexOf(otherstring), you are looking for the string “otherstring” inside of
“string”. This returns a number, from zero to the length of the string, depending on where the
“otherstring” is. Actually, the maximum location of “otherstring” is one less than the length of the
string, because JavaScript starts counting from zero. The first location in a string is zero, and the
last location is the length minus one. If you look for the string “a” in the string “Gila”, “indexOf()”
will return 3. If you look for the string “Gi” in the string “Gila”, “indexOf()” will return 0, because
that’s the location the string “Gi” starts at in the string “Gila”.

So when we ask for the location of “homePage” inside of “childPage”, we know that homePage
exists if the result is zero or more (“indexOf()” returns a negative one if the needle does not exist in
the haystack). Since URLs are relative, we can make things a little easier on ourselves by chopping
off everything except the homePage portion and whatever exists after the homePage portion. That’s
what the “slice()” function does. It slices the string, starting at the number we give it. So when we
call “slice(homeLocation)”, we throw away everything that occurs before the homePage portion of
the string. If the homePage is “/NetLife/” and the childPage is
“http://www.hoboes.com/NetLife/Web_Scripting/” then after the slice, parentPage will be
“/NetLife/Web_Scripting/”.

if (parentPage.charAt(parentPage.length-1) == '/') {
parentPage = parentPage.slice(0, -1);
}

We are going to find the parent by chopping off the last portion of the URL. URL portions are
separated with the “slash” character. But some URLs have a slash at the end, so we need to get rid
of that slash if it exists. The “charAt()” function tells us what character is at that location. Since
locations begin at zero, the final location is length minus one. Here, we’re checking to see if the
final location in “parentPage” contains a slash. If it does, we do the next line, which slices
parentPage from 0 (the first location) to negative one (a special number that tells slice to chop one
character off from the end).

slashLoc = parentPage.lastIndexOf('/');
if (slashLoc > 0) {
parentPage = parentPage.slice(0, slashLoc+1);
} else {
parentPage = '';
}

We set the variable “slashLoc” to the location of the last slash in parentPage. The function
“lastIndexOf()” is just like “indexOf()” except that it starts looking from the end of the string
instead of from the beginning.
Advanced JavaScript 26

Then we check to see if the slash’s location is greater than zero. If it is zero (or less), then there is no
parent page, so we just set parentPage to an empty string. If it is greater than zero, we slice
parentPage from the beginning to the location of the slash. When you give “slice()” a second
number, “slice()” slices to the character in front of that number’s location. So if we want to actually
include that character, we need to add one to the slash’s location. We want our parent to include
the final slash, so we do the addition.

At this point, if childPage contained, for example,


“http://www.hoboes.com/NetLife/Web_Scripting/lessons/” then parentPage now contains
“http://www.hoboes.com/NetLife/Web_Scripting/”. The rest of the script just returns this to
whoever called the function “findParent()”.

You can see an example of this script in action at


http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson11.html.

Adding the parent’s name


Rather than simply write “Parent” as the link’s text, we can write the name of the parent’s folder.
This is relatively simple compared to grabbing the parent. In fact, it’s somewhat complementary:
instead of grabbing everything before the current location, we want only the current location. If our
parent is “/NetLife/Web_Scripting/” we want “Web_Scripting”.

In the “filestamp()” function, under where we set “parentPage”, add a line to set “parentName”:

parentPage = findParent(document.location, homePage);


parentName = getName(parentPage);

Change the line that writes the Parent link to:

document.write('<a href="', parentPage, '">', parentName, '</a> | ');

All we need do now is create the “getName()” function.

function getName(theURL) {
//find the location of the final slash if it exists
if (theURL.charAt(theURL.length-1) == '/') {
theURL = theURL.slice(0, -1);
}
slashLoc = theURL.lastIndexOf('/');
if (slashLoc > 0) {
theName = theURL.slice(slashLoc+1);
//get rid of trailing .xxx
dotLoc = theName.lastIndexOf('.');
if (dotLoc > 0) {
27 Advanced JavaScript

theName = theName.slice(0, dotLoc);


}
} else {
theName = 'Top';
}
return theName;
}

Most of this we’ve already seen. We check to see if the last character is a slash, and if so, we delete
it. We then check to see where the final remaining slash is, and this time, we slice from that
location instead of to that location. We also check to see if there is a period in the resulting name.
This will happen if, for example, our name is “fred.html” or “current.cgi”. Usually, we wouldn’t
want to see the “.html” or the “.cgi”, those are for the computer. So we chop anything after (and
including) the final period.

If there is no name (for example, the page URL is “/”), we just return the name “Top”.

See this script in action at


http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson12.html.

Bread Crumb Trail


Now that we can get the name and the URL for the parent, why not show all the parents, in order?
This is like the “trail of bread crumbs” that Hansel and Gretel left to know where they came from. It
shows the viewer what pages normally “contain” this page, and thus provide possible avenues of
exploration for further information.

We already know how to “loop” with the “while” statement, but we didn’t pay much attention to it.
Here, we’ll use the “while” statement to keep adding new parents onto the old parent until there is
no more parent left.

First, change the “if/then” that prints the parent to:

if (parents) {
document.write(parents);
}

We will create a string called “parents” that contains the names and links to the parent pages. Now,
we need to create that variable. Up at the top, where you set the parentPage and the parentName,
replace those two lines with:

parents = '';
parentPage = document.location;
Advanced JavaScript 28

while (parentPage = findParent(parentPage, homePage)) {


parentName = getName(parentPage);
parentLink = '<a href="' + parentPage + '">' + parentName + '</a>';
parents = parentLink + " | " + parents;
}

On the first line, we set the “parents” variable to an empty string. We need to do this because,
inside the while loop, we are going to be building this string up piece by piece. Each time we get a
new parent, we will add the new parent to the pre-existing “parents” variable. But the first time
through the loop, there is no pre-existing “parents” variable unless we have already created one.
That’s what we do here. We created the “parents” variable, but left it empty.

We do the same thing for “parentPage”. We’ll be setting this in the loop, but we’re also using it the
first time through the loop. So we need to set it to our starting point before we enter the loop. We
set it to the document’s location. Our first parent will be the immediate parent just above our
document’s location.

while (parentPage = findParent(parentPage, homePage)) {

Our “while” will repeat all of the JavaScript lines between the “{” and the corresponding “}” four
lines down. It will continue to repeat those lines until the above function returns nothing, or zero.
In this case, it will return nothing, since that’s what our “findParent()” function does when there
are no more parents. As long as “parentPage” contains something, the “while” will make JavaScript
loop through the next few lines. Remember that “parentPage” is getting smaller each time we call
the “findParent()” command. Eventually, it will be empty, and the loop will stop.

parentName = getName(parentPage);
parentLink = '<a href="' + parentPage + '">' + parentName + '</a>';
parents = parentLink + " | " + parents;

For each parent, we get the name of the parent. Then we create the link. And then we “prepend” the
link to the previously existing “parents” variable. When the loop is completed, the “parents”
variable will contain each of the parents, separated by a vertical bar. See an example of this script in
action at http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson13.html.

Cookies
I’m sure you’ve seen web pages that tell you how many people have visited a site. JavaScript can’t
do that. But it can tell the visitor how many times their computer has visited the site. Your script
can do this by storing a “cookie” on their computer, and then checking that cookie every time it
runs. A “cookie” is like a variable that lasts even when the script isn’t running. The script can ask
29 Advanced JavaScript

for it whenever the script starts up, and then modify it as well. We can use a cookie to keep track of
how many times the current user has loaded our web page.

Cookies, like JavaScript, exist on the client computer. They can be turned off, and they can be
modified by the client. Like JavaScript, you cannot trust cookie values. But you can use them to
assist the user, to store information such as when they last visited and what their browsing
preferences are if you allow a choice of preferences.

Try to keep the number of cookies you use down to one or two. If you need more, you probably
need to keep a database on the server to store the user’s information.

We are going to use our cookie to keep track of how many times the visitor has been to our site.
Using cookies comes in two parts: setting the cookie, and getting the cookie. Each cookie has a
name, a path, and a value. The path is important. It ensures that we are the only ones who get to
see this cookie (other than the client). If, for example, you are using geocities, and you set the path
to “/”, you’ll end up giving that cookie information to anyone else at geocities.

In your scripts.js file, after setting “changeDate”, add three lines for getting, adding to, and setting
your cookie.

changeDate = new Date(document.lastModified);


visitCount = getCookie('Visits', 0);
visitCount++;
setCookie('Visits', visitCount, homePage, 365);

There are two functions in there that we have not yet seen. One is “getCookie()” and one is
“setCookie()”. We will need to create both of these.

We will also need to write this visit information to the web page. Add the following lines to the set
of writes you’re doing:

document.write('<tr><td align="right">You have visited us ', visitCount, ' time');


if (visitCount != 1) {
document.write('s');
}
document.write('</td></tr>');

If visitCount is one, we tell the viewer that they have “visited us 1 time”. Otherwise, (for example,
they’ve visited us four times) we tell them that they have “visited us 4 times”. We write the “s” in
“times” only if visitCount is not 1.

Now on to our cookie functions. Our first function will get the cookie. If there is no cookie (which
there won’t be, the first time we get it), it returns a pre-specified default value.
Advanced JavaScript 30

//get a cookie
function getCookie(cookieName, defaultValue) {
//see if the cookie is there already
cookieName = new String(cookieName + '=');
//get a list of all cookies
allcookies = document.cookie;
cookieLoc = allcookies.indexOf(cookieName);
if (cookieLoc >= 0) {
//the viewer has been here before
cookieStart = cookieLoc + cookieName.length;
cookieEnd = allcookies.indexOf('; ', cookieStart);
if (cookieEnd == -1) {
cookieEnd = allcookies.length;
}
cookieValue = allcookies.slice(cookieStart, cookieEnd);
cookieValue = unescape(cookieValue);
} else {
cookieValue = defaultValue;
}
return cookieValue;
}
function getCookie(cookieName, defaultValue) {

Our function will take two arguments: the name of the cookie, and the default value if the cookie
doesn’t exist yet.

//see if the cookie is there already


cookieName = new String(cookieName + '=');

JavaScript gets cookies as one big string full of all the cookies (like a cookie jar…). In order to find
the cookie we want, we have to look for it. Cookies always begin with the cookie’s name and then an
“=” sign.

//get a list of all cookies


allcookies = document.cookie;

The string that has all the cookies in it can be gotten from “document.cookie”.

cookieLoc = allcookies.indexOf(cookieName);
if (cookieLoc >= 0) {
//the viewer has been here before

We use “indexOf()” to see if the cookieName exists in the cookie jar. If it does (if we get back any
number zero or greater), then the cookie exists.

cookieStart = cookieLoc + cookieName.length;

The start of the cookie value will be write after the cookie’s name. So we add the length of the
cookie’s name to the start of the cookie’s name to find out where the value starts.

cookieEnd = allcookies.indexOf(';’, cookieStart);

Cookie values always end with a semicolon, and semicolons cannot be in the cookie’s value, so we
can find the end of the cookie by looking for the next semicolon after the start of the cookie value.
31 Advanced JavaScript

if (cookieEnd == -1) {
cookieEnd = allcookies.length;
}

But, oops, there is one case where the cookie value might not end in a semicolon: if it is the last
cookie value in the list. Then, the end of the value is the end of the cookie list.

cookieValue = allcookies.slice(cookieStart, cookieEnd);


cookieValue = unescape(cookieValue);

We use “slice()” to grab the cookie value from start to end, and then we “unescape” the cookie’s
value. There are special characters, such as the semicolon, that cannot appear in a cookie’s value.
When placed there, they have to be “escaped”. We unescape them with the unescape function.

Then we have the cookie’s value, so we return it to whoever called the function.

We now are able to get cookies, but we still haven’t set any.

//set a cookie that will expire in x days


//and is valid on validPath
function setCookie(cookieName, cookieValue, validPath, expiration) {
//get the current time
expirationDate = new Date();
//add the requisite number of days by converting to milliseconds
expirationDate = expirationDate.valueOf() + expiration*24*60*60*1000;
//turn it back into a date
expirationDate = new Date(expirationDate);
expires = '; expires=' + expirationDate.toGMTString();
path = '; path=' + validPath;
theCookie = cookieName + '=' + escape(cookieValue) + path + expires;
document.cookie = theCookie;
}

We are doing a little work with dates here as well as with setting cookies.

function setCookie(cookieName, cookieValue, validPath, expiration) {

Our function is called “setCookie()” and it takes four arguments: the name of the cookie, the value
that the cookie will store, the path on the server where the cookie will be returned (it will be
returned for that path and for any lower paths), and the number of days the cookie will last before
it expires.

//get the current time


expirationDate = new Date();
//add the requisite number of days by converting to milliseconds
expirationDate = expirationDate.valueOf() + expiration*24*60*60*1000;
//turn it back into a date
expirationDate = new Date(expirationDate);

We get the current time by asking for a new date. Then, we take the value of the date in
milliseconds—that is, the number of milliseconds since the start of time on this computer—and add
Advanced JavaScript 32

a day’s worth of milliseconds for every day we want this cookie to last. We then turn the variable
back into a date by asking for a new date again, but this time given it our new number of
milliseconds to create the date from. We now have a date that is the correct number of days in the
future.

As a side note, remember that for this to work, the date on both the server and on the client must
be correct. If one is off, cookies will expire before they are supposed to. Dates and times are
extremely important to modern computers. Always set yours to a trusted central time server. See
your computer’s “Date & Time” control for more information about how to do that automatically.

expires = '; expires=' + expirationDate.toGMTString();

The cookie is made up of parts separated by semicolons. Our expiration date will be a semicolon, a
space, the word “expires”, an “=” sign, and then the expiration date in universal time.

path = "; path=" + validPath;

Similarly, the path is a semicolon, the word “path”, an “=” sign, and the path.

theCookie = cookieName + "=" + escape(cookieValue) + path + expires;

We construct the cookie by placing the cookie’s name, the “=” sign, and the escaped cookie value
(remember above where we unescaped the value?) in front of the path and the expiration date.

document.cookie = theCookie;

Finally, we give the cookie back to the document. You might expect that the above line would erase
all current cookies and replace them with our single cookie, but this is a special case. JavaScript
takes the cookie we’re giving it and adds it to the list of cookies. If the cookie we’re giving it already
exists, it replaces that cookie, but does not erase any other cookies.
See an example of this script in action at
http://www.hoboes.com/NetLife/Web_Scripting/lessons/lesson14.html. Click reload to see the
number increase by one. Remember that you’ll need to have cookies turned on in order to see it!

For an additional exercise, try storing the document’s last modification date in a cookie, and then
let the viewer know if the document has been modified since they last visited.
33 JavaScript Issues

JavaScript Issues
It might not be there
Not all browsers have JavaScript. Some non-visual browsers won’t use it. And you cannot rely on
JavaScript existing even in visual browsers. Even if the viewer leaves JavaScript turned on in their
browser, there’s a very good chance that some functionality will be turned off. Mostly, this is
because JavaScript is commonly abused by scammers.

Many people have pop-up blocking turned on, for example, so that they don’t get advertisements
popping up on their computer; most browsers have this option built-in because the problem is so
widespread.

Some browsers let the user choose exactly what JavaScript functionality to allow, from the ability to
resize windows on.

When going over this tutorial in early 2007, I discovered that the very simple first example didn’t
function at all in two out of three of the then-major browsers. I’d chosen setting the text in the
status bar as the first example because it required only a single line and because its result was so
obvious. No longer; most likely the functionality was abused by phishing sites. As far as I can tell,
the ability to see changed status text is no longer available in most browsers.

Browsers will also attempt to detect whether your script is consuming too many resources on the
client computer. If the browser detects this, it will either automatically stop your script, or present
the viewer with a dire warning that the script is likely doing something wrong, and do they want to
cancel? Most likely they will.

Trusting JavaScript
You cannot trust JavaScript at all. Not only can the viewer turn JavaScript off, but they can also
change it. A JavaScript file is just like a web page: it gets downloaded to the client computer and
then “displayed”. The viewer has full control over the file since it is on their computer, and
malicious users can take advantage of this if you trust the “output” of JavaScript.
JavaScript Issues 34

JavaScript should be used to assist the user, not to assist the server (or the webmaster). It should
not be used to perform authentication, nor should it be used to calculate things that are then stored
on the server. You would never want to calculate prices using JavaScript and then charge a
customer based on that calculation, for example: you’ll end up giving some people a pretty hefty
discount when they realize they can manipulate the calculation themselves. This does not mean
that you cannot use JavaScript to show the viewer a quick summary of their prices or shopping cart
total. It just means that you should, once they submit their purchase, calculate the prices on your
end as well. Remember that on the Internet, it only takes one person to take advantage of security
flaws in your web site.

JavaScript is a great feature for making your web pages easier to use. But it should not be used in
place of server-side programming. Your pages should always be accessible to people who do not use
JavaScript (it is difficult to imagine what a JavaScript would look like through a translator or a
voice reader, for example), and you should not rely on the JavaScript calculations coming to your
end intact and trustworthy.

Different Versions
Different web browsers, and different versions of web browsers, will often treat the same
JavaScript slightly differently. This will be more of an issue the more complex your JavaScript
becomes. Try to keep your JavaScript standard, try to test on a wide variety of browsers and
versions, and make sure your web pages work if your viewers end up having to turn JavaScript off
to bypass inadvertent bugs in your JavaScript. Remember that just because your code works now,
there is no guarantee that it will work with tomorrow’s browsers. Keep things simple, and
especially try not to “take advantage” of bugs in a browser’s JavaScript implementation. Someday
that bug will probably get fixed.

Managing Your Script Files


If you look at other people’s web pages, you’ll notice that sometimes they’ll put JavaScript right
inside their web pages, instead of putting it into a separate file as we’ve done here. I recommend
against this. By putting your JavaScript into a separate JavaScript (.js) file, you can call the same
file from different web pages. If a new browser version necessitates changing your JavaScript code
to overcome a new bug, you’ll be able to make the change once, instead of looking for all the web
pages you’ve used something like that code in. You’ll always miss at least one.
35 JavaScript Issues

Separating your JavaScript into its own file also makes it much harder for your JavaScript to
interfere with your HTML in browsers that don’t implement JavaScript, or don’t implement it the
way you expect it to work.

You can put more than one <script src="…"> in your web pages, to reference more than one set of
JavaScripts. Just make sure your JavaScript functions all have unique names.
Programming Tips 36

Programming Tips
Describe Your Goal
Write down what you wish to accomplish. Then break it down into smaller parts. Try to find the
simplest part, and implement just that part. If you can’t get that simple part to work, see if you can
break it down into even simpler parts.

If you can’t break it down any further, move on to the next problem. Perhaps by the time you finish
the problem you can solve, you’ll have some insight into the related problem that you couldn’t.

Test Often
Learn to love your browser’s reload button. Whenever you make a change that might affect your
web page, test immediately. Don’t make a whole bunch of changes before testing; if your web page
no longer works, you won’t necessarily know which change caused it to fail. Write your programs a
step at a time and test often.

Test things that you don’t even expect to happen: try to think up weird scenarios and come up with
a means of testing what happens to your page under those scenarios. This will give you valuable
information about what your code is really doing.

Also, make extensive use of the “window.alert()” function to let you know the value of variables at
troublesome points.

Centralize Your Code


You should almost never repeat the same basic code more than once. If you need the same routine
a second time, seriously consider moving it into a subroutine.

For example, if you wanted to put the date into your “Current Time:” line, we already have the code
that creates a date. Unfortunately, if you call it directly you’ll end up with “Today” as the string,
because that’s what that subroutine does. Rather than duplicating the portion of the code that
creates the actual date, move it out of the “formatDate()” subroutine. Call it something like
37 Programming Tips

“makeDate()”. Then, you can call that subroutine both from “formateTime()” and from
“formatDate()”.

Another example might be the code we used for prepending a zero to numbers that are smaller
than 10. We probably should have created a subroutine that would do that for us, and then call that
subroutine every time we need to prepend zeros.

But consider the things you might want to do with a subroutine at the moment you create it. Might
we want to prepend something other than zeros? Might we want to pad to three or even four
characters instead of just to two? An appropriate subroutine might be called with “thishour =
leftpad(thishour, "0", 2);” to ensure that “thishour” has at least two characters, and prepend a zero
if it does not. One could then use “indexline = leftpad(pagenumber, ".", 4);” to prepend periods and
ensure four characters in the “indexline” string. The function might look something like:

function leftpad(theItem, thePad, minSize) {


newItem = new String(theItem);
while (newItem.length < minSize) {
newItem = thePad + newItem;
}
return newItem;
}

Avoid the Hammer Syndrome


Once you have a hammer, all problems start to look like nails. It can be easy, once you start
programming JavaScript, to look at every web page problem as a problem with a JavaScript
solution. Look for simpler HTML solutions first. HTML is faster and more reliable than JavaScript,
and will last longer.

Some problems will have to be solved with server-side programming, either using server-side
includes or server-side programming such as with Perl or PHP. Trying to solve these problems with
client-side JavaScript is prone to errors, sometimes dangerous ones if money or privacy is involved.
Programming Tips 38

More Information
The two most useful books I’ve seen for JavaScript webmasters are Webmaster in a Nutshell, which
is simply a useful reference for all sorts of webmaster information, and JavaScript: The Definitive
Guide (http://www.hoboes.com/Books/javascript.shtml), by David Flanagan. You’ll find links to
both of these on my Recommended Software page at
http://www.hoboes.com/NetLife/NSpace/software.shtml.

Thanks go to Joy Brunetti (http://www.sandiego.edu/~brunetti/) for testing out the sample scripts
and being the first guinea pig!

“The best book on programming for the layman is Alice in Wonderland; but that’s because it’s the best book on
anything for the layman.”
39 GNU Free Documentation License

GNU Free Documentation License


Version 1.1, March 2000

Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is
permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

0. Preamble
The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure
everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered
responsible for modifications made by others.

This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense.
It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the software does. But this License is not limited to software
manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is instruction or reference.

1. Applicability and Definitions


This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed
under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee,
and is addressed as "you".

A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of
the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could
fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may
not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or
of legal, commercial, philosophical, ethical or political position regarding them.

The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the
notice that says that the Document is released under this License.

The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says
that the Document is released under this License.

A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to
the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images
composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to
text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise
Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not
Transparent. A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format,
SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque
formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or
XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some
word processors for output purposes only.
GNU Free Documentation License 40

The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

2. Verbatim Copying
You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add
no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or
further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you
distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

3. Copying in Quantity
If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts,
you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and
Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The
front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the
covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these
conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably)
on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable
Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network
location containing a complete Transparent copy of the Document, free of added material, which the general network-using public
has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must
take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will
remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or
through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies,
to give them a chance to provide you with an updated version of the Document.

4. Modifications
You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you
release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing
distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the
Modified Version:
1. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous
versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a
previous version if the original publisher of that version gives permission.
2. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the
Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has
less than five).
3. State on the Title page the name of the publisher of the Modified Version, as the publisher.
4. Preserve all the copyright notices of the Document.
5. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.
6. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version
under the terms of this License, in the form shown in the Addendum below.
7. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license
notice.
41 GNU Free Documentation License

8. Include an unaltered copy of this License.


9. Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document,
create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item
describing the Modified Version as stated in the previous sentence.
10. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and
likewise the network locations given in the Document for previous versions it was based on. These may be placed in the
"History" section. You may omit a network location for a work that was published at least four years before the Document
itself, or if the original publisher of the version it refers to gives permission.
11. In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all the
substance and tone of each of the contributor acknowledgements and/or dedications given therein.
12. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the
equivalent are not considered part of the section titles.
13. Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version.
14. Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section.
If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to
the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of
a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end
of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added
by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously
added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace
the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert
or imply endorsement of any Modified Version.

5. Combining Documents
You may combine the Document with other documents released under this License, under the terms defined in section 4 above for
modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents,
unmodified, and list them all as Invariant Sections of your combined work in its license notice.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a
single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section
unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a
unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined
work.

In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled
"History"; likewise combine any sections entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all
sections entitled "Endorsements."

6. Collections of Documents
You may make a collection consisting of the Document and other documents released under this License, and replace the individual
copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the
rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that
document.
GNU Free Documentation License 42

7. Aggregation with Independent Works


A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a
storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation
copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other
self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative
works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one
quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the
aggregate. Otherwise they must appear on covers around the whole aggregate.

8. Translation
Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a
translation of this License provided that you also include the original English version of this License. In case of a disagreement
between the translation and the original English version of this License, the original English version will prevail.

9. Termination
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other
attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so
long as such parties remain in full compliance.

10. Future Revisions of this License


The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such
new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See
http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of
this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified
version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not
specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software
Foundation.

You might also like