Begin To Code With JavaScript - Rob Miles
Begin To Code With JavaScript - Rob Miles
com
Begin to Code with JavaScript
Rob Miles
OceanofPDF.com
BEGIN TO CODE WITH JAVASCRIPT
Published with the authorization of Microsoft Corporation by:
Pearson Education, Inc.
Copyright © 2022 by Pearson Education, Inc.
All rights reserved. This publication is protected by copyright, and permission must be obtained from
the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in
any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For
information regarding permissions, request forms, and the appropriate contacts within the Pearson
Education Global Rights & Permissions Department, please visit www.pearson.com/permissions
No patent liability is assumed with respect to the use of the information contained herein. Although
every precaution has been taken in the preparation of this book, the publisher and author assume no
responsibility for errors or omissions. Nor is any liability assumed for damages resulting from the use
of the information contained herein.
ISBN-13: 978-0-13-687072-2
ISBN-10: 0-13-687072-4
Library of Congress Control Number: 2021941656
ScoutAutomatedPrintCode
TRADEMARKS
Microsoft and the trademarks listed at http://www.microsoft.com on the “Trademarks” webpage are
trademarks of the Microsoft group of companies. All other marks are property of their respective
owners.
WARNING AND DISCLAIMER
Every effort has been made to make this book as complete and as accurate as possible, but no
warranty or fitness is implied. The information provided is on an “as is” basis. The author, the
publisher, and Microsoft Corporation shall have neither liability nor responsibility to any person or
entity with respect to any loss or damages arising from the information contained in this book or
from the use of the programs accompanying it.
SPECIAL SALES
For information about buying this title in bulk quantities, or for special sales opportunities (which
may include electronic versions; custom cover designs; and content particular to your business,
training goals, marketing focus, or branding interests), please contact our corporate sales department
at [email protected] or (800) 382-3419.
For government sales inquiries, please contact
[email protected].
For questions about sales outside the U.S., please contact
[email protected].
Editor-in-Chief
Brett Bartow
Executive Editor
Loretta Yates
Development Editor
Rick Kughen
Sponsoring Editor
Charvi Arora
Managing Editor
Sandra Schroeder
Senior Project Editor
Tracey Croom
Copy Editor
Rick Kughen
Indexer
James Minken
Proofreader
Scout Festa
Technical Editor
John E. Ray
Editorial Assistant
Cindy Teeters
Cover Designer
Twist Creative, Seattle
Compositor
Danielle Foster
Graphics
Danielle Foster
OceanofPDF.com
To Imogen
OceanofPDF.com
About the author
Rob Miles spent more than 30 years teaching programming at the
University of Hull in the United Kingdom. He now runs a company
promoting community uptake of computer technology. He’s a Microsoft
MVP with a passion for programming and creating new things. If he had
any spare time, he’d spend it writing even more code. He loves building
devices and then switching them on to see what they do. He reckons that
programming is the most creative thing you can learn how to do. He claims
to know a lot of really good jokes, but nobody has ever heard him tell one.
If you want an insight into the Wacky World™ of Rob Miles, you can read
his blog at www.robmiles.com and follow him on Twitter via @RobMiles.
OceanofPDF.com
Contents at a glance
Part 1: The world of JavaScript
Chapter 1 Running JavaScript
Chapter 2 Hypertext Markup Language (HTML)
Chapter 3 Cascading Style Sheets (CSS)
OceanofPDF.com
Contents
Introduction
1 Running JavaScript
What is JavaScript?
JavaScript origins
JavaScript and the web browser
Our first brush with JavaScript
Tools
Getting Git
Getting Visual Studio Code
Getting the sample files
Working on files with Visual Studio Code
What you have learned
7 Creating functions
What makes a function?
Give information to functions
Arguments and parameters
Multiple parameters in a function
Using references as function arguments
Arrays of arguments
Returning values from function calls
Add error handling to an application
Local variables in JavaScript functions
What you have learned
8 Storing data
Collections of data
Ice Cream Sales
Creating an array
Processing data in an array
Build a user interface
Arrays as lookup tables
Creating fixed with layouts
What you have learned
9 Objects
Make a tiny contacts app
Prototype HTML
Prototype style sheet
Prototype JavaScript
Storing contact details
Finding contacts
Displaying contacts
Saving a contact
Finding a contact
Use an object to store contact details
Use an object in the Tiny Contacts program
Store data in JavaScript local storage
Use JSON to encode object data
Use property accessors
Use a data schema
Build HTML from a schema
Build a data object from a schema
Improving the user interface
Add “Super Search” to Tiny Contacts
What you have learned
10 Advanced JavaScript
Manage errors with exceptions
Catching exceptions
Class design
Fashion Shop application
Object-oriented design
Store data in a class hierarchy
Add a method to give an object a behavior
Overriding methods in subclasses
Static class members
Data storage
Build a user interface
Exploring the Fashion Shop application
What you have learned
11 Creating applications
Data analysis
Fashion Shop stock list
Fashion Shop data analysis
Work with array methods
Read the weather
Fetch data from a server
Node.js
Create a web server with Node.js
Node package manager
Deploying a Node.js server
What you have learned
12 Creating games
Use the HTML Canvas
Canvas coordinates
Computer art
Draw images on a canvas
Animate images
Control gameplay
Window events
Control object position with a keyboard
Use keydown and keyup events
Create game objects
Game sprites
The game object
Starting the game
Add a cheese sprite
Add a Cracker sprite
Add lots of crackers
Catch the crackers
Add sound
Adding scores
Add a killer tomato
Create timed sprites
Complete the game
Add a start screen
Start the game running
What you have learned
Index
OceanofPDF.com
Introduction
Programming is the most creative thing you can learn how to do. Why? If
you learn to paint, you can create pictures. If you learn to play the violin,
you can make music, but if you learn to program, you can create entirely
new experiences (and you can make pictures and music, too, if you want).
Once you’ve started on the programming path, there’s no limit to where you
can go. There are always new devices, technologies, and marketplaces
where you can use your programming skills.
Think of this book as your first step on a journey to programming
enlightenment. The best journeys are undertaken with a destination in mind,
and the destination of this journey is “usefulness.” By the end of this book,
you will have the skills and knowledge to write useful programs and make
them available to anyone in the world.
But first, a word of warning: I would not say that learning to write programs
is easy. This is for two reasons:
If I tell you that it’s easy, and you still can’t do it, you might feel bad about
this (and rather cross with me).
If I tell you it’s easy and you manage to do it, you might think that it isn’t
worth doing.
Learning to program is not easy. It’s a kind of difficult that you might not
have seen before. Programming is all about detail and sequencing. You
must learn how the computer does things and how to express what you want
it to do.
Imagine that you were lucky enough to be able to afford your own personal
chef. At the start, you would have to explain things like, “If it is sunny
outside, I like orange juice and a grapefruit for breakfast, but if it is raining,
I’d like a bowl of porridge and a big mug of coffee.” Occasionally, your
chef would make mistakes. Perhaps you would get a black coffee rather
than the latte that you wanted. However, over time, you would add more
detail to your instructions until your chef knew exactly what to do.
A computer is like a chef who doesn’t even know how to cook. Rather than
saying “make me a coffee,” you would have to say, “Take the brown
powder from the coffee bag and add it to hot water.” Then you would have
to explain how to make hot water and how you must be careful with the
kettle and so on. This is hard work.
It turns out that the key to success as a programmer is much the same as for
many other endeavors. To become a world-renowned violin player, you will
have to practice a lot. The same is true for programming. You must spend a
lot of time working on your programs to acquire code-writing skills.
However, the good news is that just as a violin player really enjoys making
the instrument sing, making a computer do exactly what you want turns out
to be a very rewarding experience. It gets even more enjoyable when you
see other people using programs that you’ve written and finding them
useful and fun to use.
Yes, the best way to learn things is by doing, so you’ll find “Make
Something Happen” elements throughout the text. These elements offer
ways for you to practice your programming skills. Each starts with an
example and then introduces some steps you can try on your own.
Everything you create will run on Windows, macOS, or Linux.
CODE ANALYSIS
If you don’t already know that programs can fail, you’ll learn this hard
lesson soon after you begin writing your first program. To help you deal
with this in advance, I’ve included “What Could Go Wrong” elements,
which anticipate problems you might have and provide solutions to those
problems. For example, when I introduce something new, I’ll sometimes
spend some time considering how it can fail and what you need to worry
about when you use the new feature.
PROGRAMMER’S POINTS
I’ve spent a lot of time teaching programming, but I’ve also written
many programs and sold a few to paying customers. I’ve learned some
things the hard way that I really wish I’d known at the start. The aim of
“Programmer’s Points” is to give you this information up front so that
you can start taking a professional view of software development as you
learn how to do it.
“Programmer’s Points” cover a wide range of issues, from
programming, to people, and to philosophy. I strongly advise you to
read and absorb these points carefully—they can save you a lot of time
in the future!
What you will need
You’ll need a computer and some software to work with the programs in
this book. I’m afraid I can’t provide you with a computer, but in the first
chapter, you’ll find out how you can get started with nothing more than a
computer and a web browser. Later, you’ll discover how to use the Visual
Studio Code editor to create JavaScript programs.
Using a PC or laptop
You can use Windows, macOS, or Linux to create and run the programs in
the text. Your PC doesn’t have to be particularly powerful, but these are the
minimum specifications I’d recommend:
A 1 GHz or faster processor, preferably an Intel i5 or better.
At least 4 gigabytes (GB) of memory (RAM), but preferably 8 GB or
more.
256 GB hard drive space. (The JavaScript frameworks and Visual
Studio Code installations take about 1 GB of hard drive space.)
There are no specific requirements for the graphics display, although a
higher-resolution screen will enable you to see more when writing your
programs.
Using a Raspberry Pi
If you want to get started in the most inexpensive way possible, you can use
a Raspberry Pi running the Raspbian operating system. This has a
Chromium-compatible browser and is also capable of running Visual Studio
Code.
Downloads
In every chapter in this book, I’ll demonstrate and explain programs that
teach you how to begin to program—and you can then use that code to
create programs of your own. I’ve made a few video walkthroughs for some
crucial tasks. The book text will contain screenshots that you can use, but
these can go out of date. Follow the links to the walkthroughs to get the
latest steps to follow. You can download the book’s sample code and video
walkthroughs from the following page:
MicrosoftPressStore.com/BeginCodeJavaScript/downloads
Follow the instructions you’ll find in Chapter 1 to install the sample
programs and code. You’ll discover how to use GitHub to make your own
copy of the sample programs. You can then use GitHub to publish
JavaScript-enabled web pages for anyone in the world to view. You will
need to connect to the Internet and create a free GitHub account to do this.
You can browse the GitHub site and all the examples here:
www.begintocodewithjavascript.com
Video walkthroughs
You can also find the walkthroughs here:
https://bit.ly/3wEn6zX
Acknowledgments
Thanks to Mary for the cups of tea and Immy for the distraction.
Errata, updates, and book support
We’ve made every effort to ensure the accuracy of this book and its
companion content. You can access updates to this book—in the form of a
list of submitted errata and their related corrections—at
MicrosoftPressStore.com/BeginCodeJavaScript/errata
If you discover an error not already listed, please submit it to us at the same
page.
For additional book support and information, please visit
http://www.MicrosoftPressStore.com/Support
Please note that product support for Microsoft software and hardware is not
offered through the previous addresses. For help with Microsoft software or
hardware, go to
http://support.microsoft.com
Stay in touch
Let’s keep the conversation going! We’re on Twitter:
http://twitter.com/MicrosoftPress
OceanofPDF.com
Part 1
The world of JavaScript
We are going to start our journey by looking at the world of JavaScript.
We’ll begin by considering just what it is that a programming language
does. Then we’ll investigate the JavaScript programming language and
discover how JavaScript programs get to run on your computer. We’ll learn
how web pages provide an environment for JavaScript and how to use
Hypertext Markup Language (HTML) and Cascading Style Sheets (CSS) to
create containers for our JavaScript programs. We’ll discover just how
powerful modern web browsers are as software development tools and how
to have a conversation with JavaScript from within a browser. We’ll also
learn how to manage our software source code and share it with others.
OceanofPDF.com
1
Running JavaScript
What you will learn
Programmers have a set of tools and techniques they use when they create
programs. In this chapter, you’re going to discover how JavaScript
programs run on a computer. You’ll also have your first of many
conversations with the JavaScript command prompt and investigate your
first JavaScript program. Finally, you’ll download the Git and Visual Studio
Code tools and the example programs for this book and do some simple
editing.
What is JavaScript?
Our first brush with JavaScript
A web page with secrets
Tools
Install Git
Install Visual Studio Code
Clone the sample repository
Edit the secret program
What you have learned
What is JavaScript?
Before we go off and look at some JavaScript, it’s worth considering just
what we are running. JavaScript is a programming language. In other
words, it’s a language that you use to write programs. A program is a set of
instructions that tells a computer how to do something. We can’t use a
“proper” language like English because “proper English” is just too
confusing for a computer to understand. As an example, I give you the
doctor’s instructions:
Click here to view code image
"Drink your medicine after a hot bath."
We would probably have a hot bath and then drink our medicine. A
computer would probably drink the hot bath and then drink its medicine.
You can interpret the above instructions either way because the English
language allows you to write ambiguous statements. Programming
languages must be designed so that instructions written using them are not
open to interpretation; they must tell the computer precisely what to do.
This usually means breaking actions down into a sequence of simple steps:
We can get this effect in English (as you can see above), but a programming
language forces us to write instructions in this way. JavaScript is one of
many programming languages that have been invented to provide humans
with a way of telling the computer what to do.
In my programming career, I’ve learned many different languages over the
years, and I confidently expect to have to learn even more in the future.
None of them are perfect, and I see each of them as a tool that I would use
in a particular situation, just like I would choose a different tool depending
on whether I was making a hole in a brick wall, a pane of glass, or a piece
of wood.
Some people get very excited when talking about the “best” programming
language. I’m quite happy to discuss what makes the best programming
languages, just like I’m happy to tell you all about my favorite type of car,
but I don’t see this as something to get worked up about. I love JavaScript
for its power and the ease with which I can distribute my code. I love
Python for its expressiveness and how I can create complex solutions with
tiny bits of code. I love the C# programming language for the way it pushes
me to produce well-structured solutions. I love the C++ programming
language for the way that it gives me absolute control of hardware
underneath my program. And so on. JavaScript does have things about it
that make me want to tear my hair out in frustration. But that’s true of the
other languages, too. And all programming languages have things about
them I love. But most of all, I love JavaScript for the way that I can use it to
pay my bills.
PROGRAMMER’S POINT
The best programming language for you is the
one that pays you the most
I think it is very fitting that the first programmer’s point is one that has
a strong commercial focus. Whenever I get asked which is the “best”
programming language, I always say that my favorite language is the
one that I get paid the most to use. It turns out that I’ll write in any
programming language if the price is right.
I strongly believe that you can enjoy programming in any language, and
that includes JavaScript. Conversely, you can have a horrible time
writing bad programs in any language. The language is just the medium
which you use to express your ideas.
So, if you tell someone that you’re writing JavaScript programs and they
tell you that it’s not a very good programming language for reasons that you
don’t understand, just show them how many jobs there are out there for
people who can write JavaScript code.
JavaScript origins
You might think that programming languages are a bit like space rockets in
that they are designed by white-coated scientists with mega-brains who get
everything right the first time and always produce perfect solutions.
However, this is not the case. Programming languages have been developed
over the years for all kinds of reasons, including ones like, “It seemed a
good idea at the time.”
JavaScript was invented by Brendan Eich of Netscape Communications
Corporation and first appeared in a Netscape web browser that was released
at the end of 1995. The language had a variety of names before the
company decided on JavaScript. It turned out to be a poor choice of name
because it makes it easy to confuse JavaScript with the Java programming
language, which is actually quite different from JavaScript.
JavaScript was intended as a simple way of making web pages interactive.
Its name reflects the way that it was supposed to be used alongside Java
applications (called applets) running in a web browser. However, JavaScript
was extended beyond all the expectations of its creator and is now one of
the most popular programming languages in the world. Whenever you visit
a website, it is almost certain that you will be talking to a JavaScript
program.
This book will teach you JavaScript, but actually I’m trying to turn you into
a programmer. The fundamentals of program creation are the same for
JavaScript and pretty much all programming languages. Once you’ve
learned how to write JavaScript, you’ll be able to transfer this skill into
many other languages, including C++, C#, Visual Basic, and Python. It’s a
bit like the way that once you have learned to drive, you can drive any
vehicle. When you are using a strange car, you just need to find out where
the various switches and controls are, and then you can set off on your
journey.
http://www.begintocodewithjavascript.com/hello
This looks like a very ordinary web page, but it holds a secret behavior
that you can find by pressing the F12 key on your keyboard. Figure 1-2
shows the Developer View.
This is called Developer View. It shows all the elements that make up the
web page. A complete description of everything you can do in this view
would not fit in this book. Don’t be worried about how complicated it all
looks, we are only going to use a couple of the features. We are going to
start by looking at the elements that make up the text on the page. Make
sure that the Elements tab is selected as you can see in Figure 1-2. Then
look at the text underneath, which is shown in Figure 1-3.
Figure 1-3 Page elements
Figure 1-3 shows the elements on this page. You can see that the text
that appears on the page is here. Parts of the text are enclosed in what
look like formatting instructions, for example some is marked as <h1>
and some as <p>. If you look back at the web page as displayed you will
notice that the <h1> text is in a large heading font, whereas the <p> text is
in smaller text. This is how pages are formatted. You can see how the
page works, but where is the secret? To answer this, click the right-
pointing arrowhead at the left of the word script to open this part of the
view (see Figure 1-4).
Figure 1-4 doAddition function
Clicking the arrow opens that part of the listing. The hidden feature is a
function called doAddition. This takes two numbers, adds them together,
and displays the result using an alert. Later in the text, we will go into
detail of how this JavaScript works, but even at this stage, it is quite
clear what is going on.
However, this function is never actually used in the web page. We can
use it ourselves by entering it into the JavaScript console, which is built
into the browser. This performs JavaScript statements that you type in.
You can open the console by selecting the Console tab at the top of the
window (see Figure 1-5).
Figure 1-5 JavaScript console
This is the Console window. I’ve typed in the name of the function and
given it two numbers to work on. When the function runs it display an
alert with the result it has calculated, as shown in Figure 1-6.
CODE ANALYSIS
Talking to JavaScript
We can learn a little about the way JavaScript works by giving the
JavaScript console some commands and considering the responses.
> 2+3
This looks like a sum, and as you might expect, you get a number for an
answer
<-5
> 6-5
<- 1
JavaScript seems quite happy when we ask it to do sensible things. Now,
let’s try asking it to do something stupid. What do you think would
happen if we tried to subtract one string from another using the
following statement?
<- NaN
The JavaScript console is not calling for grandma to come and sort the
problem out. The value NaN means “not a number”. It is a way that
JavaScript indicates that the result of a calculation has no meaning.
Some programming languages would display an error message and stop
a program if you tried to use them to subtract one string from another.
JavaScript does not work like this. It just generates a result value that
means “this result is not a number” and keeps going. We will consider
how to a program can manage errors like this later in the text.
And because we are talking about errors, how about asking JavaScript to
do some silly math:
> 1/0
When I got my first pocket calculator, the first thing I tried to do with it
was calculate one divided by zero. I was richly rewarded by a result that
just kept counting upward. What do you think JavaScript will do?
<- Infinity
JavaScript says that the result of the calculation is the value Infinity.
This is another special value that is generated by JavaScript when it does
calculations. Talking of calculations, how about asking JavaScript to do
another one for us?
> 2/10+1/10
<- 0.30000000000000004
This number is very, very close to 0.3 (the correct answer), but it is ever-
so-slightly larger than it should be. This illustrates an important aspect of
the way that computers work. Some values that we can express very
easily on paper are not held exactly by the machine. This is only usually
a problem if we start performing tests with the values that we calculate,
such as a check to see if the calculated result above was equal to the
value 0.3 might fail because of the tiny difference. Let’s see if we can
use JavaScript to do some things for us. How about this?
This is how the doAddtion function displays the result it has calculated.
Finally, let’s try another function called print:
> print()
What you will see next depends on the computer and the browser that
you are using, but you should see a print window appear, which offers
you the chance to print the web page. If you’ve ever wondered what
happens when you press the Print button on a web page, you know now.
Congratulations. You now know how web pages work. Your browser
fetches a file from the server and then follows the instructions in that file to
build a page for you to look at. The file contains text that is to be displayed
on the page, along with formatting instructions. A page file can also contain
JavaScript program code.
The instructions that the browser follows are expressed in a language called
Hypertext Markup Language (HTML). In the next chapter, we’ll take a
detailed look at HTML, but before we do that, we need to get some tools
that will let us fetch the sample code for this book onto our computer and
work with HTML and JavaScript.
Tools
You will need some software tools to get the best out of the exercises in this
book. We are going to start with two, a program called Git that will manage
the program files that we work on and a program called Visual Studio Code,
which we will use to work on the files. Neither of these will cost you any
money, and they are available for Windows, macOS, and Linux. You can
follow through the printed instructions below, or you can use one of my
video walkthroughs that you can find here:
https://www.begintocodewithjavascript.com/media
PROGRAMMER’S POINTS
Git and Visual Studio Code are professional
tools
When you learned to ride a bike, you probably had one with training
wheels. And people learning to drive a car usually start in something
small and easy to handle. You are learning programming with the tools
that professionals work with. This is a bit like learning to drive using a
Formula 1 racing car. However, there is nothing to worry about here. A
Formula 1 car might look a bit scary, but it still has a steering wheel and
the usual set of pedals. And you don’t have to drive it fast if you don’t
want to.
GitHub and Visual Studio code have a huge range of features, but you
don’t have to use them. Just like there are buttons on my car dashboard
that I don’t press because I’m not sure what they do, you don’t have to
know about every feature of these tools to make good use of them.
It is very sensible to start developing with “proper” tools because job
recruiters are often as interested in the tools that you are familiar with
as they are with the programming languages that you can work with.
Getting Git
The source code of programs that you write is stored on your computer as
files of text. These files are called “source code”. You work on your
programs by changing the contents of these files. When I was starting out
programming, I learned very quickly that you can go backward as well as
forward when writing software. Sometimes, I would spend a lot of time
making changes to my programs that would turn out to be a bad idea, and I
would have to go back and undo them all. I solved this problem by making
copies of my program code before I did any major edits. That way, if
anything went bad, I could go back to my original files.
Lots of other programmers noticed this problem, too. They also noticed that
if you release a program to users, it is very useful to have a “snapshot” of
that code so that you can keep track of any changes that you make. The best
programmers are great at being “intelligently lazy,” so they created source
code management (SCM) software to manage this. One of the most popular
programs is called Git.
Git was created in 2005 by Linus Torvalds who was writing the Linux
operating system at the time. He needed at tool that could track what he was
doing and make it easy for him to work with other people. So, he created
his own. Git is a professional tool and very powerful. It lets large numbers
of developers work together on a single project. Different teams can work
on their own versions of the code, which can them be merged. There is no
need for you to use all of these powerful features, though. You’re just going
to use Git to keep track of our work and as a way of obtaining the example
programs.
https://git-scm.com
Figure 1-8 Git installation page
https://code.visualstudio.com/Download
Click the version of Visual Studio Code that you want and follow the
instructions to install it. Once it is installed, you will see the start page
shown in Figure 1-10.
Figure 1-10 Visual Studio Start page
Now that you have Visual Studio installed, the next thing you need to do
is fetch the sample files to work on.
https://github.com/begintocodewithjavascript/begintocodewithjavascript.
github.io
If you visit this URL with your browser, you will find that you can
navigate all the files, including the file hello.html, which we
investigated earlier, and take a look at what is inside them. See Figure 1-
11.
Figure 1-11 Repository home page
You can see that GitHub is keeping track of the changes that I have made
to the example programs. We are going to use Visual Studio Code to
clone this repository. Start Visual Studio Code and click the Source
Control button, as shown in Figure 1-12.
Figure 1-12 Visual Studio Source Control button
This opens the Source Control dialog, as shown in Figure 1-13. Next,
click the Clone Repository button to begin the process of fetching a
repository from GitHub.
Figure 1-13 Visual Studio Code source clone repository
Visual Studio code will download the contents of the repository and
store them on your machine. Enter the URL of the repository in the
dialog that appears:
https://github.com/begintocodewithjavascript/begintocodewithjavascript.
github.io
When you press Enter at the end of the URL, as shown in Figure 1-14,
you will be asked where on your computer you want to put the files that
are about to be copied. I suggest that you create a folder named GitHub
in your Documents folder and use that, but you can put the repository
anywhere you like. Once you’ve selected the folder, Visual Studio will
copy all the files in the repository from the GitHub site to your computer.
For now, you are just going to look in the hello.html file, so click the
hello.html file name in the Explorer to open it (see Figure 1-16).
Once the page has opened, you can make some changes to the text in the
file. I’ve changed one heading so that it reads “Hello from Rob.” You
can save the file by holding down the Control key (Command key on
macOS) and pressing S (CTRL+S). Or you could use the Save command
in the File menu. Either way, you now want to view the changed file in a
browser to see if the changes have worked.
When you cloned the repository, you told Visual Studio Code where to
put the files, so now is the time to open File Explorer and navigate to
that folder. If you’ve forgotten where you put the files, you can find out
just by hovering your mouse pointer over the file name in Explorer.
Visual Studio Code will then show you the path to that file (see Figure
1-17).
Figure 1-17 Finding the hello.html file
Now you will see the file in all its edited glory. Note that the address
being browsed is now a file on your local storage, rather than on the
web. Note also that you can press F12 if you like and view the contents
of the file, just like we did at the start of this chapter.
OceanofPDF.com
2
Hypertext Markup Language
(HTML)
This URL specifies that the site uses the secure version of the hypertext
transfer protocol, that the address of the host server is
begintocodewithjavascript.com, and that the path to the file containing the
web page is hello.html. If you leave off the path, the server will deliver the
contents of a default file which might be called index.html or Default.htm or
some other name, depending on how the server has been set up.
When the user requests a website, the browser sends a message to the server
to request the page. This message is formatted according to the Hypertext
Transport Protocol (HTTP) and is often called a “get” request (because it
starts with the word GET). The server then sends a response that includes a
status code and then, if it is available, the text of the web page itself is sent.
If the page cannot be found on the server (perhaps because the URL was not
given correctly), the HTTP status code results in the familiar “404 page not
found” message. We will learn more about this process later in the book
when we write some JavaScript code that gets web pages.
What is HTML?
This is not a guide to HTML. You can buy whole books that do a very
thorough job of describing the language and how it is used. But you should
finish this section with a good understanding of the fundamentals. HTML is
a markup language. Markup is what the “M” in HTML stands for. The word
“markup” comes from the printing profession. Printers would be given text
that had been “marked up” with instructions such as “print this part in large
font” and “print this part in italic.”
Figure 2-2 shows what happens if you don’t use a markup language
properly. In this case, the customer wanted a cake with no writing on it. The
customer said, “Please Leave Blank” when asked what she wanted written
on the cake. Unfortunately, the baker took this instruction literally.
The sequence <em> is recognized by the browser as meaning “make the text
that follows this instruction look slightly different from the other text” and
is called a tag. The browser will display emphasized text until it sees the
sequence </em>, which marks the end of the emphasized text. Most
browsers emphasize text by displaying it as italic. If we viewed the above
HTML in a Microsoft Edge, we would see something that looks like this:
Click here to view code image
This text is emphasized. This text is not.
Once you understand the fundamentals of HTML, you can use it to format
text. The HTML below shows a few more tags.
Click here to view code image
This is <em>emphasized</em><br>
This is <i>italic</i><br>
This is <strong>strong</strong><br>
This is <b>bold</b><br>
This is <small>small</small><br>
This is <del>deleted</del><br>
This is <ins>inserted</ins><br>
This is <u>underlined</u><br>
This is <mark>marked</mark><br>
The example HTML above uses a tag, <br>, that means “start on a new
line.” The <br> tag does not need to be matched by a </br> element to
“close it off.” This is because it has an immediate effect on the layout; it is
not “applied” to any specific items on the page. When I pass this text into a
browser, I get the output shown in Figure 2-3.
Figure 2-3 The <br> tag creates a new line of text.
If you look closely at the text in Figure 2-3, you will notice that some of the
requests have similar results. For example, the emphasized (<em>) and italic
(<i>) formats both produced italic output. The bold (<b>), italic (<i>), and
underline (<u>) tags are regarded as slightly less useful than the more
general ones, such as emphasized (<em>) or strong (<strong>). The
reasoning behind this is that if a display has no way of producing italic
characters a request to display something in italic is not going to work.
However, if the display is asked to “emphasize” something, it might be able
to do this in a different way, perhaps by changing the color of the text.
Output produced by HTML is intended to be displayed in a useful way on a
huge range of output devices. When you use a markup language, you should
be thinking about the effect you want to add to a piece of text. You should
think “I need to make this stand out, so I’ll use the <strong> format,” rather
than just making the text bold.
You can write the commands using uppercase or lowercase or any
combination of the two. In other words, the tags <em>, <EM>, and <Em> are all
regarded as the same thing by the browser.
Display symbols
By now, you should have a good idea how HTML works. A tag <blah>
marks the start of something. The sequence </blah> marks the end. The tags
can be nested (placed inside each other).
Click here to view code image
<em>This is emphasized <strong>This is strong and
emphasized</strong></em>
The name of the less than character (<) is lt, and the name of the greater
than (>) symbol is gt. Note that the end of a symbol name is marked by a
semicolon (;). If you are now wondering how we display an ampersand (&),
the answer is that it has the symbol name amp.
Click here to view code image
You can find a handy list of symbols and their names here:
https://dev.w3.org/html5/html-author/charref. Note that when you give a
symbol a name, the case of the names is significant.
É<br>
é<br>
The HTML above would display the uppercase (É) and lowercase (é)
versions of eacute. If you like emojis (and who doesn’t?), you can add
these to your web pages by using a symbol that includes the number of the
emoji that you want to use.
If you want to discover all the numbers that you can use to put emojis in
your web pages, take a look here: https://emojiguide.org/.
Hello
world
from Rob
The layout of this text is a bit of a mess. However, when this text is
displayed by a browser, you see the following:
Hello world from Rob
The browser takes in the original text, splits it into words, and then displays
the words with single spaces between them. Any layout information in the
source text is discarded. This is a good idea because the designer of a web
page can’t make any assumptions about the display that will be used. The
same page needs to work on large and small displays—from smartphones to
large LCD panels.
We’ve seen that the <br> sequence asks the browser to create a new line
during the display of text. Now we are going to consider some more
commands that control how text is laid out when it is displayed. The <p>
and </p> commands enclose text that should appear in a paragraph:
Click here to view code image
The <br> command is not the same as the <p> command; it does not space
the lines out like a paragraph would.
Create headings
We can use other tags to markup text as headings at different levels:
Click here to view code image
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<p>A normal paragraph</p>
<pre>
This text
is rendered
exactly how I wrote it.
</pre>
The text enclosed by the <pre> tags is displayed by the browser without any
changes to the formatting.
This text
is rendered
exactly how I wrote it.
Note that the ASCII art above contains a < character, which I had to convert
to a symbol (<) so that it is displayed correctly. This is important.
Remember that the browser will not format preformatted text, but it still
observes the character conventions that you must use to display characters
and symbols. You can add tags to the preformatted text to make parts of it
emphasized; <p> tags inside preformatted blocks of text might work, but
this is not advised because it makes your html badly formed. The logo
appears as shown in Figure 2-7.
Figure 2-7 My logo
PROGRAMMER’S POINT
Don’t abuse the browser
Browsers are generally very tolerant of badly formatted HTML. The
browser will try to display something even if the HTML it receives is
badly formatted. This means you can get away with HTML like this:
Click here to view code image
<em>Emphasized <strong>strongly emphazised</em> just strong
</strong>
The above figure shows what correct nesting looks like. Each element
ends before its enclosing one. The reason why I’m stressing this is that
most browsers can work out the meaning of the badly nested HTML
and display it correctly, but some might not. This could lead to your
web pages looking wrong to some people. I’m sure you’ve had the
experience of having to switch browsers because a particular website
doesn’t look right. Now you know how this can happen.
You can identify incorrectly nested HTML when you see an end tag that
doesn’t match the most recent start tag. If you want to use a program to
make sure that your HTML is correct, you can use the official validator
site at https://validator.w3.org/. You can point the validator at a site you
have created or paste HTML text into it for checking.
The image tag uses an attribute to specify the file that contains the image to
be displayed. An attribute is given inside the tag as a name and value pair,
separated by the equals character. When the browser finds an img tag, it
looks for the src attribute and then looks for an image file with that name.
In the case of the above HTML, the browser would look for an image called
seaside.JPG. It would look in the same place on the server from which it
loaded the web page. We must make sure that file exists on the server;
otherwise, the image will not be displayed.
You can add another attribute to an img tag that provides alternative text
that is displayed if the image cannot be found.
Now the browser will display the text “Waves crashing on an empty
beach” if the image can’t be located. The alternative text (ALT) is also
very useful for visually impaired web users who can’t see the image but
who would appreciate a text description of what is in it.
The image will be displayed in line with the text on the page. We can use
the HTML layout tags to lay an image out sensibly with the surrounding
text:
Click here to view code image
<h1>Seaside Picture</h1>
<p><img src="seaside.JPG" alt="Waves crashing on an empty
beach"></p>
<p>This picture was taken at Hornsea in the UK.</p>
The image shown in Figure 2-8 is 600 pixels wide. A pixel (short for
picture cell) is one of the dots that make up the picture. The more pixels
that you have, the better looking the picture is.
Figure 2-8 An image that is 600 pixels wide
However, this can cause problems if the picture is too large to fit on the
device being used to display the image. The img tag supports width and
height attributes that can be used to set the displayed size of an image. So,
if I want to display the image as 400 pixels wide I can do this:
Click here to view code image
<p><img src="seaside.JPG" alt="Waves crashing on an empty
beach" width="400">
Note that I didn’t specify the height, which means the browser will
automatically calculate the height that matches a width of 400 pixels. You
can specify both height and width if you like, but you need to be careful not
to make the pictures distorted. Setting the absolute width of an image using
height and width attributes looks like a good idea at first, but it can be
restricting. Remember that an underlying principle of the World Wide Web
is that a page should display in a useful way on any device. An image size
of 400 pixels might be fine for a small device, but it will appear very small
if viewed on a large TV display. In the next chapter, we will discover how
we can use style sheets to allow items on a web page to be automatically
scaled for the target device.
The browser looks for the sequence <!DOCTYPE HTML> at the start to make
sure that it is reading an HTML file. All the HTML that describes the page
is given between <html> and </html> tags. The </html> tag contains a lang
attribute that specifies the language of the page. The language "en" is
English. The <head> and </head> tags mark the start and end of the heading
of the document. The heading contains information about the content of the
page including styling information (which is discussed further in the next
chapter). The text between the <body> and </body> tags is what is to be
displayed. In other words, everything we have learned up to now goes into
the body part of the web page file.
The text in the body of the <a> tag is the text that the browser will highlight
as the link. In the example HTML above the words “this link” will be the
linkable text. This will result in text on the page that looks like this:
Click here to view code image
Click on this link to open another page.
If the reader clicks the link, the browser will open a local file—in this case,
a file named “otherpage.html”—which will be displayed. The destination
of the link can refer to a page on a completely different site:
Click here to view code image
<p>Click on <a href="https://www.robmiles.com"> this link</a>
to go to my blog.</p>
Using a button
One way to create an active web page is by using a button. This HTML
code creates a button that contains the text “Say Hello”:
Click here to view code image
<button onclick="doSayHello();">Say Hello</button>
The button is displayed in the normal flow of the text in the page, as shown
in Figure 2-9.
The button has an onclick attribute. One of the great things about
JavaScript is that most of the time, the names make sense. The onclick
attribute specifies a function that is to be used when the button is clicked. In
this case, the attribute specifies a JavaScript function called “doSayHello”.
A JavaScript function is a sequence of JavaScript statements that have been
given a name. (We will take a detailed look at functions in Chapter 8.)
Click here to view code image
function doSayHello() {
alert("Hello");
}
This function only performs a single action; it displays an alert that says
“Hello” to the user when it is called. The line of JavaScript that displays the
alert is called a statement. The end of a statement is marked by a semicolon
character. A function can contain many statements, each of which is ended
with a semicolon (;).
Click here to view code image
<!DOCTYPE html>
<html lang="en">
<head>
<title>Ch02-06 Buttons</title>
</head>
<body>
<h1>Buttons</h1>
<p>
<button onclick="doSayHello();">Say Hello</button>
</p>
<script>
function doSayHello() {
alert("Hello");
}
</script>
This is the complete HTML text of the web page. The <script> element is
at the bottom of the body of the document. The page displays the Say Hello
button, and when the button is pressed, the alert is displayed, as shown in
Figure 2-10.
Figure 2-10 Say Hello alert
The web page contains the input element, a button element that will call a
function to display the alert, and the function that uses the input text in an
alert. The user can type their own text into the input and then press the
Show Alert button to have the text displayed in an alert. Figure 2-11 shows
what the program looks like when it is used.
Figure 2-11
If you run the example, you will notice that when you press the Show Alert
button, the text you have entered in the input area is displayed in the alert.
On the right-hand side of the statement above, you can see the use of
getElementByID to get the location of the text element with the
alertInputText ID. The left-hand side of the statement creates a variable to
hold this location. The word var creates a JavaScript variable. A variable is
a named location that stores some information that the program wants to
remember.
At “Rob’s Car Rental,” I would offer to write down the location of a car for
a customer who was afraid of forgetting where their car was. I’d give them
a piece of paper with “Car Location” (the name of the “variable”) and “Bay
E6” (the value of the variable) written on it. In the JavaScript above, the
variable we are creating is called element (because it refers to an element in
the document) and the value is the location of the text input element. This
operation is called an assignment because the program is assigning a value
to a variable. An assignment operation is denoted using the equals (=)
character. (We will discuss variables in detail in Chapter 4.)
Now that the program has a variable called element that contains a
reference to the input, we can extract the text value from this element and
store it in a variable called message:
The variable called message now contains the text that was typed into the
input by the user. (Remember that we set this to “Alert!” in the HTML.)
The program can now display this text in an alert:
alert(message);
CODE ANALYSIS
The doShowAlert function
Click here to view code image
function doShowAlert() {
var element = document.getElementById("alertInputText");
var message = element.value;
alert(message);
}
Question: What would happen if you got the ID of the text element
wrong?
In JavaScript, you tend to have to go hunting for the errors that you
make. In some programming languages, you are told about errors
when they occur. In JavaScript, things tend to fail silently or just do
something that you were not expecting.
Question: What would happen if the user didn’t type any text into the
text area on the web page before pressing the button?
Answer: If you look at the HTML at the very start of this section,
you will see that the value attribute of the text tag is set to “Alert!” If
the user doesn’t replace this with their message the word “Alert!”
will be displayed.
Answer: The browser will block any activity on the web page until
you clear the alert that is displayed. When you press the button again,
the doShowAlert function would be called again. It would make two
new variables called element and message and use them to display the
appropriate message text.
The first two lines set up variables that refer to the input and output
elements. The third line gets the message to be displayed, and the fourth
puts this message onto the web page, as shown in Figure 2-12.
Press F12 to open the Developer Tools view. Select the Console tab.
Enter the following JavaScript statement:
var outputElement =
document.getElementById("outputParagraph");
outputElement.textContent = "fred";
Take a look back at the web page. You should see that the word “fred”
has appeared. By setting the value of the TextContent property of the
paragraph, we can change the text in the paragraph. A JavaScript
program can read properties as well as write them. Enter the following
statement:
This will make an alert box appear with “fred” in it (because that is the
textContent of the element referred to by outputElement). Now let’s see
what happens if we make a mistake. Try this:
Click here to view code image
outputElement.tetContent="test";
alert(outputElement.tetContent);
This will display an alert showing the value in the tetContent property,
which is the string “test.” We will discover more about creating
properties in objects in Chapter 9.
See if you can change the web page so that the name is displayed as a
heading (<h1>) rather than as a paragraph. You can use Visual Studio
Code to edit the HTML for the web page. Will you have to change the
JavaScript or the HTML?
Egg timer
We now know enough to be able to create a properly useful program. We
are going to create an egg timer. The user will press a button and then be
told when five minutes (the perfect time for a boiled egg) have elapsed. We
know how to connect a JavaScript function to an HTML button. The next
thing we need to know is how to measure the passage of time. We can do
this by using a JavaScript function called setTimeout. We have used
functions already. The alert function accepts a string that it displays. The
setTimeout function accepts two things: a function that will be called when
the timer expires and the length of the timeout. The timeout length is given
in thousandths of a second. The statement below will cause the doEndTimer
function to run one second after setTimout was called.
setTimeout(doEndTimer,1000);
Our egg timer will use two functions. One function will run when the user
presses a button to start the timer. This function will set a timer that will run
the second function after five minutes. The second function will display an
alert that indicates that the timer has completed.
Click here to view code image
function doStartTimer() {
setTimeout(doEndTimer,5*60*1000);
}
function doEndTimer() {
alert("Your egg is ready");
}
The doStartTimer function is connected to a button so that the user can start
the timer. The doEndTimer will be called when the timer completes. I’ve
added a calculation that works out the delay value. I want a five-minute
delay. There are 60 seconds in a minute and a value of 1000 would give me
a one-second delay. This makes it easier to change the delay. If we want to
make a hard-boiled egg that takes seven minutes, I just have to change the 5
to a 7. Note that the * character is used in JavaScript to mean multiply. You
will find out more about doing calculations in Chapter 4.
<body>
<h1>Egg Timer</h1>
<p>
<button onclick="doStartTimer();">Start the
timer</button>
</p>
<script>
function doStartTimer() {
setTimeout(doEndTimer,5*60*1000);
}
function doEndTimer() {
alert("Your egg is ready");
}
</script>
</body>
</html>
Let’s take a look at how the egg timer works. Find the Ch02
HTML/Ch02-09 Egg Timer folder. Double-click the file index.html in
that folder to open the page.
Click the Start The Timer button once. This version of the code only
has a 10-second delay, so after 10 seconds, you would see the alert
appear.
Click the Start The Timer button three times in succession. Wait and
see what happens. Was this what you expected? It turns out that each
time you press the button, a new timeout is created. Now press F12 to
open the Developer Tools. Enter the following code and press Enter.
What would you expect to see?
doEndTimer();
This is a call of the function that will run and display the end message.
You should see the alert appear telling you that your egg is ready. Click
OK in the alert to close it. Enter the following and press enter. What
would you expect to happen?
setTimeout(doEndTimer,3*1000);
After three seconds the alert appears, because that is the length of the
timeout. You should also have seen something else appear when the
function runs. You will also see an integer displayed. If you repeat the
setTimeout call, you will see another value displayed. It is usually one
bigger than the previous one. This number is the “ID” of timer. This can
be used to identify a timeout so that it can be canceled. We are not going
to do that, so you can ignore this value.
See if you can change the web page so that it supports multiple cooking
times. Add buttons for “Soft” (four minutes), “Normal” (five minutes),
and “Bullet” (ten minutes). You will have to add two more buttons and
two more JavaScript functions to the program.
If you want to see how I did it, open the Ch02-09 Selectable Egg Timer
file. My solution even displays the status of the timer.
The audio element includes another element called src that specifies where
the audio data is going to come from. In this case, the audio is stored in an
MP3 file named everythingSound.mp3, which is stored on the server. The
text inside the audio element is displayed if the browser does not support
the audio element. I’ve given this element an ID so that the code in the
doEndTimer function can find the audio element and ask it to play the MP3
file.
Click here to view code image
function doEndTimer() {
alarmSoundElement = document.getElementById("alarmAudio");
alarmSoundElement.play();
}
This code looks like the code in the Ch02-08 Paragraph Update example.
In that case, the getElementById method was fetching a paragraph element
to be updated. In the function above, getElementById is fetching an audio
element to be played. An audio element provides a play method that starts it
playing. The rest of the file is exactly the same as the original egg timer. If
you try this program, you will hear quite an impressive sound when your
egg is ready.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Ch02-11 Sound playback</title>
</head>
<body>
<audio controls>
<source src="everythingSound.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</body>
</html>
This is the complete source of an MP3 file playback page. If you visit the
page you will see a simple playback control, as shown in Figure 2-13.
Figure 2-13 Sound playback
This is how the playback control looks when using the Edge browser. Other
browsers will look slightly different, but the fundamental controls will be
the same. You can start the playback by pressing the play control at the far
left.
This img element displays the picture in the file seaside.JPG. A JavaScript
program can change the displayed image by modifying the src attribute of
the image and making it refer to a different image file:
Click here to view code image
var pic = document.getElementById("pageImage");
pic.src="fairground.JPG";
These two statements get a reference to the image and then set the src
attribute of the img to refer to the image fairground.jpg. This will update
the image displayed by the browser. Note that this is a repetition of a pattern
that you’ve seen several times now. A program obtains a reference to a
display element and then makes changes to it. You can find a complete
image picker program in the Ch02-12 Image Picker example.
OceanofPDF.com
3
Cascading Style Sheets (CSS)
What you will learn
In the last two chapters, you’ve learned how to use HTML to design a web
page and how to use JavaScript to add some behaviors to it. However,
you’ve probably also noticed that the web pages that you’ve been creating
don’t look much like ones on the sites you usually visit. They are lacking in
design and color. In this chapter, you’ll discover how to manage the
appearance of a web page to make it more appealing. Along the way, you’ll
pick up some important points abut JavaScript programming and make
some nifty applications and games.
Above, you can see how style is applied to a single paragraph. The first
paragraph is ordinary. The second has been styled with red text. Figure 3-1
shows how this appears on the page.
The HTML standard contains a set of color definitions that you can refer to
by name. Visual Studio Code will show you a tiny preview of the color
when you are editing the text of your code, as shown in Figure 3-2.
Visual Studio Code will also produce a color menu when you start typing a
color value into a style when you are editing your HTML source (see
Figure 3-3).
Figure 3-3 Visual Studio color selector
There are very many style settings. The interactive help in Visual Studio
will show you all the possible settings when you start typing a style
command. Style settings can be combined in a single style description by
separating them with the semicolon character. The style below would result
in a tasteful display of red text on a yellow background.
Click here to view code image
We’ve used this to make a program that responds to button clicks and
another one that runs a function after a time interval has elapsed. Now
we are going to use exactly same pattern to make a web page that
highlights text when you roll the mouse over it. You definitely seen this
used on web pages that you have visited. Take a look at the code below:
Can you work out which event we are using, and how the function
doMouseOver changes the color of the text?
The event that we are using is called onmouseover and the program is
using the style property of the paragraph to make it turn red. The
browser will call the function doMouseOver when it detects that the mouse
pointer is over the paragraph text. The function doMouseOver obtains a
reference to the paragraph and then sets the style of that paragraph to
include the color red.
Let’s take a look at how the code works in practice. Find the Ch03
HTML/ Ch03-02 Color Change on Mouse Over folder. Double-click
the index.html file in that folder to open the page. In the top-left corner,
you will see a simple page with this message: “Roll your mouse over this
paragraph.” Roll your mouse over the text and note what happens. You
should see the text turn red, which is exactly what you want, but you
should notice something else, too. Is the behavior what you want? I think
you would prefer it if the text turned back to black when the mouse was
not over the paragraph.
We have found our first bug. A bug in a program is a behavior that you
don’t want. Finding and fixing bugs is a big chunk of software
development. In this case, the bug came about because we didn’t think
through what rollover actually means. Perhaps we assumed that the
browser would restore the original color of the text when the mouse left
the paragraph, but that is not how the program works. How do you think
we can fix this?
If you want to see my fixed solution, take a look in the Ch03 HTML/
Ch03-03 Color Change on Mouse Over Working folder. This works,
but later in the text, we will discover a much easier way to create a
rollover effect.
PROGRAMMER’S POINT
Bugs are a fact of life for a programmer
You are going to have to get used to creating bugs. I’ve been
programming for many years and I still write code with bugs in. And I
expect to create many more bugs as I write more programs. The thing to
remember is that creating a bug is fine, but creating a fault is not. You
get a fault when a customer finds a bug in your program. Programmers
spot bugs by testing. Programmers make faults by not testing enough,
which leads to bugs making their way into the final product. Whenever
you make something, you need to work out how to test it. In the case of
our “paragraph highlight” program, the testing is obvious—just move
the mouse over and see what happens. When we make some bigger
programs, we’ll discover that testing can be more complex.
Note that bugs are also the result of by poor specifications. Initially, I
said that I wanted some text to change color when the mouse pointer is
rolled over it. The first version of our program did this, so you could
say it was free of bugs. It was only when we noticed that the text stayed
highlighted when the mouse moved off the text that we decided that
behavior was not what we wanted. This shows how important it is to
think through exactly what you want a program to do before you start
building it. It also shows the usefulness of “prototype” programs that
can be used to determine whether the solution does exactly what the
customer wants.
They all agree that they need a font that looks like this.
(This is called a serif font because the lines in the character design have
lines on the end.)
And they all agree that we need a font that looks like this.
(This is called a sans-serif font because it doesn’t have extra lines and
“sans” is French for “without.”)
However, the manufacturers have not agreed on the names for them. For
example, the “sans serif” font can be called “Arial” or “Helvetica.”
The style above asks for Arial, followed by Helvetica and finally sans-
serif. Most computers have a sans-serif font, so the last entry in the list acts
as a “catch all.” The first item on the list is a specific font, while the last
item on the list will be a more abstract font type. If I were picking
vegetables to have for dinner, the first item would be “chips” (a specific
dish) and the last would be “potatoes” (a general catch-all for the particular
vegetable I want). Font selection works in the same way. Note that when I
select a font family, I get the designs for bold and italic versions of the
characters in that font, too. See Figure 3-4.
Figure 3-4 Visual Studio Code font selector
We have already seen how helpful Visual Studio Code is when selecting
style colors. It also pops up suggestions for font families, which have been
arranged in a sensible way. The suggested families give a good range of
typefaces that you can use in your pages, as shown in Figure 3-5 below.
You can find the HTML code that generates this page in the example folder
at Ch03 HTML/ Ch03-04 Fonts in JavaScript.
Figure 3-5 Font examples
Figure 3-6 shows the above HTML as it would appear on the page. (You
can find the HTML code that shows these examples in Ch03 HTML/Ch03-
05 Font Sizes.)
Figure 3-6 Font sizes
Text alignment
You can also add an element to a style command to tell the browser how to
lay out the text. By default (unless you specify otherwise), your text will be
laid out with each line starting at the left-hand margin. You can add a text-
align setting to a style, as shown below and in Figure 3-7.
When a new Date object is created, it is set with the current date and
time. The variable currentDate is a reference that refers to the newly
created Date object. We’ve used references before when we created a
reference to a paragraph element in a web page that we wanted to
update. Take a look at example Ch02-08 Paragraph Update if you need
to refresh your understanding of this. We can ask an object questions by
calling methods on the reference to it. Type the following:
alert(currentDate.getHours());
This statement uses the getHours method, which is part of a Date object.
This method returns a number that contains the hours value of the date.
The statement displays this in an alert. There are also methods to get the
minutes and seconds values. Each method has a name that reflects what
it does. See if you can use them to display these time values as well.
Note that you must put the open and close brackets () after each method
name so that JavaScript knows you want to call the method. We will find
out more about making method calls in Chapter 7.
Now type in the following statements to set variables with the hours,
minutes, and seconds values that we need for the clock:
This statement creates a variable called timeString that contains the time
that we want to display. The values in the hours, mins, and secs variables
are converted into text. You can view this string using an alert:
alert(timeString);
If you check the time that appears in the alert, you will find that it is out
of date because it will have taken you a few seconds to type all these
statements. The value in currentDate is a snapshot of the date and time.
This will not be a problem in our clock program because the time values
will be displayed immediately after they have been read. We now know
how to get the time value into a string that is ready for display. The
HTML for the clock display program contains a paragraph that has the
id timePar. Type the following statements:
We’ve used this pattern of statements before. The first one creates a
variable that refers to the output element we want to use to display the
time. The second statement sets the textContent property of that element
to the contents of the timeString variable. This will cause the time to be
displayed.
The HTML for this page contains a function that does everything we
have just typed in. Type the following statement to call this function:
doClockTick()
You should see the date and time update to show the current date and
time. Press F12 to close the Developer Tools in the browser.
Answer: The commands var and new look very similar because they
seem to be associated with the creation of something, but you might
be confused about exactly what is going on. In the case of var, a
program is creating a new variable:
var age=21;
This would create a variable called age, which is set to the number 21
(which is a bit optimistic in my case).
A program uses new when it wants to make a new object. The word
new is followed by the name of the type of object that is to be created:
This creates a new variable called currentDate (that’s what var does)
and then sets this variable to refer to a Date object created using new.
So, var is used to create variables, and new is used to create objects.
<body onload="doStartClock();">
setInterval(doClockTick, 1000);
Question: Why does the time take a second to appear when the clock
starts?
Answer: If you load the example, page you will find that it takes a
second for the time to appear. For a second after the page has loaded,
the time is displayed as 0:0:0. If you think about it, this is exactly
how the program works. The setInterval function calls the function
doClockTick at one-second intervals, but this means that program
must wait for this interval to elapse before the clock is displayed.
Can you think of a way to solve this problem?
The solution is simple. The program must call doClockTick from the
doStartClock function. Since the doStartClock method is called
when the page is loaded, this will cause the display to be updated at
the start. You can find my version of this in the Ch03 HTML/Ch03-
09 Clock Quick Start folder.
Margins around text
Text on a printed page does not extend right to the edge of the paper. This
book has margins around the paragraphs. Some paragraphs (for example,
the “Code Analysis” sidebar above) have different margins from the rest of
the text. This makes the paragraphs stand out. A style can express the size of
margins around a paragraph. It can also describe a border for a paragraph.
The paragraph above has an outer margin, a border, and then “padding”
around the text inside the border.
Click here to view code image
<p style="margin: 20px;
padding: 10px;
border:1px;border-style: solid; border-color:blue;">
This is some text in a blue box.</p>
The dimensions of the margins and the border are expressed in units we
have not seen before called px, which is short for pixel.
I could have spent some time drawing a diagram to show how the margin,
border, and padding values are used to control the layout of text on a page,
but it turns out that the Edge browser will do this for me. In Figure 3-9, you
can see the developer view of the HTML above, which you can find in the
code folder Ch03 HTML/ Ch03-10 Margins. The diagram on the bottom
right of Figure 3-9 shows how the margin, border, and padding elements all
fit inside each other.
Figure 3-9 Margin display
I’ve specified the margin, border, and padding dimensions in the px unit,
which is an absolute unit that equates to a single dot on the target display.
We used these units when we specified the size of an image to be drawn on
the screen. If you are concerned with precise layout, you can use these to
lay out text and graphics exactly. The size of a px unit matches that used to
set the size of images, so you can combine text and graphics to make
precisely aligned pages. The HTML below, which you can find in the Ch03
HTML/ Ch03-11 Fixed Width Paragraphs code folder, puts an image and
a descriptive paragraph inside a blue box, as shown in Figure 3-10 below.
Click here to view code image
<p style="margin: 20px;
border:1px;
border-style: solid;
border-color:blue;
padding: 10px;
width:400px;
font-family: Arial, Helvetica, sans-serif;
text-align: justify;
">
<img src="seaside.JPG" alt="Waves crashing on a deserted
beach" width="400">
This picture was taken on New Year"s Day 2020 at
Hornsea sea front.
Hornsea is a village on the north eastern coast of England.
</p>
<head>
<title>Ch03-13 Stylesheet File</title>
<link rel="stylesheet" href="styles.css">
</head>
The HTML above shows how this works. The link element contains a rel
attribute that tells the browser the type of resource that the link relates to. In
this case, the link relates to a style sheet. The link to the file containing the
style information is specified in the href attribute. In the case of the HTML
page above, this is a local file called styles.css, which is held in the same
folder as the HTML page. However, this file could be in a different folder,
or it could even be on another server. The actual style sheet file contains the
style instructions:
Click here to view code image
p {
color: blue;
font-family:Arial, Helvetica, sans-serif;
}
PROGRAMMER’S POINT
It is a good idea to separate style from layout
A web page is made up of layout (what is on the page and where it is)
and style (how the page looks). It is very sensible to separate these
elements. I could have filled this entire book with a description of how
to style web pages, but it would not be a very good read because I’m
not very good at design. I’d much rather find a designer who is good
with fonts and colors and ask them to sort those things out. Being able
to put the styling information into a separate file means that I can
design the layout and the behavior of the application entirely apart from
the style.
Computer scientists talk about “separation of concerns” in a project,
where different people work on different parts. At the start of the
project, everyone agrees how the different components will work
together, and then they can work on just their parts. In the case of
HTML and style, I would tell the designer I was using <p>, <h1>, and
<h2> for different levels of text, and then the designer could work on the
look of these styles. Later, when we start writing larger JavaScript
programs, we will discover a way of separating the program code from
the HTML, which allows another level of separation.
Notice that this looks like the way that we modified the styling of <p>,
except that the address class has a leading dot (.) to indicate that this is a
newly created style class: .address. We can then specify that this class
provides the style of a paragraph:
Click here to view code image
<p class="address"> This is an address paragraph.</p>
We can add a class attribute to any element of text that we want to format,
but sometimes it is useful to apply a style class to multiple items. In the
case of the address style above, we would like to mark all the paragraphs in
the address that we are displaying. We could mark each paragraph
individually, but it would be nice if we could mark them all at once. The
<div> and <span> elements make this possible. They are used to create
regions to which classes can be assigned.
Click here to view code image
<!DOCTYPE html>
<html lang="en">
<head>
<title>Ch03-14 Address Style</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="address">
<p>Rob Miles</p>
<p>18 Pussycat Mews</p>
<p>London</p>
<p>NE14 10S</p>
</div>
</body>
</html>
The HTML above would format all the paragraphs of the address using the
address class because they are enclosed in a division. The div element
specifies a division in the document. Each div element marks the start and
end of a paragraph of text. This means that we can’t use a div element to set
the style of some words in a paragraph. If we want to just format part of a
paragraph using a particular style, we can use the span element.
Click here to view code image
In the example above, I want the word style to stand out from the text
because it is an HTML element name. I’ve created a class called codeInText
and used it to apply a style to the word style in the sentence. I can’t use div
in this situation because this would break the sentence over several lines.
The Ch03 HTML/ Ch03-16 Code Style with span example shows how it
works. You can put span and div elements inside each other, but it doesn’t
make much sense to put a div inside a span because this would cause
paragraph breaks in your line of text. You must, of course, make sure that
any “nesting” is properly formatted. Take a look at the Programmer’s Point
“Don’t abuse the browser” in Chapter 2 for more details on this issue.
Cascading styles
You might be wondering why they are called cascading style sheets. The
name refers to the way styles “cascade” down from one element to all the
elements it encloses. Consider the following HTML:
Click here to view code image
<!DOCTYPE html>
<html lang="en">
<head>
<title>Ch03-17 Cascading Styles</title>
</head>
<body style="color: blue;">
<p>This is an ordinary paragraph.</p>
<p style="color:red">This is a red paragraph.</p>
<p style="background: yellow;">This has a yellow background.
</p>
</body>
</html>
The document contains three style elements. The first is applied to the body
of the document. The next two are applied to elements inside the body of
the text. The body element has been styled with the color blue. The body
element encloses the two paragraph elements, so this setting cascades down
onto these paragraphs, as shown in Figure 3-11.
Figure 3-11 Cascading styles in action
The “ordinary” paragraph has blue text because of the style applied to the
enclosing body element. The red paragraph is red because the color setting
in the style for the paragraph overrides the cascading style. However, the
text with a yellow background has blue text because the style on this
paragraph does not modify the color in the enclosing one; instead, it
modifies the color of the text background. The rule is that style settings are
“inherited” from enclosing elements unless they are “overridden” in them.
PROGRAMMER’S POINT
Managing styles is all about design
As you go through this book, I want to you learn that a lot of solution
development is about making your life easier. For example, you might
have a problem if you showed your customer the solution you had built
and they told you they want shocking-pink text on an orange
background (it has been known). If you’d applied the text style to each
HTML element, this would mean you would have to work through the
entire document and make the requested changes. If you’ve used style
sheets properly, you should be able to change just one file to make a
change like this.
A huge amount of programming is about organization and planning.
This chapter has introduced some excellent tools that you can use to
create and manage the appearance of an HTML page.
.rollover {
color:black;
}
.rollover:hover {
color:red;
}
The style sheet above creates a style called rollover. There are two
definitions for the style. The first definition just sets the color as black. The
second definition of rollover has an additional selector: hover. A selector
indicates the circumstance in which this variant of the style should be used.
The hover selector specifies that this style is to be used when the mouse is
hovering over an element with the class set to rollover. This style sets the
color to red. If you view this page in the Ch03 CSS\Ch03-18 Rollover
with CSS folder, you will see how it works.
There is a lot more you can do with selectors. You can use them to set styles
for unvisited links, or selected items, and you can even use them to set the
first letter of a paragraph. You can find a full reference at the following
Mozilla page. You will have to work hard to understand all of it (I did), but
it is powerful stuff: https://developer.mozilla.org/en-
US/docs/Web/CSS/CSS_Selectors.
What you have learned
This chapter has given you a good understanding of what style is and how
to manage it. Here are the major points we covered in this chapter:
The definition of an element in an HTML page can include a style
attribute that describes how the element should be displayed, such as
to make the text in a paragraph red.
The definition of an element can also include event attributes that
execute a piece of JavaScript code when a particular event occurs,
such as the onmouseover event triggering code when the user moves
the mouse pointer over the element.
The style information for a text element can include the font to be
used to draw the text. Fonts are specified as families, which include
all the variants of the text to be displayed (such as italic and bold). It
is conventional to provide a number of different font-family values
when specifying font options because systems use different names for
popular font designs.
The size of elements in an HTML document can be specified in
multiple ways. If the intention is to change the size of text relative to
other text, the size should be expressed in em units, where an em value
of 1 is “normal-sized” text.
Text can be aligned across an HTML page using the text-align
attribute.
The setInterval function can be used to call a JavaScript function at
regular intervals. We used this to create a ticking clock.
The style of an element can include definitions for margin, padding,
and border items. The margin is the outer margin around the element.
The border can be drawn in a variety of styles and colors, and the
border has a set thickness. The padding value sets how far the item is
placed away from the border.
When specifying the dimensions of borders and margins around
HTML elements, the px unit can be used. A value expressed in px
units represents a number of pixels and equates to the size of a pixel
in an image. Using px units means that you can get absolute control
over the layout of items at the expense of portability. (For example,
the pages might look too large or too small on some devices.)
A style sheet contains style settings that can be assigned to elements
in an HTML document. Style settings can modify styles such as <p>,
<h1>, and <h2>, or they can create completely new styles that can be
assigned to elements using the class attribute.
A style sheet can be held in a file that is separate from an HTML
page. The page contains a link element in the page heading that
identifies the style sheet file to be used. This allows complete
separation between the content and the styling of a page.
Styles are applied to elements in a way that cascades down from
enclosing elements. For example, if the body of a document is styled
with red text, that setting will cascade down into any elements in the
document. However, a color style attribute in a paragraph inside the
document will override this cascading setting.
The div and span elements act as containers around other elements.
Style attributes applied to the div and span elements cascade down
into all the elements contained in them. When a div element is
rendered, the browser will insert line breaks at the start and the end of
the div. This does not happen with a span element, making the span
element useful for applying styles to words in sentences.
To reinforce your understanding of this chapter, you might want to consider
the following “profound questions” about styles and style sheets.
Can I add a style attribute to any element?
Yes. It might not be sensible to set the font of the script element in an
HTML file, but it will not cause an error if you do.
What happens if I add an irrelevant style to an item?
Nothing. If you want to set a font for the <script> part of your HTML file,
you can do that, and you will not get any errors, but it would not be a
sensible thing to do.
What happens if I set conflicting style settings?
The most “recently” applied style will be the one that is enforced. In other
words, if the text color of the body of the document is set to black, but the
text color of the paragraph in the body is set to red, the text will be red. This
is how “cascading” works.
Is a CSS file a program?
No. The JavaScript programs that we have written set out a sequence of
actions to be performed. A CSS file contains a number of style settings
items that are applied to HTML elements that are assigned to them.
Is redText a good name for a CSS style class?
I don’t think so. If your customer decides that they really want to change to
blue text for that style, you can’t easily change the name of the class. The
name of a class should reflect what you want a style to achieve. For
example, you could have a class called displayName, which is used to
display names, and you could have another class called displayAddress for
addresses. If a style is being displayed as red, that’s something that would
be reflected in the settings for that style class, not in the name of the class
itself.
Can I store CSS files on a different server from the HTML file that
contains the web page?
Yes, you can. The link element that gets the CSS file contains a URL that
can refer to a file on a distant machine.
When should I use div, and when should I use span?
Div is used if you want to control the style of some elements that make up a
division in your page. By division, I mean something like an entire address,
an order, or a report. The division will be separated from the rest of the page
by line breaks. Span is used when you want to style a small portion of a
paragraph. For example, you might use span to highlight the word code in
this sentence. In this case, you don’t want any line breaks in the text.
What is the difference between id and class?
An element on a web page can have a setting for an id value and a class
value. The id value is unique for that element in the HTML document.
JavaScript code that works with the document can locate an element by its
id. The class value specifies the style to be applied to this element. A large
number of elements in a document can have the same class value. This
would make changing the style of these elements very easy because the
designer would just have to change the definition of the class in the style
sheet, and it would be applied to all the elements.
What is the difference between the em and px units?
This is confusing. Not least because em also means “emphasized” when
applied to text. An em value of 1 refers to the size of a “normal” character in
the current font. So, I can specify a size in em values so that I can make my
text larger or smaller relative to the rest of the text. I don’t want to use an
absolute value for my text size because, as we have seen, different fonts
have different “standard” text sizes, and I don’t want everything to become
too large or too small if the font changes. So em is very useful if you want to
express that some things are bigger than others, but you don’t want tie
things to specific sizes.
A px value refers to a number of “pixels” on the screen. Modern high-
resolution screens have pixels that are so small that this might not be an
accurate mapping, but the idea is that px values give you the ability to place
things more precisely, particularly in relation to images, which are also
sized using pixel dimensions. So em is used if you want to lay elements out
very precisely in relation to each other.
Is this all there is to CSS?
Absolutely not. We have barely scratched the surface in this chapter. You
can perform animation, fade images in and out, and do all manner of other
things too. The great thing is that the interactive help from tools like Visual
Studio Code and the wonderful Developer Console in the browser allow
you to experiment with styles to find out more. It is certainly worth doing
this. As we have seen when we looked at the rollover style selector, we can
replace JavaScript code with style sheet behavior. One of the rules of
HTML development is that you should always check to see if a style sheet
could be used to get the effect that you want before you write any
JavaScript code. Just because you could write a program to get a particular
effect doesn’t mean that you should.
OceanofPDF.com
Part 2
Coding with JavaScript
In this part, we start writing JavaScript applications. We’ll discover how to
create complete programs that run inside the browser. We’ll gain
fundamental programming knowledge of data storage and processing in
software. Then we’ll move on to a discussion of how to structure solutions
and break a large program into smaller components. Finally, we’ll take a
look at software objects and how they can be used to create custom data
storage types that map program storage to real-world data.
OceanofPDF.com
4
Working with data
What you will learn
In this chapter, you’ll build more JavaScript programs. You’ll discover that
a computer is fundamentally a data processor and that a program tells the
computer what to do with the data. You’ll see how programs store data
using variables, and you’ll learn how JavaScript manages diverse kinds of
data that can be stored by a program. You’ll also learn how JavaScript
manages the visibility of variables within a program. By the end of this
chapter, you’ll be able to create useful programs.
PROGRAMMER’S POINT
Software might be a matter of life and death
Remember that seemingly innocuous programs can have life-
threatening capabilities. For example, a doctor may use a spreadsheet
you have written to calculate doses of drugs for patients. In this case, a
defect in the program could result in physical harm. (I don’t think
doctors do this—but you never know.) For a deeply scary description of
how poor software design can cause injury and even death, search for
Therac-25 on the web.
In this example, the cook plays the role of the computer, and the recipe is
the program that controls what the cook does with the ingredients. A recipe
can work with many different ingredients, and a program can work with
many different inputs, too. For example, a program might take your age and
the name of a movie you want to see and provide an output that determines
whether you can go see that movie based on its audience rating.
JavaScript as a data processor
Figure 4-4 shows the workings of one of the early example programs,
Ch02-08 Paragraph Update, from a data processing perspective. The
input to the program is an input box on the HTML page, and the output
from the program is the text in a paragraph in the HTML page. In this case,
the JavaScript program code is in the function doUpdateParagraph, which
runs when the user presses a button on the page. This function doesn’t
perform any processing on the data input; it simply transfers text from the
input element to the output element.
This is a program structure that we will be using a lot in the next few
chapters. We can change what a program does by changing the instructions
in the functions that run inside the web page. Statements in a function will
act on data and generate new values by evaluating expressions.
Process data with expressions
An expression can be as simple as a single value (for example 2 or Rob
Miles), or it can contain operators and operands. Figure 4-5 shows a
simple expression with two operands and one operator. Things that do the
actual work are called operators. In the case of 2+2, there are two operands
(the two values of 2) and one operator (+). When you feed an expression
into the JavaScript command prompt, it identifies the operators and
operands and then works out the answer.
CODE ANALYSIS
Evaluate expressions with JavaScript
The function shown previously in Figure 4-4 doesn’t process any data;
instead, it simply transfers the text from the input to the output. Data
processing in JavaScript is performed by the evaluation of expressions.
An expression can be as simple as a single value (which is called a
literal because it is taken exactly as it is). Alternatively, an expression
could perform a complicated calculation. Let’s do some expression
evaluation to find out more.
> 2+2
<- 4
> (2+3)*4
<- 20
Answer: This one is quite interesting. You should try it with the
console. What happens is that JavaScript says to itself, “The
expression I’m trying to work out is incomplete. I need a closing
parenthesis.” So, the console waits for more input from you. If you
type the closing parenthesis and complete the expression, the value is
calculated and the result is displayed. You can even add more sums
on the second line if you want.
> (2+3*4
)
<- 14
Note that the command shell is trying to help you work out where the
error is by identifying the incorrect character.
Scripting languages
We can use the console for having conversations like this because
JavaScript is a “scripting” programming language (the clue is in the name).
You can think of the console as a kind of “robot actor” who will perform
whatever JavaScript statements you give it. In other words, you tell the
console what you want your program to do using the JavaScript language. If
the instructions don’t make sense to the “robot actor,” it tells us it can’t
understand them (usually with red text). The process of taking a program
and then acting on the instructions in it is called interpreting the program.
Actors earn a living interpreting the words of a play; computers solve
problems for us by interpreting program instructions.
PROGRAMMER’S POINT
Not all programming languages run like
JavaScript
Not all programming languages are “scripting” languages, which are
interpreted in the same way as JavaScript. Sometimes, program
instructions are converted into the very low-level instructions that the
hardware of your computer understands. This process is called
compilation, and the program that performs this conversion is called a
compiler. The compiled instructions can then be loaded into the
computer to be executed. This technique produces programs that can
run very fast because when the compiled low-level instructions are
performed, the computer doesn’t have to figure out what the
instructions mean; they can just be obeyed.
You might think this means that JavaScript is a “slow” computer
language because each time a JavaScript program runs, the “robot
actor” must work out the meaning of each command before performing
it. However, this is not really a problem because modern computers run
very, very fast, and JavaScript uses some clever trickery to compile
your program as it runs.
The two items in Figure 4-6 contain the same data, except that the image on
the left more closely resembles how the document would be stored in a
computer. The computer uses a numeric value to represent each letter and
space in the text. If you work through the values, you can figure out each
value, beginning with the value 87, which represents an uppercase W (in the
“When” that begins the first regular paragraph in the document on the
right).
Because of the way computers hold data, yet another layer lies beneath the
mapping of numbers to letters. Each number is held by the computer as a
unique pattern of on and off signals, or 1s and 0s. In the realm of
computing, each 1 or 0 is known as a bit. (For a wonderful explanation of
how computers operate at this level and of how these workings form the
basis for all coding, see Charles Petzold’s Code: The Hidden Language of
Computer Hardware and Software.) The value 87, which we know means
“uppercase W,” is held as the following way:
1010111
This is the binary representation of the value. I don’t have the space to go
into precisely how this works (and Charles Petzold already did this!), but
you can think of this bit pattern as meaning “87 is made up of a 1 plus a 2
plus a 4 plus a 16 plus a 64.”
Each of the bits in the pattern tells the computer hardware whether a
particular power of 2 is present. Don’t worry too much if you don’t fully
understand this but do remember that as far as the computer is concerned,
data is a collection of 1s and 0s that computers store and manipulate. That’s
data.
Information, on the other hand, is the interpretation of the data by people to
mean something. Strictly speaking, computers process data and humans
work on information.
For example, the computer could hold the following bit pattern somewhere
in memory:
Click here to view code image
11111111 11111111 11111111 00000000
You could regard this as meaning, “You are $256 overdrawn at the bank” or
“You are 256 feet below the surface of the ground” or “Eight of the thirty-
two light switches are off.” The transition from data to information is
usually made when a human reads the output.
I am being so pedantic because it is vital to remember that a computer does
not “know” what the data it is processing means. As far as the computer is
concerned, data is just patterns of bits; it is the user who gives meaning to
these patterns. Remember this when you get a bank statement that says you
have $8,388,608 in your account when you really have only $83!
Data processing in JavaScript
We now know that JavaScript is a data processor. A script containing
JavaScript statements is interpreted by the browser, which then produces
some output. We also know that within the computer running a JavaScript
program, data values are represented by patterns of bits (representing ons
and offs). Now we need to discover how variables let our programs store
and manipulate the data being processed.
Variables in programs
We have already used quite a few variables in our JavaScript programs.
Variables are how programs remember things. You can think of a variable
as a storage location you can refer to by name. What you store in the
location and the name you give the location are up to you. You can create a
variable in a JavaScript program by thinking of a name for the variable and
then putting a value in the variable. Perhaps you know someone with a
pressing need to add up some numbers. In this case, the first statement in
your program might look like this:
total = total + 1;
When you press Enter, JavaScript will create the variable. However, it
gives a rather strange response:
Each time we perform the addition statement, the value in total gets
larger by 1. This expression might appear confusing. If you’ve worked
with mathematical equations, you’ll remember that the equals character
(=) means that one value is equal to another. From a mathematical point
of view, the statement generated above is obviously wrong because the
total cannot equal the total plus 1. However, it’s important to
remember that in JavaScript, the equals operator means “assign.” So, the
expression total+1 is evaluated on the right side and then is assigned to
the variable on the left side. In JavaScript, it is perfectly okay to create a
variable and assign it a value immediately:
If you do this, you will notice that the result displayed by the console is
undefined because, as we saw at the start of this section, a statement that
creates a variable does not return a value. If you haven’t set a value into
a variable, JavaScript marks that variable as holding the value undefined.
Enter this statement to create a new variable called test.
> var emptyTest;
Now you can investigate the value that the newly created variable
emptyTest holds. If you just enter the emptyTest variable, the console
will hold the value stored in the variable emptyTest:
> emptyTest
<- undefined
Note that this does not mean that the variable emptyTest does not exist.
Instead, it means that the variable emptyTest does not hold a value. The
contents of emptyTest are undefined. We can pass the undefined value
around as we would any other:
> emptyCopy=emptyTest;
<- undefined
> emptySum=emptyTest + 1;
<- NaN
This kind of calculation will not cause a problem with your program,
except that it will produce silly results. JavaScript makes a distinction
between things that are not defined and things that do not exist. If you
try to view the value in a variable that does not exist, something different
happens. Enter the name notDefined and press Enter:
JavaScript identifiers
Names of things in JavaScript are called identifiers. We used the identifier
total for the first variable that we created. When you write a program, you
must come up with identifiers for the variables in that program. JavaScript
has rules about the way you can form identifiers:
An identifier must start with a letter, the dollar character ($), or the
underscore character (_) and can contain letters, numerals (digits), or the
underscore character.
The name total is a perfectly legal identifier, as is xyz. However, the
identifier 2_be_or_not_2_be would be rejected with an error because it starts
with a digit. Also, JavaScript views uppercase and lowercase letters
differently; for example, FRED is regarded by JavaScript as different from
fred.
PROGRAMMER’S POINT
Create meaningful identifiers
I find it terribly surprising that some programmers use identifiers such
as X21 or silly or hello_mum. I don’t. I work very hard to make my
programs as easy to read as possible. So, I’ll use ones such as length or,
perhaps even better, windowLengthInInches. My window length
identifier uses a format where the first letter of each word inside the
identifier is a capital letter. This is called camel case because the capital
letters in the name stick up like humps on the back of a camel. Another
convention uses the underscore character to split up the words in an
identifier: window_length_in_inches. I reckon either of these is okay,
although camel case is more common in JavaScript. I don’t care which
one you use, but I do care that you use it consistently throughout your
program.
I don’t care which method you choose to make up your identifiers; I
only care that you strive to create identifiers with meaning. If the
identifier applies to a particular thing, then identify that thing. And if
that thing has particular units of measurement, then then add those, too.
For example, if I were storing the age of a customer, I’d create a
variable called customerAgeInYears.
JavaScript allows identifiers of any length, and longer identifiers don’t
slow down a program. However, very long names can be a bit hard for
humans to read, so you should try to keep them down to the lengths
shown in the examples.
CODE ANALYSIS
Code errors and testing
By now, you should be getting used to the idea that if you give a
JavaScript program the wrong instructions, the wrong thing will happen.
However, consider the JavaScript below, which is supposed to add 1 to
the value in the variable with the name total:
Total = total + 1
I mentioned at the start of this book that JavaScript has some features
that make me want to tear my hair out. This is one of them because it
means that your punishment for a simple typing mistake is not an
error or warning message. Instead you get a program that runs but
doesn’t work properly.
Tests don’t prove that a program is good; tests simply prove that a
program is not as bad as it would be if it had failed the tests.
Tests work best if they are added at the time the program is created.
We’ll talk about testing strategies every time we make a new
program.
total = Total + 1
Answer: JavaScript will refuse to run this statement. It will tell you
that you are using a variable with the name Total, which it hasn’t
seen yet. Sometimes, typing mistakes will be detected before your
program runs, but other times, they might not.
You might be thinking that you’ve been set up to fail because I’ve
suggested that you use long, meaningful names, and typing those
long, meaningful names creates more opportunities for mistakes. For
now, one way around this problem is to use the text copy feature of
your editor to copy names from one part of the program to another.
Performing calculations
We know that JavaScript expressions are made up of operators and
operands. The operators identify actions to be performed, and the operands
are worked on by the operators. Now we can add a bit more detail to this
explanation. Expressions can be as simple as a single value or as complex
as a large calculation. Here are a few examples of numeric expressions:
2 + 3 * 4
-1 + 3
(2 + 3) * 4
If you want to force the order in which an expression evaluates, you can put
parentheses around the elements of the expression you want to evaluate
first, as in the final example above. You can also put parentheses inside
parentheses if you want—provided you make sure that you have as many
opening parentheses as closing ones. Being a simple soul, I tend to make
things clear by putting parentheses around everything.
It is probably not worth getting too worked up about expression evaluation.
Generally speaking, things tend to be evaluated how you would expect.
Here is a list of some other operators, with descriptions of what they do and
their precedence (priority). The operators are listed with the highest priority
first.
OPER
HOW IT’S USED
ATOR
Unary minus. This is the minus that JavaScript finds in negative
-
numbers.
Multiplication. Note the use of the * rather than the more
*
mathematically correct but confusing x.
Division. Because of the difficulty of drawing one number
/
above another during editing, we use this character instead.
+ Addition.
Subtraction. Note that we use the same character as for unary
-
minus.
This is not a complete list of the operators available, but it will do for now.
Because these operators work on numbers, they are often called numeric
operators. However, one of them, the + operator, can be applied between
strings, as you’ve already seen.
CODE ANALYSIS
Work out the results
Question: See if you can work out the values of a, b, and c when the
following statements have been evaluated:
var a = 1;
var b = 2;
var c = a + b;
c = c * (a + b);
b = a + b + c;
Answer: a=1, b=12, c=9. The best way to work this out is to behave
like a computer would and work through each statement in turn.
When I do this, I write down the variable values on a piece of paper
and then update each as I go along. Doing this means that you can
predict what a program will do without having to run it.
CODE ANALYSIS
Whole numbers versus real numbers
You can learn about the difference between whole numbers and real
numbers by looking at a few situations in which they might be used.
Question: I’m building a device that can count the number of hairs on
your head. Should I store this value as a whole number or as a real
number?
Answer: When we work out the result, we’ll find that the average
includes a fractional part, which means that we should use a real
number to store it.
Answer: This is very tricky. You might think that the price should be
stored as a real number—for example, $1.50 (one and a half dollars).
However, you could also store the price as the whole number, 150
cents. The type of number you use in a situation like this depends on
how that number is used. If you’re just keeping track of the total
amount of money you take in while selling your product, you can use
a whole number to hold the price and the total. However, if you are
also lending money to people to buy your product and you want to
calculate the interest to charge them, you would need a fractional
component to hold the number more precisely.
PROGRAMMER’S POINT
The way you store a variable depends on what
you want to do with it
It seems obvious that you would use a whole number to count the
number of hairs on your head. However, one could argue that we could
also use a whole number to represent the average number of hairs on
100 people’s heads. This is because the calculated average would be in
the thousands. Fractions of a hair would not add much useful
information, so we could drop any fractional parts and round to the
nearest whole number. When you consider how you are going to
represent data in a program, you must take into account how it will be
used.
> 0.1
<- 0.1
At this point, you might think that I’ve been lying to you because I
said that the value 0.1 can’t be held accurately, and now this example
shows JavaScript returning the value 0.1. However, I’m not lying to
you—JavaScript is. The JavaScript print routine “rounds” values
when it prints them. In other words, it says that if the number to be
printed is 0.10000000000000000551115 or thereabouts (which it is),
then it will just print 0.1.
Answer: At the moment, you’ve just got my word for it that values
are rounded when printed and that errors are being hidden from us as
a result. However, if we perform a simple calculation, we can
introduce an error that is large enough to escape being rounded.
Enter the following calculation into the JavaScript Shell and note
what comes back.
> 0.1+0.2
<- 0.30000000000000004
The result of adding 0.1 to 0.2 should be 0.3, but because the values
are held as binary floating-point values, the result of the calculation
contains an error large enough to escape being rounded.
Open the Developer View by pressing F12. You can begin by displaying
a random number by calling the random function from the Math library:
> Math.random()
> Math.random()
<- 0.01479622790601498
I would be very, very surprised if you got the same number as the one
printed above (you would have to run your program at exactly the same
time I did). You will see a number between 0 and 1. Call random a few
more times and note that you get a different number each time. If you
tried it enough times, it is possible you could see a value 0 but you
would never see a value of 1. That is important to us.
The random function returns a value between 0 and 1. We can expand the
range of the random number by multiplying it by the range that we want;
in this case, that range is 6. Try entering this:
> Math.random()*6
This will generate a result that ranges from 0 up to but not including 6
(because random() can never return 1). Try it.
> Math.random()*6
<- 1.342641962710725
The next thing we need to do is get rid of that fractional part. JavaScript
provides another Math function, called floor, which chops the fractional
off a number. No matter how large the fractional part, it is always
discarded. Try this:
> Math.floor(1.9999)
The value 1.9999 is very close to 2, but the floor function throws away
the entire fractional part. We can apply the floor function to our random
value. Try this:
> Math.floor(Math.random()*6)
> Math.floor(Math.random()*6)+1
This is the “brains” of our program. Click the Elements tab in the
Developer View and then expand the <script> element to view the
doRollDice function.
In the middle of the function there is a statement that sets the value of
the spots variable to a random number between 1 and 6. How would you
change the program to produce a number between 1 and 20?
This turns out to be very easy; the program must multiply the random
value by 20 rather than 6.
Working with text
We now know how to use variables that hold numbers. A program can also
create a variable that holds a string of text.
var customerName = "Fred";
This statement looks exactly like the statement we used to create the total
variable except that the value being assigned is a string of text. The string
being assigned is enclosed in double quote characters that define the limits
of the text. The double quote characters are called delimiters because they
define the limits of the text. The delimiters are not part of the string being
stored, so the customerName variable just contains the word Fred.
The customerName variable is different from the total variable in that it
holds text rather than a number. We can use this variable anywhere we
would use a string.
Click here to view code image
var message = "the name is " + customerName;
If you want to enter a string that contains both single and double quotes,
you can use backticks (`)—also known as an acute—to delimit the string:
Click here to view code image
If you have a need to enter a string that contains both kinds of quotes and
backticks, then it must be an amazing string. You can enter that by using
escape sequences.
ESCAPE
WHAT IT MEANS WHAT IT DOES
SEQUENCE
Backslash character
\\ Enters a backslash into the string
(\)
Enters a single quote into the
\' Single quote (')
string
Enters a single backtick into the
\` Backtick (`)
string
Enters a double quote into the
\" Double quote (")
string
ESCAPE
WHAT IT MEANS WHAT IT DOES
SEQUENCE
Unicode Line
\n End this line and take a new one
Feed/New Line
Move to the right to the next tab
\t Unicode Tab
stop
Unicode Carriage Return the printing position to the
\r
return start of the line
CODE ANALYSIS
> 1 + 2 + "hello" + 3 + 4
<- "3hello34"
Note that this is not the kind of programming I approve of, because it
is a bit confusing. If I really wanted to create an output like what’s
shown above, I would break it down into a number of separate
statements.
var calc1 = 1 + 2;
var calc2 = 3 + 4;
var result = calc1 + "hello" + calc2;
The page contains two input fields for the values to be entered, a button to
request a calculation, and a paragraph element that displays the result. We
know how to create almost every part of this application except for one
thing. The user will enter the numbers to be added as text strings. We need a
way of converting these strings into numbers that can be added together.
> 2+2
The console shows the result of the expression you would expect:
<- 4
> "2"+"2"
<- 22
We can see this distinction in action when we create variables. Create the
two variables by entering the following:
JavaScript provides a function called typeof, which will tell you the type
of a variable you supply to it. Use it to investigate the type of the
variables name and age.
> typeof(stringTwo)
<- "string"
> typeof(numberTwo)
<- "number"
> typeof(convertedTwo)
<- "number"
This is the statement that calculates the addition and stores it in a variable
called result. This is the part of the program where the data processing is
performed. The rest of the HTML and JavaScript are there to provide a
means of input and output. The last thing the function needs to do is display
the result for the user. We have written several functions that do this; the
result is displayed by modifying the text in a paragraph on the web page.
Click here to view code image
The good news is that at least the program didn’t output a number like
-8399608 when the user upset it like this, but it is still less than perfect.
In the next chapter, we will discover how a program can decide when a
number is valid and display a suitable alert message. However, the best
way to remove an error like this is to do something that ensures it can
never happen. We can tell the browser that a given input element is a
number rather than text.
Note that even though we have specified that the type of the input field is
number, we still get a text string from the input field when we use it in
our programs. However, we can be sure that the text that we get from the
element only contains digits. You can try this version of the page in the
Ch04 Working with data\Ch04-04 Number Adding Machine example
folder.
PROGRAMMER’S POINT
Error handling is a big part of programming
Professional programmers spend at least as much time thinking about
how things can go wrong as they do writing program code. They also
spend a lot of time deciding how they can prove that their program
works by testing it. This is one reason why what look like simple
programs can take a long time to create.
Making applications
We now know enough programming to be able to make some useful
applications, so let’s make some.
This is my first version. I’m using the Pizza emoji symbol (🍕) to
get a nice pizza slice for the heading. The page works fine with the data
above. If I say there are 30 students, the program will tell me I need 20
pizzas. However, there are problems with some numbers of pizzas, as you
can see in Figure 4-9.
Figure 4-9 Pizza fractions
I can’t ask the pizza place for a fraction of a pizza, so I need a way of
converting the number of pizzas to an integer. At this point, I also must
decide what the conversion will do. If I just use the floor function we used
in the dice program, this will result in an order for 26 pizzas because the
floor function truncates the floating-point value. This effectively means
that I’ll have pizza for only 39 people rather than 40, leaving one hungry
student. There are several ways to address this problem. I might think the
best way to attack the problem is to add one extra pizza to the order to take
care of any “spares.”
Click here to view code image
var noOfPizzas = Math.floor(noOfStudents / 1.5) + 1;
The program uses a style sheet to modify the style of the <h1> and <p>.
You could modify these styles to make it look even better.
PROGRAMMER’S POINT
Never assume that you know what a program is
supposed to do
If you wrote the pizza calculator for a customer, you should not decide
for yourself what the program should do if it must order a fraction of a
pizza. Your customer might want to “round down” the number of pizzas
to keep their costs down. If this is the case, they will complain when
your program adds an extra pizza. Alternatively, they might want to
establish a reputation as a generous person, in which case the program
should be made to “round up” the value.
As a programmer, never assume that you know what the program
should do. You must always ask the customer. Otherwise, you might
find yourself paying for over-ordered pizzas.
You can find my version of the solution in this folder: Ch04 Working with
data\Ch04-07 Fahrenheit to Centigrade. You can now write any kind of
conversion program you like, converting feet to meters, grams to ounces, or
liters to gallons.
Adding comments
As soon as you start to make useful programs, I think you should start
adding comments to make it clearer what your program is doing. You don’t
write comments for the computer; you write comments for someone reading
your program:
Click here to view code image
/* Based on each pizza feeding 1.5 students. We divide the
number
of students by 1.5 to get the number of pizzas. Then we drop
the fractional part and add 1 to round up the number
Note that this means we might buy slightly too much
pizza for some numbers of students.
*/
var noOfPizzas = Math.floor(noOfStudents / 1.5) + 1;
The comment in the program above makes it very clear exactly how we are
calculating the number of pizzas and the reasoning behind the statement. If
the comment weren’t there, you’d have to know that 1.5 was there because
we have decided that is how many students each pizza will feed. You can
write a comment that spreads over several lines by enclosing your comment
text in the characters /* and */. When the browser sees the character
sequence /* in a JavaScript program, it ignores the following text, up to the
point where it sees a */ that ends the comment text. You can put comments
anywhere in your program. The browser will completely ignore them. You
can also create single-line comments:
Click here to view code image
PROGRAMMER’S POINT
Don’t add too much detail in your comments
Writing comments is a very sensible thing to do, but don’t go mad.
Remember that the person who is reading your program can be
expected to know JavaScript and doesn’t need things explained to them
in too much detail:
Click here to view code image
goatCount = goatCount + 1; // add one to goatCount
HTML comments
Note that these comments only work in the <script> part of the program.
You can add comments to the HTML, as we saw in Chapter 2, but you use a
different character sequence to mark the start and end of the comments:
Click here to view code image
The start of the comment is marked by the sequence <!-- and the end of the
comment by the sequence -->. As with JavaScript comments, the text
between the two sequences is ignored by the browser.
Global and local variables
At the start of this section, we wanted to make a totalizer program that can
be used to add up a bunch of numbers. We can now create this. Let’s
assume that we are creating a solution for a customer who really does want
to totalize some numbers. You have sat down with her and agreed on the
following design for the application.
Your customer would like a stylish black background containing the Abacus
emoji. We can create this by using a style sheet that sets the color scheme
for the application and finding the symbol number for the abacus
(🧮).
She wants to be able to type in a value and press the Add to total button to
add the value to the total. She also wants a button she can use to set the total
back to zero when she has finished adding one set of values. You agree on
the design shown in Figure 4-10 above.
PROGRAMMER’S POINT
Getting a good specification is vital
The sample page shown in Figure 4-10 is a good start for the
specification of the Totalizer application. It is very important that you
get a solid specification for any work that you perform, even (or
perhaps especially) if you are working for someone you know. The nice
thing about the screenshot of the application is that it sets out exactly
what the solution should look like. However, there are some questions
I’d want answered, too.
I would like to know if there is any upper limit to the amount to be
added to the total. I’d also like to know if the Totalizer should accept
negative numbers to be subtracted from the total or whether the total
should always be increased. The answers to these questions tell me
whether the Totalizer should detect and reject invalid input values. The
customer might be assuming that negative values should not be added
(or might never have thought about this issue). Either way, as the
builder of the solution, you need to know how it should work.
Otherwise, you might end up having conversations with your customer
that include phrases such as, “It isn’t supposed to do that…”.
Global variables
The Totalizer program is interesting because it is the first program we have
written that needs to “remember” something between function calls. Until
now, every program that we have created takes data from the input
elements, does something to it, and then displays the result. Any variables
that we have created to store data in a function during data processing are
discarded as soon as the process has finished. For example, consider the
temperature conversion program, which takes a temperature entered in
Fahrenheit and converts it to centigrade.
All the variables in this function will be destroyed once the function has
finished. They are described as local because they are local to the function.
This is how the JavaScript manages variables created using var. Most of the
time, this is exactly what you want. We don’t want the program to use any
values left over from a previous use of the function. However, the Totalizer
program needs to retain the total value for use in successive calls of the
function that adds values to it. In other words; we want to write some code
like this:
Click here to view code image
var total=0; // Global variable to hold the total
PROGRAMMER’S POINT
Global variables are a necessary evil
If you talk to some programmers, they might tell you that your
programs should never use global variables. This is because a global
variable represents a possible failure point that is out of your control. I
can be sure that all the variables in my functions contain correct values.
This is because each time a function runs, it makes clean new copies of
every variable, but a global variable exists in outside my functions. I
can’t regard it as “clean” because I don’t know what other functions
might have been doing with it. Mistakes by other programmers could
make my functions do the wrong thing, and that is bad. If another
function changes, the contents of total my function could display a
result that is incorrect. However, in the case of the Totalizer program, a
global variable is the simplest way I can make it work.
Programmers talk about functions having side effects. These are things
that the function does that change the state of the system in which they
are running. In the case of the Totalizer, the doAddToTotal function has a
side effect that increases the value of total by the amount entered by
the user. This is a side effect that is present by design. It is important to
avoid unintended side effects.
CODE ANALYSIS
var total=0;
Answer: Yes. The function that is called to clear the total back to 0
will set the value of total back to 0.
This function sets the value of total to 0 and then updates the
display to reflect this.
Question: How could I create a Totalizer that stored the total value when
the page was not being used?
You can find my version of the Totalizer program in the Ch04 Working
with data\Ch04-08 Totalizer folder. This includes the style sheet that sets
up the requested color scheme.
“Nerves of Steel”
We can use our ability to make random numbers, coupled with the
setTimeout function we used to make egg timers in Chapter 2, to create a
“Nerves of Steel” party game. The game works like this:
This game can get very tactical, with players taking a chance on an
unlikely number just so that they will be one of the people to go forward
to the next round.
Adding sound
You can add sound to the game. You can have a ticking clock sound
effect while the players are waiting and a “ding” sound when the timer
expires. To do this the program will have to start and stop the audio
playback. It will also have to “reset” the ticking sound so that it plays
from the beginning of the sound sample. A sound in HTML provides
play and pause methods that can be used to control playback. It also
provides a currentType property that a program can use to read or set.
This is the tickAudio element in my version of the program:
<audio id="tickAudio">
<source src="tick-track.mp3" type="audio/mpeg">
</audio>
I can start the playback as follows. The first statement sets the playback
position at 0 so that the playback begins at the start of sound. The second
statement plays the sample.
tickSoundElement.pause();
Note that there is no command to stop the playback of a sound. You can
find my versions of the games in the folders Ch04 Working with
data\Ch04-09 Nerves of Steel and Ch04 Working with data\Ch04-10
High and Low. You can use these as the basis of any other games you
might like to create.
OceanofPDF.com
5
Making decisions in programs
Boolean thinking
The if construction
Use decisions to make an application
Improve the ride selector
What you have learned
Boolean thinking
In Chapter 4, you learned that programs use variables to represent different
types of data. I like to think that you will forever associate the number of
hairs on your head with whole numbers (integers) and the average length of
your hair with real numbers (floating-point values). Now it’s time to meet
another way of looking at data values: Boolean. Data that is Boolean can
only have one of two values: true and false. You could use a Boolean value
to represent whether a given person has any hair.
The words true and false are keywords. These are words that are “built in”
to JavaScript. There are 63 different keywords. You’ve already seen a few
of them. For example, function is a keyword. When JavaScript sees the
keywords true or false, it thinks in terms of Boolean values.
JavaScript regards values that are numbers or text as being either “truthy”
or “falsy.” Values are regarded as “truthy” unless they are zero, an empty
string, Not a Number (NAN), or undefined—in which case, they are
“falsy.”
CODE ANALYSIS
Boolean values
Boolean values are a new type of data that a program can manipulate.
But of course, we have questions about them.
alert(itIsTimeToGetUp);
Answer: When you display any value, JavaScript will try to convert
that value into something sensible for us to look at. In the case of
Boolean values, it will display true or false.
Question: Is there a JavaScript function called Boolean that will convert
things into Boolean values, just like there is a Number function that will
convert things into a number?
Answer: Indeed, there is. The Boolean function applies the rules of
“truthy” and “falsy” to the value supplied to it.
> Boolean(1);
<- true
> Boolean(0);
<- false
> Boolean(-1);
<- true
Answer: Yes. If you understand this, you can call yourself a “truthy
ninja.” Any string other than an empty string is regarded as true.
> Boolean("false");
<- true
> Boolean("");
<- false
> Boolean(1/0);
<- true
> Boolean(1/"Rob");
<- false
Note that, as with numbers, this conversion does not work the other
way. Just as we had to use the Number function to convert a string into
a number, we have to use the Boolean function to convert values of
other types into values that obey the “truthy” and “falsy” rules.
The statements above get the hours, mins, and secs values for the current
time. We could use these values to write some JavaScript that would decide
whether I should get up. Note that the hours value is supplied as a 24-hour
clock value, meaning it goes from 0 to 23 over the day.
Boolean expressions
We’ve said that JavaScript expressions are made up of operators (which
identify the operation) and operands (which identify the items being
processed). Figure 5-1 shows our first expression, which worked out the
calculation 2+2.
Figure 5-1 An arithmetic operator
Comparison operators
These are the comparison operators that you can use in JavaScript
programs.
OPER
NAME EFFECT
ATOR
Greater True if the value on the left is greater than the value
>
than on the right
OPER
NAME EFFECT
ATOR
True if the value on the left is less than the value on
< Less than
the right
Greater
True if the value on the left is greater than or equal
>= than or
to the value on the right
equals
Less than True if the value on the left is less than or equal to
<=
or equals the value on the right
True if the value on the left and the value on the
== Equality
right can be promoted to values that are equal
True if the values on the left and the value on the
=== Identity
right are the same type and hold the same value
True if the value on the left and the value on the
!= Not equals
right cannot be promoted to values that are equal
True if the values on the left and the value on the
Not
!== right are not the same type or do not hold the same
identical
value
This statement will set the variable itIsTimeToGetUp to the value true if the
value in hours is greater than 6 and false if the value in hours is not greater
than 6. Remember that an operator that is a single equals character performs
an assignment, not a test. If this seems hard to understand, try reading the
statement and listen to how it sounds. The statement “itIsTimeToGetUp
equals hour greater than six” is a good explanation of the action of this
statement.
CODE ANALYSIS
Examining comparison operators
Question: How does the equality operator work?
> 1==1;
<- true
> "Rob"=="Rob";
<- true
> true == true;
<- true
We’ve seen that JavaScript “promotes” values when they are used in
expression. This happens with the equality operator, too. The logical
value true is promoted to the value 1 when it is used in an expression
with the equality operator.
> 1 == true;
<- true
> 2 == true;
<- false
> true == 1;
<- true
The identity comparison === does not perform any promotion before
comparing two values. If we use the identity comparison to compare
the logical value of true with 1, a result of false is produced.
Answer: When I was learning to program, I associated the < in the <=
operator with the letter L, which reminded me that <= means “less
than or equal to.”
These statements create two variables, x and y, which should both hold
the value 0.3. The variable x has the value 0.3 directly assigned, whereas
the second variable, y, gets the value 0.3 as the result of a calculation
that works out the result of 0.1 + 0.2. What do you think we will see if
we test the two variables for equality?
> x == y;
<- false
This expression uses the equality operator (==), which will produce a
result of true if its two operands hold the same value. However,
JavaScript decides that x and y are different because the variable x holds
the value 0.3, and the variable y holds the value 0.30000000000000004.
This illustrates a problem with program code that compares floating-
point values to determine whether they are equal. The tiny floating-point
errors mean values we think are the same do not always evaluate that
way.
The date and time values returned from the JavaScript Date object are
supplied as integers so you can test these for equality without problems.
Logical operators
At the moment, my test to determine whether it is time to get up is only
controlled by the hour value of the time.
The above statement sets the value of itIsTimeToGetUp to true if the hour is
greater than 6 (meaning from 7 and onward) but we might want to get up at
7:30. To be able to do this, we need a way of testing for a time when the
hour is greater than 6 and the minute is greater than 29. JavaScript provides
three logical operators we can use to work with logical values. Perhaps they
can help solve this problem.
OPERAT
EFFECT
OR
Evaluates to True if the operand it is working on is False
!
Evaluates to False if the operand it is working on is True
Evaluates to True if the left-hand value and the right-hand
&&
value are both True
OPERAT
EFFECT
OR
Evaluates to True if the left-hand value and the right-hand
||
value are both True
The && (and) operator is applied between two Boolean values and returns
true if both values are true. There is also an || (or) operator, which is
applied between two Boolean values and returns true if one of the values is
true. The third operator is the operator ! (not), which can be used to invert
a Boolean value.
CODE ANALYSIS
Logical operators
We can investigate the behavior of logical operators by using the
Developer View in the Edge browser. We can just type in expressions
and see how they evaluate. Please don’t be confused by the way that the
< and > characters are used in the devleoper console samples below.
<- !true;
> !true;
<- false
Answer: Because both sides (operands) of the && (and) operator need
to be true for the result to be true, you shouldn’t be surprised to see
a result of false here.
Question: So far, the examples have used only Boolean values. What
happens when we start to combine Boolean and numeric values?
We know that any value other than 0 is true, so JavaScript will return
the right-hand operand, which in this case is True. We can see this
behavior with the || (or) operation, too. JavaScript only looks at the
operands of a logical operator until it can determine whether the
result is true or false.
> 1 || false;
<- 1
> 0 || True;
<- True
You might wish to experiment with other values to confirm that you
understand what is happening.
We want to make some JavaScript that takes in hour and minute values and
decides whether to sound the alarm. We could try to make an alarm that
triggers after 7:30 by writing the following statement:
Click here to view code image
var itIsTimeToGetUp= hours>6 && minutes>29;
The && (and) operator is applied between the result of two Boolean
expressions and returns true if both of the expressions evaluate to true. The
above statement would set the variable itIsTimeToGetUp to true if the value
in hours is greater than 6 and the value in minutes is greater than 29, which
you might think is what we want. However, this statement is incorrect. We
can discover the bug by designing some tests:
The table shows four times, along with the required result (what should
happen), and the observed result (what does happen). One of the times has
been observed to work incorrectly. When the time is 8:00, the value of
itIsTimeToGetUp is set to false, which is wrong.
The condition we are using evaluates to true if the hours value is greater
than 6 and the minutes value is greater than 29. This means that the
condition evaluates to false for any minute value that is less than 29,
meaning it is false at 8:00. To fix the problem, we need to develop a
slightly more complex test:
Click here to view code image
var itIsTimeToGetUp= (hours>7) || (hours==7 && minutes>29);
I’ve added parentheses to show how the two tests are combined by the ||
(or) operator. If the value of hours is greater than 7, we don’t care what the
value of minutes is. If the hours value is equal to 7, we need to test to see
whether the minutes value is greater than 29. If you try the values in the
table with the above statement, you will find that it works correctly. This
illustrates an important point when designing code intended to perform
logic like this. You need to design tests that you can use to ensure that the
program will do what you want.
The if construction
Suppose I want to make a program that will display a message telling me
whether it’s time to get out of bed. We can use the Boolean value we just
created to control the execution of programs by using JavaScript’s if
construction. Figure 5-3 shows how an if construction fits together.
The condition controls the execution of the statement. In other words, if the
condition is “truthy,” the statement is performed; otherwise, it is not
performed.
Click here to view code image
if (itIsTimeToGetUp) alert("It is time to get up!");
The statement above would display an alert if it were time to get up. You
can see this in use in the example \Ch05 Making Decisions in
Programs\Ch05-01 Alarm Alert, which displays the alert if you visit the
page after 07:30 in the morning.
This is the full text of the alarm alert page. Note that the statement that
implements the “intelligence” of the program is only one tiny part of the
code.
The behavior of the if construction is controlled by the condition. The
condition does not have to be a variable; it can also be a logical expression:
Click here to view code image
if ((hours>7) || (hours==7 && minutes>29)) alert("It is time to
get up!");
This statement removes the need for the itIsTimeToGetUp variable.
However, I quite like using the variable because it helps the user understand
what the program is doing.
The else part is added onto the end of a conditional statement. If comprises
the keyword else followed by the statement to be performed if the
condition is false. We could use it to make our alert program display a
message when we can stay in bed.
Click here to view code image
if(itIsTimeToGetUp)
alert("It is time to get up!");
else
alert("You can stay in bed");
CODE ANALYSIS
If constructions
Question: Must an if construction have an else part?
Answer: No. They are very useful sometimes, but it depends on the
problem that the program is trying to solve.
The code above displays a message and plays an alarm sound. You can find
the working program in the example Ch05 Making Decisions in
Programs\Ch05-03 Alarm Alert with sound block. This uses the
“everything sound” as an alarm, which some might feel a bit harsh, but it
certainly wakes me up. Note that in the above code, I’ve used curly braces
to enclose the statements for both the if and else parts of the condition,
even though there is no need to do this for the else part as it only contains
one statement. I do this to make it clear what is going on. It also means that
it is easier to add extra statements controlled by the else part because I can
just put them inside the block.
You discuss with him the design of the program user interface. The user
interface is what people see when they use the program and the steps that
they go through when they are using it. In this application, users will
specify the ride they want to go on and enter their age. They then click a
button and are told whether they can go on that ride (see Figure 5-5).
Figure 5-5 Theme park rides
PROGRAMMER’S POINT
Design the user Interface with the customer
You might think that an interface like this would be simple to design
and that the customer will have no strong opinions on how the user
interface looks and functions. I’ve found this to be wrong. I’ve had the
awful experience of proudly showing my finished solution to a
customer only to be told that it was not what they wanted and that it is
“hard to use.” I now understand that this was my fault. Rather than
showing only my finished design, I should have created the design with
the customer. That would have saved me a lot of work.
Build the user interface
The first thing we need to do is create the HTML web page and the style
sheet for the application. In Chapter 3, we decided that it was a good idea to
separate the style sheet file, which holds the style of the page elements,
from the page layout. It is also a good idea to separate the JavaScript
program code from the HTML layout. We do this by putting the JavaScript
into a file with the language extension “.js.” We can then add an element in
the head of the HTML file that specifies this file name:
Click here to view code image
<script src="themepark.js" ></script>
The HTML above is added to the <head> part of an HTML document and
includes the contents of the JavaScript file themepark.js in an HTML page.
You can see it in use in the HTML below.
This is the HTML file for the Theme Park Ride Selector application. It uses
some features of HTML that we’ve not seen before. We can create an
ordered list of items by using the <ol> tag to enclose some <li> list
elements. The browser will automatically number the elements for us. Each
element on the page is assigned a class that has a specific style. The settings
for each of the styles are in a separate CSS style sheet file called
styles.css. A part of this file is given below:
The menuHeading class is in the HTML used to format the heading. It uses
the Impact font and adds two shadows to the text. The first shadow is blue
and close to the text, which provides a 3D effect for each character. The
second shadow is more diffuse and darker blue so that it makes the
characters appear to stand out from the page. You can see the effect in
Figure 5-5. Each shadow is defined by a color value preceded by three
values. The first two values give the x and y offsets of the shadow from the
text. The third value determines how “diffuse” the shadow is. The first
shadow is not diffused at all, whereas the second has a diffusion size of
10px, leading to the text shown earlier in Figure 5-5.
The style sheet also applies some shared settings to all the menu input
classes. This means that the font is set once for all those classes, making it
easy to change the font if required. It is a good idea to group classes in this
way if they all have a set of common characteristics. Remember that classes
accumulate setting values, which are then used on the HTML elements that
are assigned to that class. So, for example, the menuYes class will bring
together the following settings—some from those shared by other menu
settings, and some specific to that class:
Click here to view code image
color: green;
When these statements have completed, the variables rideNo and ageNo
contain the number of the ride and the age of the guest. The next thing the
function does is get a reference to the paragraph that will be used to display
the result. If you look at the HTML for the user interface, you’ll see that
this paragraph has the ID menuAnswerPar:
Click here to view code image
Now that the program has the input data and somewhere to put the output, it
can make decisions about the use of the rides. If the user has selected ride
number 1, there are no age restrictions for the Scenic River Cruise, so this
code is a single test for a ride number of 1. If the user has selected this ride,
we set the style class for the result element to the menuYes class. This has the
effect of changing the style of that element so that the text is now green.
Then the inner text for the paragraph is set to You can go on the Scenic
River Cruise so that this is displayed for the user.
if(rideNo==1) {
// This is the Scenic River Cruise
// There are no age limits for this ride
resultElement.className="menuYes";
resultElement.innerText = "You can go on the Scenic River
Cruise";
}
If the user has not selected ride number 1, the program must test to see
whether ride number 2 has been picked.
Click here to view code image
if(rideNo==2) {
// This is the Carnival Carousel
// riders must be 3 or over
if(ageNo<3) {
resultElement.className="menuNo";
resultElement.innerText = "You are too young for the
Carnival Carousel";
}
else {
resultElement.className="menuYes";
resultElement.innerText = "You can go on the Carnival
Carousel";
}
}
The code above shows how this works. The program works by nesting one
conditional statement inside another. Note how I’ve used the layout of the
program to make it clear which statements are controlled by which
condition.
Now that you have code that works for the Carnival Carousel, you can use
it as the basis for the code that handles some of the other rides. To make the
program work correctly for the Jungle Adventure Water Splash, you need to
check for a different ride number and confirm or reject the user based on a
different age value. Remember that for this ride, a visitor must be at least
six years old.
Click here to view code image
if(rideNo==3) {
// This is the Jungle Adventure Water Splash
if(ageNo<6) {
resultElement.className="menuNo";
resultElement.innerText =
"You are too young for Jungle Adventure Water
Splash";
}
else {
resultElement.className="menuYes";
resultElement.innerText = "You can go on Jungle
Adventure Water Splash";
}
}
You can implement the Downhill Mountain Run very easily by using the
same pattern as for the previous two rides. But the final ride, the
Regurgitator, is the most difficult. The ride is so extreme that the owner of
the theme park is concerned for the health of older people who ride it and
has added a maximum age restriction as well as a minimum age. The
program must test for users who are older than 90 as well as those who are
younger than 12. We must design a sequence of conditions to deal with this
situation.
The code that deals with the Regurgitator is the most complex piece of the
program that we’ve had to write so far. To make sense of how it needs to
work, you need to know more about the way that if constructions are used
in programs. Consider the following code:
Click here to view code image
if(rideNo==5) {
// This is the Regurgitator
The condition is true when the user has selected ride number 3, and all the
statements we add to the block of code controlled by this condition will run
only if the selected ride is the Regurgitator. In other words, there is no need
for any statement in that block to ask the question “Is the selected ride the
Regurgitator?” because the statements are run only if this is the case. The
decisions leading up to a statement in a program determine the context in
which that statement will run. I like to add comments to clarify the context:
Click here to view code image
if(rideNo==5) {
// This is the Regurgitator
if(ageNo<12) {
resultElement.className="menuNo";
resultElement.innerText = "You are too young for the
Regurgitator";
}
else {
// get here if the age is 12 or above
if(ageNo>90) {
resultElement.className="menuNo";
resultElement.innerText = "You are too old for the
Regurgitator";
}
else {
resultElement.className="menuYes";
resultElement.innerText = "You can go on the
Regurgitator";
}
}
}
These comments make the program slightly longer, but they also make it a
lot clearer. This code is the complete construction that deals with the
Regurgitator. The best way to work out what it does is to work through each
statement in turn with a value for the user’s age. You can find all the sample
code in the folder Ch05 Making Decisions in Programs\Ch05-04 Theme
Park.
switch(rideNo)
{
case 1:
// This is the Scenic River Cruise
// There are no age limits for this ride
resultElement.className = "menuYes";
resultElement.innerText = "You can go on the Scenic River
Cruise";
break;
case 2:
// This is the Carnival Carousel
// .. statements for Carnival Carousel go here
break;
case 3:
// This is the Jungle Adventure Water Splash
// .. statements for Jungle Adventure Water Splash go here
break;
case 4:
// This is the Downhill Mountain Run
// .. statements for Downhill Mountain Run go here
break;
case 5:
// This is the Regurgitator
// .. statements for the Regurgitator go here
}
The code above shows how the switch would be used. The value in rideNo
is used as the control value for the switch, and the program will select the
case that matches the control value. You can put as many statements as you
like in a particular case, but you must make sure that the last statement in
the case is the break keyword, which ends the execution of the code for that
case. You can find my switch-powered solution for the Theme Park ride
selector in the Ch05 Making Decisions in Programs\Ch05-05 Switch
Theme Park Ride Selector folder.
You can use the switch statement with strings and integer values, which can
be a convenient way of selecting an option. A switch construction can have
a default selector, which is obeyed if none of the cases match the control
value. You can also use multiple case elements to select a particular
behavior. The switch below is controlled by a variable called commandName.
The commands Delete, Del, and Erase all result in the erase behavior being
selected:
Click here to view code image
var commandName ;
switch(commandName)
{
case "Delete":
case "Del":
case "Erase":
// Erase behavior goes here
break;
case "Print":
case "Pr":
case "Output":
// Print behavior goes here
break;
default:
// Invalid command behavior goes here
break;
}
WHAT COULD GO WRONG
Missing breaks in switches can cause mayhem
Click here to view code image
switch(rideNo)
{
case 1:
// This is the Scenic River Cruise
// There are no age limits for this ride
resultElement.className = "menuYes";
resultElement.innerText = "You can go on the Scenic River
Cruise";
case 2:
// This is the Carnival Carousel
if (ageNo < 3) {
resultElement.className = "menuNo";
resultElement.innerText = "You are too young for the
Carnival Carousel";
}
else {
resultElement.className = "menuYes";
resultElement.innerText = "You can go on the Carnival
Carousel";
}
break;
}
Fortune Teller
The Math.random function can be used in if constructions to make
programs that perform in a way that appears random.
if(Math.random()>0.5)
resultString = resultString+"tall ";
else
resultString = resultString+"short ";
if(Math.random()>0.5)
resultString = resultString+"blonde ";
else
resultString = resultString+"dark ";
Is there a limit to how many if conditions you can nest inside each
other?
No. JavaScript will be quite happy to let you put 100 if statements in a row
(although you would have a problem editing them). If you find yourself
doing this, you might want to step back from the problem a bit and see if
there is a better way of attacking the problem.
How long can a block be?
A block of code can be very long indeed. You could control 1,000 lines of
JavaScript with a single if condition. However, very long blocks can make
code hard to understand. If you want to control a large amount of code with
a condition, you should put the code into a function. We will learn about
functions in Chapter 8.
Does the use of Boolean values mean that a program will always do the
same thing given the same data inputs?
It is very important that, given the same inputs, the computer does the same
thing each time. If the computer starts to behave inconsistently, this makes
it much less useful. When we want random behavior from a computer (for
example, when writing a fortune teller program), we have to obtain values
that are explicitly random and make decisions based on those. Nobody
wants a “moody” computer that changes its mind (although, of course, it
might be fun to try to program one using random numbers).
Will the computer always do the right thing when we write programs
that make decisions?
It would be great if we could guarantee that the computer will always do the
right thing. However, the computer is only ever as good as the program it is
running. If something happens that the program was not expecting, it might
respond incorrectly. For example, if a program was working out cooking
time for a bowl of soup, and the user entered 10 servings rather than 1, the
program would set the cooking time to be far too long (and probably burn
down the kitchen in the process).
In that situation, you can blame the user (because they input the wrong
data), but there should probably also be a test in the program that checks to
see if the value entered is sensible. If the cooker can’t hold more than 3
servings, it would seem sensible to perform a test that limits the input to 3.
This part of a program is called “input validation,” and it is a very important
that programs do this. When you write a program, you need to “second
guess” what the user might do and create decisions that make your program
behave sensibly in each situation.
OceanofPDF.com
6
Repeating actions in programs
What you will learn
In the last chapter, you learned how a program can make decisions and
change its behavior according to the data that it is given. In this chapter, you
are going to discover how to make a program repeat a sequence of actions
using the JavaScript loop constructions. Along the way, we’re going to
explore some new features of HTML and JavaScript. We are also going to
discover some ways that programs can go wrong and how good design can
reduce the chances of a program failing.
App development
Investigate list elements
Building web pages from code
More multiplication table fun
What you have learned
App development
Our starting point is the Theme Park Ride Selector program developed in
Chapter 5. This program uses conditional (if) constructions to display
whether a rider can go on their selected ride.
Figure 6-1 shows the solution in use. The rider entered their age as 18 and
selected ride number 1, the Scenic River Cruise, which they can go on. The
program works, but the owner of the theme park wants changes. She wants
to remove the need for the ride selection and have the program display the
ride names in red or green to indicate which ones can be ridden for a given
age. She has created a new design and wants you to rewrite the application
to match.
Figure 6-1 Theme Park Ride Selector
Figure 6-2 shows how the updated application will work. The rides that are
available to an 8-year-old are shown in green. The first thing we need to do
is remove the ride numbers from the ride display. The previous application
used a numbered list because the rider had entered their chosen ride
number. However, the new application doesn’t need ride numbers.
Click here to view code image
This is the HTML that we will use to display the names of the rides in the
updated application. It uses an unordered list element— <ul>—that holds a
collection of list elements (<li>) for rides. These are not displayed with
numbers. Now we need to modify the program in the JavaScript code that
controls the behavior of the application. The program will get the age of the
rider and then use it to indicate whether the rider can go on each ride.
This code shows how the program displays the results for the Jungle
Adventure ride. It follows a pattern that we have seen many times before:
1. Get a reference to the document element that will display the result for
the rider to see.
2. Update a property of this document element to show the result.
The code above sets a variable called jungleAdventureElement to refer to
the element holding the text being displayed for the Jungle Adventure ride.
(This is the list item with the ID jungleAdventure.) It then uses a
conditional statement controlled by the value in ageNo to update the
className property of jungleAdventureElement to an appropriate style. The
ageNo variable contains the age of the rider.
.menuYes {
color: green;
}
.menuNo{
color: red;
}
This combination of JavaScript and style sheet will cause the text for the
Jungle Adventure to change to red if the age of the ride user is less than 6
and to green for any other age. We must implement this construction for all
the other rides in the theme park. A friend of ours is looking for some free
access to the Theme Park, so we decide to subcontract the work to him. He
is an experienced programmer (or at least he has read a couple more books
than we have). He does the work, gets his Theme Park tickets, and hands
over the finished program. The new program seems to work well, and the
owner of the theme park is pleased with it at first. However, after a while,
he starts to get complaints from riders about incorrect displays for the
Downhill Mountain Run ride. We need to find out what has gone wrong.
PROGRAMMER’S POINT
Always respond constructively to fault reports
I’ve had my share of bugs over the years. I learned quickly that
customers appreciate a positive response to their fault reports. It is
important to remember that when you are fixing a fault, your loyalty is
to solving the problem, not finding out who caused it. I never made a
fuss when a bug turned out not to be my fault, and I always accepted
responsibility when it was. By being constructive in my approach to
fault reports, I could turn a negative into a positive, so that my
customers would end up praising my fault-fixing skills rather moaning
about my buggy code.
CODE ANALYSIS
Fixing faults
Programs contain bugs because they are created by fallible humans. We
get a bug when, for whatever reason, a program does something that it
should not. A bug becomes a fault when it affects the user in some way.
It seems that there is a bug in the ride program that is causing the faulty
display. Let’s open the program in the Ch06 Repeating actions\Ch06-
01 Broken Ride Selector folder and take a look.
Answer: We’ve been told that the Downhill Mountain Run ride
display is not working properly. Only riders who are 12 years or over
can use this ride. Let’s start with an age that is less than 12:
This test shows that the program is working correctly for 8-year-old
riders. They should not be allowed on the Downhill Mountain Run or
the Regurgitator. Let’s try 12—an age that should work.
var downhillMountainElement=
document.getElementById("downhillMountain");
if (ageNo < 12) {
downhillMountainElement.className = "menuNo";
} else {
jungleAdventureElement.className = "menuYes";
}
var downhillMountainElement=
document.getElementById("downhillMountain");
if (ageNo < 12) {
downhillMountainElement.className = "menuNo";
} else {
jungleAdventureElement.className = "menuYes";
}
The error is in the else part. I’ve highlighted it above. Rather than
setting the className on the downhillMountainElement, it instead
works on the jungleAdventureElement. The program is deciding
correctly that the rider can go on the Downhill Mountain Run ride,
but then it is displaying the result on the wrong element.
Answer: This bug is easy to fix. We just need to change it so that the
correct element is updated when the rider can go on the ride.
Click here to view code image
var downhillMountainElement=
document.getElementById("downhillMountain");
if (ageNo < 12) {
downhillMountainElement.className = "menuNo";
} else {
downhillMountainElement.className = "menuYes";
}
Answer: The primary cause of the fault was a lack of proper testing.
If the program had been properly tested, the fault would have shown
up. However, the practice of using block copy when writing the code
made the bug possible. We should try to write our solutions in a way
that reduces the number of ways they could go wrong. This includes
not using block copy to repeat sections.
PROGRAMMER’S POINT
Design is important
You might think that worrying about the internal design of a program is
a waste of time. If the program works, why do we need to care about
how it fits together? However, it is important that you always strive to
make your code well designed. If you are still not convinced, consider
the implications of a bug in the Theme Park Ride Selector that allowed
a three-year-old to go on the Regurgitator ride. The child might be
injured, and the Theme Park owner would be in a lot of trouble. An
investigation might conclude that we were at fault for not using best
practice when creating the code.
When we make a solution, we should try to make it easy to understand
how it works. Bugs can appear when one programmer modifies the
work of another and doesn’t fully understand how the original code
worked. The easier that program is to understand and the smaller the
number of required changes, the lower the likelihood of bugs being
introduced. We will look at design techniques throughout the rest of this
book.
The HTML above is like the earlier list of theme park rides, but each of the
list items now has a data-MinAge and a data-MaxAge attribute. These give
the age limits for each of the rides. This information about rides and ages is
now all held in one place. The JavaScript program can use the getAttribute
method provided by an element to read the contents of a data attribute.
The code above shows how this would work for the Carnival Carousel ride.
Note that the value of an attribute is a string of text, so the Number function
is used to convert the text into a numeric value. Once the program has the
maximum and minimum ages, it can then update the display to indicate
whether the rider can go on the ride.
Click here to view code image
if(ageNo<carnivalMinAgeNo){
carnivalCarouselElement.className="menuNo";
} else {
if(ageNo>carinvalMaxAgeNo){
carnivalCarouselElement.className="menuNo";
} else {
carnivalCarouselElement.className="menuYes";
}
}
CODE ANALYSIS
Data attributes
You may have some questions about data attributes. Let’s see if we can
answer them by looking at some code. Start with the sample application
in the Ch06 Repeating actions\Ch06-03 Data Ride Selector example
folder. Open this in your browser. Enter an age of 2 and click Check
Your Rides. You will see the display below.
Question: Why are the two ride names shown in different colors?
Answer: The Scenic River Cruise text is green because the minimum
age attribute for Scenic River Cruise list item is 0, and an age of 2 is
greater than 0. The Carnival Carousel text is red because an age of 2
is less than the minimum age for that ride, which is 3.
Question: What is the upper limit for the age of the Carnival Carousel
ride?
When you press Enter, the variable is created, and the statement that
created the variable returns a value of undefined. Now we can use
the getAttribute method to get data out of this element. Enter the
following statement:
> carnivalCarouselElement.getAttribute("data-MaxAge");
<- "120"
This returns the value 120, which is the contents of the data-MaxAge
attribute in the Carnival Carousel element. This means that the
maximum age for that ride is set to 120 years. You can use the same
method to read the minimum age value.
Answer: Let’s try it. Enter the statement below, which looks for a
data attribute called data-SillyAge:
> carnivalCarouselElement.getAttribute("data-SillyAge");
<- null
This call of getAttribute returns null, which is how JavaScript
indicates that a reference value doesn’t refer to anything. In other
words, the getAttribute method couldn’t find anything, and so it
returned a value that indicates that nothing was found. We could use
an if construction to test for a value of null, so our program could
do something sensible if a data attribute is not found.
We can test this by reading back the value of the maximum age:
Answer: Yes, it can. This is a good way to store data values inside
your web page.
The HTML above shows the list of rides in the Theme Park as they are
displayed. Each of the rides is described by a list item (<li>) element and
all the lists are enclosed inside an unnumbered list (<ul>) element. The <ul>
element is a container element that holds other elements. In this case, the
list contains five list items. These list items are called the children of their
container elements. HTML elements provide methods that can be used to
access the children of an element. Let’s investigate.
When you press Enter, the JavaScript console returns the result as
undefined because, as we know, the process of creating a variable does
not return a value. However, the variable rideListElement now refers to
the list of rides. To prove this, just type the name rideListElement, and
the Developer View will show you the HTML in the element it refers to:
When you press Enter this time, the JavaScript console displays the
element. Click the little right-pointing arrow to expand the display.
The list has five children, which are the list items. These children are
held in a property of the list, which is called children. We can use an
index to specify which of the children we want to look at. The index is
expressed as a number enclosed in square brackets ([]): Let’s have a
look at the element at the start of the list. Type in the statement below.
Note that this is the element with an index of 0. When counting items in
a container, JavaScript starts counting at zero, not one. When you press
Enter, the list item for the Scenic River Cruise is displayed.
You can use this technique to obtain any of the items in the list. The
statement below will view the list item for the Regurgitator. I tried it
with a different number:
There is not a fifth element in the list (although the film The Fifth
Element is a classic). The result of trying to find a non-existent element
is the undefined value:
<- undefined
We can find out how many children there are by using the length
property of children. Try this statement to see how it works:
<- 5
CODE ANALYSIS
The for loop
We can use the Developer View in the browser to investigate what a for
loop does. Open the application in the Ch06 Repeating actions\Ch06-
04 Theme Park Ride For Loop folder (if you haven’t already) and then
open the Developer View by pressing F12.
Question: What does the for loop we have created actually do?
Answer: We can start by typing in the JavaScript that you have just
seen in Figure 6-4:
You know (because I’ve told you) that this should repeat the
statement console.log(i) 10 times—whatever that does. Press Enter
to see what happens.
Question: Why does the for loop display undefined at the end.
Answer: The for loop does not display this message. This message
is displayed because the console always displays the value of a
statement. A for loop construction does not generate a result in the
same way that creating a variable using var does not generate a
result. In both cases, the value undefined is displayed by the console.
Question: What does the word let mean in front of the declaration of i?
> i;
This variable no longer exists because it was deleted when the for
loop was completed.
Answer: This loop is silly. The loop sets i to 0 and then continues
while the value of i is greater than 10. Because the value of i is not
greater than 10, the loop will never be performed. If you run this
code, you will discover that it does not produce any output.
> undefined
Question: What happens if I put in a loop that will never end? (Please
don’t actually run this statement before reading the answer.)
Click here to view code image
> for(let i=0;i<10;i=i-1)console.log(i);
Answer: This loop is also silly. Each time around the loop, the value
of i is reduced by 1 rather than increased by 1. This means that the
value of i will never reach 10, so the loop will run forever. If you run
this statement (and I don’t advise it), you will notice that the console
will be filled with ever-decreasing numbers, the fan on your
computer will come on, and your browser will become strangely
unresponsive as it tries to run this loop as quickly as possible. The
only way to stop this that always works is to close the browser tab
holding the program. Sometimes when you visit a web page, you
find that your browser gets “stuck.” Now you know one way that it
can happen.
Now that we know about for loops, we can write the code for the Theme
Park Ride Selector.
I love this code. I really like how it works. You should spend some time
looking through it to make sure that you understand how it fits together. To
appreciate how well designed it is, consider what changes you would have
to make to the program if the theme park added another ride. The wonderful
answer is that you would not have to change this code at all. You would just
have to add another item to the list in the HTML file. You also don’t have to
change the program code if the age rating on one of the rides is changed.
You just change the data in the HTML file and the program keeps going.
The example solution in the folder \Ch06 Repeating actions\Ch06-05 Lots
of Theme Park Rides has lots of additional rides, but the JavaScript
program code is the same.
PROGRAMMER’S POINT
Great programmers are “constructively lazy”
You can spot a great programmer by the way that they use their skills to
avoid hard work. I call this “constructive laziness.” If I find myself
having to write lots of code or worrying about synchronizing different
parts of a solution, I will try to find a way of using a loop and bringing
things together into one place.
Work through collections using for-of
We’ve seen how we can use a for loop to count through a range of values.
We might find a use for this a bit later in the chapter, but we can also use a
new form of the for loop to directly work through the items in a container.
The for – of loop was not added to make something possible; we already
know how to solve the problem. It was added to make something easier.
The loop above shows how it would be used. The loop will be performed
for each of the children of the ride list. Each time round the loop the value
of rideElement is set to the next child. There is no need to create a control
variable and the code is much simpler. You can see a for-of loop in action
in the example in Ch06 Repeating actions\Ch06-06 For of loop.
We could use a 12-element list to hold the results and then update the text in
the list items with the multiplication table that the user has requested in the
same way that we update the color of each ride entry. However, that would
mean we would have to type in a 12-element list, and that sounds like a bit
too much work to me. So let’s start with an empty HTML document and
then write some JavaScript to fill in the multiplication table results by
creating list items.
This is the HTML page for the multiplication table application. Note that in
the middle there is an empty list with the ID multiplicationTableList. This
is going to hold the multiplication table that the program will generate. The
user will press the Make the multiplication table button, which will call the
JavaScript function doMultiplicationTable to create the table. Let’s have a
look at that.
Click here to view code image
function doMultiplicationTables() {
The most interesting part of this function is the last three statements, which
create a new element and add it to the list. Let’s take a look at how they
work.
CODE ANALYSIS
Building HTML from JavaScript
Take as your starting point the example application in the Ch06
Repeating actions\Ch06-07 Times Tables HTML generator folder.
Open this application and then press F12 to open the Developer View.
Question: Does the program work?
Now that we have our new element, we can set the innerText that it
contains. Type in the following and press Enter:
We now have an HTML element that is a list item containing the text
Hello world.
Answer: We can add a new child to any HTML element using the
appendChild method to add a new child to the element. First, we need
to find the element we want to add to. Type the following statement
and press Enter:
Click here to view code image
> var multiplicationTableListElement =
document.getElementById("multiplicationTableList");
> multiplicationTableListElement.appendChild(newElement);
If you look back at the web page you will discover a new line has
appeared underneath the last line of the times table. This line was
added by us just now:
This new element is not part of the HTML file; it is part of the
document object that is being maintained by the browser.
Answer: Yes, you can. In fact, there is a bug in our solution, which
means that it just keeps adding multiplication tables to the list. If you
press the Make the multiplication table button again, you will
discover that another table will be added to the page:
Question: Can a program delete items from an element?
Answer: Yes, it can. We can delete the element at the start of the list
by entering the following:
> multiplicationTableListElement
.removeChild(timesTableListElement.children[0])
Figure 6-6 above shows the structure of a while loop. The while loop will
perform the test and then, if the test is “truthy,” it will perform the
statement. It will then loop back and repeat this process until the test is
“falsey.” We can use this to create some JavaScript that will delete child
elements until there are none left:
Click here to view code image
while(multiplicationTableListElement.children.length > 0)
multiplicationTableListElement.
removeChild(multiplicationTableListElement.children[0]);
OceanofPDF.com
7
Creating functions
What you will learn
Functions are an essential part of program design. You can use functions to
break up a large solution into individual components and to create libraries
of behaviors that can be used by your programs. We have used some built-
in functions (for example, alert) and created event handler functions (for
example, doCheckAge). In this chapter, you’ll learn how to create and use
functions of your own. You’ll see how to give functions data to work on and
how a program can receive results that a function returns. Along the way,
you will pick up some tips about error handling.
CODE ANALYSIS
Investigating functions
Start by opening the application in the Ch07 Functions\Ch07-01
Greeter Function example code folder. This application contains an
HTML page with the output paragraph and a script section containing
the greeter function. Open the Developer View by pressing F12.
Answer: Up until now, our programs have used functions that have
been provided for us by JavaScript (for example, the alert function).
But the greeter function is one that we have written. However, we
can call it in the same way, simply by entering the name of the
function, followed by a pair of braces.
> greeter();
When you press Enter, the greeter function is called. This function
does not return a result (we will look at this later) and so the console
displays undefined.
<- undefined
However, you will notice that the word “Hello” has now appeared in
the browser display. This was displayed by the greeter function
when it ran.
Question: Can we define functions in the console?
Answer: Yes, we can define our own functions in the console. Type
the statement below, which creates a function called alerter.
<- undefined
The JavaScript that you have just typed contains a statement that
calls the alert function, but this has not run because this statement is
in the body of the alerter function. Now enter a statement that calls
the newly created function:
> alerter();
When you press Enter, the statement will call alerter, which will
display an alert:
<- undefined
Question: Can one function call another function?
function m3(){
console.log("sat on");
m2();
}
function m1(){
m2();
console.log("cat");
m3();
console.log("mat");
}
> m1();
When you press enter the m1 function is called. This then calls m2 and
so on. The output is what you would expect:
the
cat
sat on
the
mat
The mirror function just contains one statement that calls the mirror
function. What happens when we create the function. Press Enter to
find out.
<- undefined
When you press Enter, JavaScript will find the mirror function and
start obeying the statements in it. The first statement in mirror is a
call of the mirror function, which JavaScript will start to execute.
The program is stuck in a loop, but it does not get stuck forever.
After a while, the console stops with an error:
Figure 7-1 shows the form of a JavaScript function definition. We can work
through each of these items in turn. The keyword function tells JavaScript
that a function is being defined. JavaScript will allocate space for the
function and get ready to start storing function statements. The word
function is followed by the identifier of the function. We must create an
identifier for each function we define. Because a function is associated with
an action, it’s a very good idea to make the name reflect this. I give
functions names in the form verbNoun. The verb specifies the action the
function will perform, and the noun specifies the item it will work on. An
example would be doMultiplicationTables.
After the function identifier, we have the arguments that are fed into the
function. The arguments are separated by commas and enclosed within
parentheses. Arguments provide a function with something to work on. So
far, the functions we’ve created haven’t had any arguments, so there has
been nothing between the two parentheses. Finally, the definition contains a
block of JavaScript statements that form the body of the function. These are
the statements that will be obeyed when the function is called.
Give information to functions
The greeter function shows how functions can be used, but it isn’t really
that useful because it does the same thing each time it’s called. To make a
function truly useful, we need to give the function some data to work on.
You’ve already seen many functions that are used in this way. The alert
function accepts a string to display in the alert box. The Number function
accepts an input to be turned into a numeric value. We could make a version
of the greeter function that accepts a message to be displayed:
Click here to view code image
function greeter(message) {
var outputElement =
document.getElementById("outputParagraph");
outputElement.textContent = message;
}
CODE ANALYSIS
Investigating arguments
The new version of greeter is in the example application Ch07
Functions\Ch07-02 Greeter Arguments. Open this application and
then open the Developer View by pressing F12.
When you press Enter, the greeter function is called and the string
Hello from Rob is passed as an argument to the function call.
<- undefined
The greeter function does not return a value, so the console displays
undefined. However, you will notice that the phrase Hello from Rob
has now appeared on the browser display. This was displayed by the
greeter function when it ran.
Question: What happens if I omit the argument from the function call?
> greeter();
You might think that this would cause an error. The greeter function
is expecting to receive something that is missing from the call. If
you’ve used other programming languages, for example C++ or C#,
you will be used to getting errors if you make this mistake. However,
it turns out that JavaScript is much more relaxed about this. There is
no error, but there’s no greeting either:
This is what has happened:
function errorGreeter(message) {
if(message == undefined) {
alert("No argument to greeter");
}
else
{
let outputElement =
document.getElementById("outputParagraph");
outputElement.textContent = message;
}
}
> errorGreeter();
When you press Enter, you will see an alert because the function was
not supplied with an argument.
If you call greeter as above, JavaScript will not produce any errors,
but the greeter function will ignore the extra arguments.
Arguments and parameters
From the title of this section, you might expect that we will have a
difference of opinion, but in JavaScript, the word argument has a particular
meaning. In JavaScript, “argument” means “that thing you give to the call
of a function.”
greeter("Hello world");
In the above statement, the argument is the string Hello world. So when
you hear the word “argument,” you should think of the code that is making
a call of the function. In JavaScript, the word parameter means “the name
within the function that represents the argument.” The parameters in a
function are specified in the function definition.
function greeter(message)
This is the definition of a greeter function that has a single parameter. The
parameter has the identifier message. When the function is called, the value
of the message parameter is set to whatever has been given as an argument
to the function call. Statements within the function can use the parameter in
the same way as they could use a variable with that name.
When you press Enter, the console will create a variable called test that
contains the value 100. We can use the test variable as an argument to
the whatWouldIDo function:
> whatWouldIDo(test);
When the function has been called, the question we must consider is
“What value does test now contain?” Does it contain 0 (the value set
when it was created), or does it contain 99 (the value set in the function
whatWouldIDo)? We can answer the question by asking the console to
display the value of test:
> test
<- 0
When a function is called, the value in the argument is copied into the
parameter. So any changes to the parameter will not affect the argument
at all.
This function creates a style element using a supplied color name. The style
is then applied to the output element along with the greeting text. We then
provide arguments giving the string to be displayed and the color of the
text:
Click here to view code image
colorGreeter("Hello in Red", "red");
This call of colorGreeter has supplied the color name before the
greeting text. In other words, they are the wrong way round. This would
result in the colorGreeter trying to display the message “red” in the
color “Hello in Red.” This would not cause an error, but it would result
in the program not doing what you want. So when we make calls to
functions, we need to make sure that the arguments that are supplied are
given in the same order as the parameters. You can find the colorGreeter
function in the Ch07 Creating functions\Ch07-04 Color Greeter
folder.
This statement creates a variable called age, which contains a number with
the value 12.
Click here to view code image
> makeGreen(outputElement);
This will cause the text of the paragraph on the web page to turn green
because the makeGreen function has set the style property of the element
to which it has received a reference:
> makeGreen(21);
The result of this statement is that nothing happens. No error is produced
even though it is not meaningful to try to set the style of a numeric value
to 21. Any mistakes that you make with function arguments will not
produce errors; instead, the program will just keep running.
Arrays of arguments
There is another way that we can pass arguments into a JavaScript function
—an array of items. We will discuss arrays in detail in the next chapter. An
array is a form of collection. We have already seen one form of collection.
The unordered list that we used to display ride information in the Theme
Park in Chapter 6 held elements in the form of an array of items. We used
the for–of loop construction to work through the array. If you’re not sure
about how this works, take a moment to return to Chapter 6 and read “Work
through collections using for-of.” Within a function, the keyword
arguments means the array of arguments that were given when the function
was called.
The function calculateSum shows how this works. It uses a for-of loop to
calculate the total of all the arguments given to the function call. This total
value is then displayed on the page. The function can be called with any
number of numeric arguments:
Click here to view code image
calculateSum(1,2,3,4,5,6,7,8,9,10);
This would display the value 55. Of course, if you do something silly, you
might not get what you expect.
Click here to view code image
calculateSum(1,2,3,"Fred","Jim","Banana");
This call of the function would not cause an error. It would display the
result 6FredJimBanana. This is because of the way that JavaScript combines
strings and numbers. You can find out more in Chapter 4 in the section
“Working with strings and numbers.” You can find this sample code in
Ch07 Creating functions\Ch07-06 Argument arrays.
This statement uses the Number function. The function accepts an argument
(text expressing a number) and returns a value (the text as a numeric value).
We can write our own functions that return a value.
The settings in Figure 7-2 will produce a value in the range 1 to 50 that
could be used to play a bingo game. Let’s take a look at the code.
We have seen this kind of page before. There is some text to tell the user
about the application. There are two input fields, which are used to get the
minimum and maximum values for the random number to be produced.
There is a Roll the Dice button to trigger the generation of the value and an
output paragraph that displays the result. This page is very similar to the
one used by the Theme Park Ride Selector application in Chapter 6. The
function doRollDice is called when the user clicks the button to roll the
dice.
Click here to view code image
onclick="doRollDice('minNoText','maxNoText',
'outputParagraph');"
This is the onclick attribute for the Roll the Dice button. This attribute
contains a string of JavaScript code that will be obeyed when the button is
clicked. If you’re not clear on how this works, take a look in the section
“Using a button” in Chapter 2 for a refresh. The JavaScript that runs when
the button is clicked makes a call of the function doRollDice.
Click here to view code image
doRollDice('minNoText','maxNoText', 'outputParagraph');
The doRollDice function has three arguments, which are the ID strings for
the minNoText, maxNoText, and outputParagraph elements in the web page.
The function gets the minimum and maximum values from elements
identified by the first two arguments to the function call. It then calculates
the random result and then displays the result using the output element
identified in the third element. We can take a look at this function to see
how it works:
The function looks very small. It gets in the minimum and maximum
values, calls getCustomDiceSpots to get the random value, and then displays
the result. The function is small because it uses another function called
getNumberFromElement to get the maximum and minimum values:
This function is given the identifier of an input element on the web page as
a parameter. It fetches a number from the specified input element. We can
use this function in any program that needs to read numbers from the user.
It gets a reference to the element with the identifier that has been supplied
as a parameter, gets the text from this element, converts the text into a
number, and then returns the number to the caller. The function is called
twice in the dice application—once to read the maximum value and once to
read the minimum value. If I had an application that needed 10 inputs to be
read from the screen, I could call this function 10 times in the application.
PROGRAMMER’S POINT
Designing with functions
Functions are a very useful part of the programmer’s toolkit and form
an important part of the development process. Once you’ve worked out
what a customer wants the application to do, you can start thinking
about how you’ll break down the program into functions. Once you’ve
specified the behavior of each function in the application, you can write
the function headers (in other words, pick the function name, the
parameters, and any return value), and then you could even get
someone else to write that function for you.
Functions save you from writing too much code. Often, you find that as
you write a program, you write code that repeats a particular action. If
you do this, you should consider taking that action and turning it into a
function. There are two reasons why this is a good idea:
First, it saves you writing the same code twice; and secondly, if a fault
is found in the code, you only need to fix it in one place.
Functions also make a program easy to test. You can regard each
function as a “data processor.” Data goes into the function via the
arguments, and output is produced via the return value. We can write
what is called a “test harness” to call a function with test data and then
check to ensure the output is sensible. In other words, we can make a
program that tests itself. We will look at this later in the book.
.menuInputError {
background-color: red;
font-size: 1em;
width: 2em;
}
Question: What does NaN mean? And what is the isNan function doing?
Question: What are the min and max attributes? Where do they come
from?
The HTML above is the input element for the minimum value. The
min and max attributes are set to 1 and 99 respectively. The
getNumberFromElement function can get the values of these attributes
and then use them to perform input validation:
The function can then use these values to validate the number
entered by the user.
Question: Why does the function sometimes return the value NaN?
PROGRAMMER’S POINT
You need to attack errors
I can be a very depressing person to have at a project meeting,
particularly at the start of the project. I’ll keep searching for things that
could go wrong and things we need to worry about. I’ll also try and
involve the customer in this process and make sure we find out what
should happen when things fail. I’m not doing this because I have a
tendency to worry about things (although I probably do). I’m doing this
because I don’t want to be tripped up by unexpected problems. If you
are making something you care about, you should take the same
approach.
function fvar2() {
var i=99;
}
function fvar1(){
var i=0;
fvar2();
When a function returns, all local variables are destroyed. The code above
shows two functions that contain local variables. Both fvar1 and fvar2 use
a variable called i. If we call f1var, JavaScript follows this sequence:
1. The function fvar1 is called.
2. The first statement of fvar1 creates a variable called i and sets it to 0.
3. The second statement of fvar1 makes a call to fvar2.
4. The first and only statement of fvar2 creates a variable called i and
sets it to 99.
5. The function fvar2 finishes and control returns to the third statement
of fvar1.
6. The third statement of fvar1 prints out the value of i.
The question we must consider is this: “What value is displayed in the
console?” Is it the value 0 (which is set inside fvar1), or is it 99 (which is
set inside fvar2)? If you’ve read the first part of this section, you know the
value that will be printed is 0. The variables both have the same name (they
are both called i), but they each “live” in different functions.
JavaScript uses the word scope when talking about variable lifetimes. The
scope of a variable is that part of a program in which a variable can be used.
Each version of i has a scope that is limited to the function body in which it
is declared This form of isolation is called encapsulation. Encapsulation
means that the operation of one function is isolated from the operation of
other functions. Different programmers can work on different functions
with no danger of problems being caused by variable names clashing with
each other. Now take look at this pair of functions:
Click here to view code image
function f2() {
i=99;
}
function f1(){
i=0;
f2();
Can you spot the difference? These two functions don’t use the keyword
var to declare their variables. Is this important? Yes. It turns out that
variables declared without the var keyword are made global to the whole
application, so f1 and f2 are now sharing a single global variable called i. If
we call the function f1, it will print the value 99 because the call of f2 will
change the value of the global variable i. This means that you should
always use var to declare variables in your functions unless you specifically
want to share them. In Chapter 4, in the section “Global and local
variables,” we discovered a situation where a program needs to have a
variable that has global scope. Now we are starting to understand how this
works.
The function letDemo shows how this all works. It contains two versions of
i. The first version is declared as var and exists for the entire function. The
second version is declared inside a block and is discarded when the
program leaves that block. Note that within the block it is not possible to
use the outer version of i because any references to i will use the local
version. In this case, we say that the outer variables is scoped out. The
function also contains a variable called j, which is declared inside the inner
block. However, because j is declared as var, it can be used anywhere
inside the function. These functions are declared in the example program in
the Ch07 Creating functions\Ch07-10 Variable scope folder.
If you find this confusing, then I apologize. The best way to understand it is
to consider the problem that they are trying to solve (stopping lots of cooks
fighting over the same pots and pans) and then work from there. The most
important point is to always use var or let when you create a variable.
Otherwise, you may find yourself a victim of very strange bugs in your
programs.
OceanofPDF.com
8
Storing data
What you will learn
You might find this surprising, but you’ve already learned most of what you
need to know to tell a computer what to do. You can write a program that
gets data from the user, stores it, makes decisions based on data values, and
repeats behaviors using loop constructions. You also know how to use
functions to break a solution down into components. These are the
fundamentals of programming, and all programs are built on these core
capabilities.
However, there is one more thing you need to know before you can write
most any kind of program. You need to be able to write programs that can
manage large amounts of data. In this chapter, you’ll learn just that, along
with some extremely powerful JavaScript techniques for working with the
HTML Document Object Model (DOM) that underpins the display of a
page.
Collections of data
Investigating arrays
Use the debugger to see code run
Highlight the best and worst sales locations
What you have learned
Collections of data
Your fame as a programmer is beginning to spread far and wide. Now the
owner of an ice-cream parlor comes to you and asks that you write a
program to help her track sales results. She currently has six stands around
the city selling ice cream treats. What she wants is quite simple—she wants
a program where she can enter the sales value from each stand and then get
the total sales from all of them, as well as the best and worst sales. She
wants to use this analysis to help her plan the location of her stands and
reward the best sellers. If you get this right, you might be getting some free
ice cream, so you agree to help.
As usual, the starting point for your program is a design that shows how the
application should look. Figure 8-1 shows what the customer has drawn up.
She wants to enter the sales values and then press a Calculate button to
display the analysis. Because you have read Chapter 7 and you know about
error handling, you ask her about the upper and lower limits on the data
values and what the program should do if any of the values are out of range.
Your customer hasn’t thought of this, but you discuss the application and
agree on some additions to the design as shown in Figure 8-2.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Ice Cream Sales</title>
<link rel="stylesheet" href="styles.css">
<script src="icecreamsales.js"></script>
</head>
<body>
<p class="menuHeading"> 🍦 Ice Cream Sales</p>
<p>
<label class="menuLabel" for="s1SalesText">Stand 1 sales
(0-10000):</label>
<input class="menuInput" type="number" id="s1SalesText"
value="0" min="0"
max="10000">
</p>
<p>
<label class="menuLabel" for="s2SalesText">Stand 2 sales
(0-10000):</label>
<input class="menuInput" type="number" id="s3SalesText"
value="0" min="0"
max="10000">
</p>
<p>
<button class="menuText"
onclick="doCalc()">Calculate</button>
</p>
</body>
</html>
This HTML contains an input field for each of the six sales that are to be
entered by the user. (The listing above only shows the first two to save
space.) Each input field has an id attribute so that the program can find it
and load the value stored in it. The input field uses a new feature of HTML
that we have not seem before, the label, as shown in Figure 8-3.
Figure 8-3 Single data entry element
<p>
<label class="menuLabel" for="s1SalesText">Stand 1 sales (0-
10000):</label>
<input class="menuInput" type="number" id="s1SalesText"
value="0" min="0"
max="10000">
</p>
The label and the input are held inside a paragraph. The label contains the
label text for the input. It also contains a for attribute that matches the id of
the target of the label. Both the label and the input are assigned style sheet
classes to manage their appearance on the page.
One problem with this design is that our program needs a test like this for
all six sales values, so we need to write five more tests. Then we need
another six tests to determine the lowest sales value, and if the ice cream
parlor owner sets up more ice cream stands, this would make our program
even more complex.
We have hit this problem because we have started from the wrong place.
Sometimes, it is a good idea to use an existing program as the basis of a
new one, but we have discovered that a design created to work with two
values (the maximum and minimum values for a random number) does not
scale up very well. We must do a lot of work to extend this structure to read
in and manipulate six values.
I’ve watched a lot of people learn to program, and I’ve seen quite a few
work much harder than they needed to because they took something that
they know how to do and tried to extend it to do a different task. This is a
bit like trying to dig the foundations of a house with a spoon just because
you know how use a spoon but don’t fancy learning how to drive the
mechanical digger. We have already decided that the best programmers are
“creatively lazy.” This might be a good point to try for some creative
laziness. If you find yourself having to repeat chunks of code, you might
want to stop and think about a better way of doing this. If you really want to
do this the hard way, I’ve put my partially completed version of the
program in the Ch08 Storing data\Ch08-01 Unworkable Ice Cream Sales
folder.
Creating an array
JavaScript also provides an array component that can be used to create
indexed storage of a collection of data values. Each item in an array is
called an element. A program addresses a particular element in the array by
using an indexer, which is a number that identifies the element in the array.
Some programmers refer to an indexer as a subscript. Let’s investigate how
arrays work.
Investigating arrays
Start by opening the application in the Ch08 Storing data\Ch08-02
Array Ice Cream Sales folder in the example code. This application
works, so you can enter some data and check the results. We are just
going to investigate arrays from the developer console. Open the
Developer View by pressing the function key F12. Now we can start
typing commands into the JavaScript command prompt. The first thing
we are going to do is create an empty array. Type in the statement below:
When you press Enter, the JavaScript console creates an empty array
with the identifier sales. This action does not return a result, so the
console displays the message undefined:
We can ask the JavaScript console to show the contents of any variable
by entering the name of that variable. This works with an array, too.
Type in the identifier sales and press Enter.
> sales
<- []
The console shows us that the sales array is empty by displaying two
brackets with nothing between them. Now lets store a sales value in the
array. This statement will add an element at the start of the array:
When you press the Enter key, JavaScript must store the value 100 in the
array element with the index 0.
> sales
<- [100]
The console shows us that the sales array now contains a single value.
We can use an array element as we would use any other variable. What
do you think the following statement would do? Type it in and find out.
> sales
<- [101, 150]
JavaScript shows us the element at the start of the array (which has 101
in it) and the next element (which has 150 in it). JavaScript will add new
elements to the array each time whenever it needs to. You can think of
the array as “stretching” to hold whatever items it needs to.
The JavaScript in the Ch08 Storing data\Ch08-02 Array Ice Cream Sales
example program uses arrays to store the sales values. Below, you can see
the statements in the program that get the data into the array for analysis.
The statements above create an array called sales and then set elements in
the array with the sales values from the elements on the HTML page. Note
that because the array elements are indexed from 0, I’ve changed the IDs
for the input elements to match. In other words, the element at the start of
the array has an index value of 0 and is assigned a value from an element
with an ID that matches.
Click here to view code image
sales[0] = getNumberFromElement("s0SalesText");
PROGRAMMER’S POINT
Counting from zero is just something you will
have to get used to
If you are used to counting from 1, you will find that the way that
arrays count from zero is a bit irritating. However, you will just have to
get used to it, as it is how JavaScript (and lots of other programming
languages) work. Just remember that an array containing six elements
(like the sales array above) will index these in the range 0 to 5. Note
that this means that sometimes you will have count in one way for the
program (array elements 0 to 5) and another for the user (ice cream
stands 1 to 6).
At the start, we set the “highest I’ve seen” value to the value of the element
at the start of the array because this is the highest we’ve seen at the start of
the process. I can put this behavior into a function that will calculate the
highest value in any array that is passed into it.
A program can use the getHighest function to get the highest value from
any array of values. We can create helper functions called getHighest,
getLowest, and getTotal to use in our application.
function doCalc() {
sales[0] = getNumberFromElement("s0SalesText");
sales[1] = getNumberFromElement("s1SalesText");
sales[2] = getNumberFromElement("s2SalesText");
sales[3] = getNumberFromElement("s3SalesText");
sales[4] = getNumberFromElement("s4SalesText");
sales[5] = getNumberFromElement("s5SalesText");
var outputElement =
document.getElementById('outputParagraph');
outputElement.textContent = result;
}
The completed version of doCalc is shown above. It creates a sales array,
uses the analysis functions to create the results, and then displays them. You
can find this version of the program in the Ch08 Storing data\Ch08-02
Array Ice Cream Sales examples folder.
However, using this input type would not stop the user from directly
entering invalid values:
In this case, the user has accidentally pressed the minus key when typing
in the number and entered a negative value. The good news is that the
getNumberFromElement function that the program is using to read the
sales value will return a result of NaN (not a number) when it reads a
value outside the min and max settings for an element. (You can learn
more about how this works in Chapter 7 in the section “Add error
handling to an application.”)
The bad news is that our program will not handle this correctly. We can
fix the problem by using the way that JavaScript works with numbers.
Remember that any mathematical calculation involving the value “not a
number” will return a result of “not a number.” So if the total of all the
sales values is not a number this means that at least one of the sales
values is not a number. This is something our program can test for.
var result;
if (isNaN(totalSales)) {
result = "Please enter numbers in the correct range"
}
else {
var highestSales = getHighest(sales);
var lowestSales = getLowest(sales);
The code above shows how this works. If the totalSales value is not a
number, the result variable is set to an error message. Otherwise, result
is set to the calculated values. You can find this version of the program in
the example folder Ch08 Storing data\Ch08-03 Error handling Ice
Cream Sales.
The function uses a for loop to generate each input paragraph in turn by
calling the function makeInputPar. The end point of the loop is determined
by the noOfItems parameter. The values of the min and max parameters are
passed into the function makeInputPar. Let’s have a look at how this works.
<p>
<label class="menuLabel" for="s1SalesText">Stand 1 sales (0-
10000):</label>
<input class="menuInput" type="number" id="s1SalesText"
value="0" min="0" max="10000">
</p>
The input paragraph is composed of a label element that contains the Stand
1 sales (0-10000) label and an input element to receive the data. The label
and the input elements are assigned style classes to make it easy to manage
their appearance. The input element has min and max attributes that are used
by the browser to limit the values that the user can enter.
In our first version of this application, the input paragraphs were defined in
the HTML file for the application. There were six such paragraphs, one for
each of the ice cream stands. However, we can simplify the application by
using JavaScript to make the input paragraphs.
The function makeInputPar uses the createElement function provided by the
document object to create a paragraph element (inputPar) and give the
paragraph two child elements. The children are a label element
(labelElement) and an input element (inputElement). The makeInputPar
function is supplied with three parameters:
1. The label to be used for the input
2. The maximum input value
3. The minimum input value
A program could make the input element for the first ice cream stand by
making the following call:
Click here to view code image
var stand1input = makeInputPar("Sales 1", 0, 10000);
However, we are not going to do this because we are using a loop to create
the inputs and add them to a container.
CODE ANALYSIS
Input generation
We can see this input generation in action by using the JavaScript
console. We might also have some questions about it. Start by opening
the application in the Ch08 Storing data\Ch08-04 Input Generation
folder in the example code. This application contains an HTML page
which has been generated by the doBuildSalesInputItems function.
Open the Developer View by pressing F12.
Answer: Yes, we can. Click the Console tab to open the console.
First, we need a reference to the container element that holds the
input paragraphs. Type in the following and press Enter:
Now that we have our new paragraph, the next thing we do is add it
to the children of the container element:
This adds our newly created paragraph to the page. You should see it
appear. It will have the label “New Sales” and an input range of 1 to
99.
Above, you can see the new element (with the caption “New Sales”)
that has been added at the bottom of the list.
If the customer added more stands, we would then have to modify the
program and add more statements. For 12 ice cream stands, we would need
12 of these statements. There is a better way to do this. We can use a loop to
read the values from the HMTL elements. The loop will work through all
the input paragraphs on the page. The input paragraphs are children of the
sales item element.
Figure 8-4 shows how these elements are structured. On the left, we have
the div element with the ID salesElements that contains all the elements.
The div element contains six paragraphs, one for each ice cream stand. The
first paragraph gets the input for ice cream stand 1. It contains a label and
an input item. To get the user input, the program must work through the
sales items and extract the data from the input element.
CODE ANALYSIS
Reading numbers
Question: What is this code doing?
Answer: The input element contains max and min attributes that are
used by getNumberFromElement to validate the number that the user
types in. If the number the user has entered is outside this range, or
the user has not entered a number, the getNumberFromElement
function returns a result of Not a Number (NaN).
Question: Would I have to change this code if we added more ice cream
stands?
Answer: No. That’s the great thing about this loop. It will work
through any number of input paragraphs.
The display will show a red dot at that position as shown above. Click to
add a breakpoint. If you click in the wrong place, you can remove a
breakpoint by clicking the red dot. Once you have set the breakpoint,
click the Calculate button in the application to run the function. The
browser will call the doCalc function and then pause when it hits the
breakpoint.
The program is paused at the statement where we set the breakpoint. You
can see it highlighted in blue. We can use the transport controls to make
the program run one statement at a time.
The transport controls look a bit like Egyptian hieroglyphics. They are in
the top right-hand area of the screen in my browser, but they might be
somewhere else on yours. We will find out more about each control as
we go. For now, we want to use the Step control, which is indicated
above. Click this, and the program will execute the indicated statement
and then move on to the next one.
Note that the content of the sales array is shown for you. If you press
the Step button again you are shown the contents of the salePos variable.
You can keep pressing the button (or use the function key F9) to step
through the program. You can watch the program get a reference to the
sales element and then enter the for loop, which will work through the
elements. When the program calls the getElement function you will find
that the view moves into that function and you step through the
statements in that.
The getNumberFromElement function reads the text from an input element
and converts it into a number. Here, you can see that the text is 300 as a
string, and the result is 300 as a value. If you look back at the application
you will find that the first sale value is 300.
When you have seen enough you can press the transport control that
resumes normal program execution. If you leave the breakpoint set, you
will find that if you press the Calculate button in the application, it will
stop at the breakpoint the next time around.
You can spend as much time as you like working through code. You can
also use this technique to put breakpoints in any of the other sample
programs and watch what they do, too.
Now that you know how the program works, you can make the change
that adds two new ice cream stands to the system. The good news is that
you only have to change the value 6 to the value 8 somewhere in the
application. You can find my version in the examples in the Ch08
Storing data\Ch08-05 Eight Stand Version folder.
Your customer has had another idea. Rather than the application asking for
the sales of Stand 1, she would like the application to show named
locations, as shown in Figure 8-5.
var newArray=[];
The characters [ and ] mark the start and end of the array that is being
created. This statement creates an empty array, because there is nothing
between the [ and the ]. We set the values into an array when we create it
by putting values here:
var newArray=[1,2];
This statement creates an array called newArray that contains two numbers.
The element at the start of the array contains the value 1, and the next
element contains the value 2. This statement is exactly equivalent to these
three:
var newArray=[];
newArray[0]=1;
newArray[1]=2;
This statement creates a variable called standNames that contains the names
of all the stands. The item on the right of the assignment is the actual array.
We can also use arrays like this in function calls:
Click here to view code image
doBuildSalesInputItems('salesItems',0, 10000,
['Riverside Walk', 'City Plaza', 'Central Park', 'Zoo
Entrance',
'Main Library','North Station','New Theatre','Movie House']);
The text above comes from the HTML file for the application. The body
element can contain an attribute called onload, which contains a string of
JavaScript to be obeyed when the page is loaded by the browser. For this
application, the string of JavaScript calls the doBuildInputSalesItems to
create the input paragraphs for the sales values. You can find this function
used in the example program in the Ch08 Storing data\Ch08-06 Named
Stands folder.
CODE ANALYSIS
Creating named ice cream stands
This is all rather clever stuff. But you might have some questions:
changeArrayElement(testArray);
The input elements are not lined up vertically because the names of the
different locations are of different lengths. This is not a programming
problem, so we don’t need to make changes to the JavaScript, but it would
be useful to be able to modify the style of the labels for each item so that
they are the same size.
The CSS text above is the definition of the menuLabel style class, which is
used to style the menu label (hence the name). I’ve added two new
attributes to the style definition. The first tells the browser that this element
is a block that should be displayed inline with enclosing elements. The
second item sets the width of the element to 12 characters. If we make these
changes to the style sheet, the input display matches what the customer
requested in Figure 8-6. You can find this version of the application in the
Ch08 Storing data\Ch08-07 Named Stands fixed width example folder.
Hint: to do this the program must make a second pass through the sales
elements after it has determined the highest and lowest values. Any sales
elements with a sales value that matches the highest can be assigned a
yellow style class. Any sales elements with a sales value that matches the
lowest can be assigned a blue style class. This is the best way to do it
because it is possible to have several sales values that are the highest or
the lowest. You can find my version in the examples in the folder Ch08
Storing data\Ch08-08 Highlight High and Low.
Prototype HTML
The best way to show the lawyer what her program will look like is to
create a prototype that behaves in the same way as the finished product. We
can do this by creating an HTML page and then adding just enough
JavaScript to allow us to demonstrate how the program will be used.
This is the HTML for the prototype application. It defines the three input
areas and the two buttons. There is one new element on this page—the
textarea element.
The textarea will display a scroll bar if the user enters more than five lines
of text, and a textarea will automatically wrap text if the user types off the
end of the line. A JavaScript program can use the value property of a
textarea to interact with the content of the text area.
Prototype JavaScript
The third component of the tiny contacts application is the JavaScript that
provides the behaviors. The prototype application doesn’t do much. It just
displays contact information if the user searches for “Rob Miles” and
displays Contact not found if the user searches for any other name. The
Save Contact button just displays an alert when it is pressed.
You can find the prototype application in the Ch09 Objects\Ch09-01 Tiny
Contacts Prototype sample folder. You can use it to enter and search for
contact information. The application will only display output if you search
for a contact named “Rob Miles,” and it doesn’t store any entered data.
However, it’s very useful for demonstrating how the application will work.
Your client agrees that the application can work like this and says you can
start building it.
Helper functions
If you look closely at the prototype JavaScript code, you’ll notice a pair of
tiny functions. I’ve written these to help move data between the HTML
page and the application:
You might wonder why I wrote such small functions. They don’t make the
program much smaller. If I were to write the application without these
functions, it would only add a few statements. However, I think they do
make the program much clearer because the functions express exactly what
is being done without the distraction of how they work. For example,
consider the function that is called when contact information is not found.
At the time the function is called, we can tell from the name of the function
exactly what the program is doing.
Click here to view code image
function displayContactNotFound()
{
alert("Not found");
}
The data for a contact would be held in array elements with a particular
index value. In other words, contactNames[0] would hold the name of the
contact at the start of the storage, contactAddresses[0] would hold the
address, and contactPhones[0] would hold the phone number. Figure 9-3
shows how this works.
The elements at index 0 in each array hold the details for Rob Miles. We
can use the elements at a given index to build up a set of contact
information for a specific person. For example, Imogen Bloggs lives at
Immy Villas and has a phone number of (1234) 723523. We can write a
function that stores a contact at a particular index position in all the arrays:
storeContact(0);
Finding contacts
Now that we know how to store contact information, the next thing we can
work on is finding it. The customer wants to be able to search for contacts
by name. We need something that works through the stored contacts and
finds the position of the one we want to display. In other words, if asked to
find the entry for “Joe Smith” in the contact store shown in Figure 9-3, it
would return the value 2.
The findContactPos returns the position in the array of the contact with the
name supplied as a parameter. It uses a for loop to work through the
contactNames array, comparing each element in the array with the name it is
searching for.
CODE ANALYSIS
The findContacts function
The findContacts function is a very important part of the application.
You might have some questions about it.
Answer: The loop only runs as long as the value of pos is less than
the length of the array. An empty array has a length of 0. The initial
value of pos is set to 0 when the loop is set up. This means that the
loop is never performed if the array is empty because 0 is not less
than 0.
Question: What happens when a match is found for the name being
searched?
Answer: When the program finds a matching name, the value of the
index variable is returned to the caller. This is the position in the
array of the name.
For example, using the data store in Figure 9-3, the above statement
would create a variable called pos, which would be set to 1 by the
call of findContactPos.
Answer: If the name is not found in the array, the for loop will
complete without finding a match. The program would then move on
to the statement after the for loop, which returns the value Not a
Number (NaN) to indicate that the name was not found. It is perfectly
sensible for a function to contain more than one return statement.
Note that it is up to the program calling findContactPos to check to
see if the name was found.
This type of search behavior is common in systems that you use every day.
Whenever you use a credit card to pay for something, the bank’s computer
will use the credit card number to search for your bank account information
so that the transaction can be authorized and added to your statement.
Displaying contacts
The final function that we need is one that displays the contact on the
HTML page. This function is given a position in the contacts store and
displays the elements in each array at that position. It uses the
displayElementValue function that we saw earlier to display each item:
function displayContact(pos){
displayElementValue("name", contactNames[pos]);
displayElementValue("address", contactAddresses[pos]);
displayElementValue("phone", contactPhones[pos]);
}
Saving a contact
The final pieces of code that we need are the functions that respond to the
button presses in the application. When the user clicks the Save Contact
button, the function doSave is called by the browser. This function must
work in two different ways:
1. It must create a new contact store for a new contact.
2. It must update the contact information for an existing contact.
The doSave function gets the contact name from the web page and then uses
the findContactPos function to see if the contact store already contains
someone with that name. The findContactPos returns a value, which is
stored in a variable called pos. If the value of pos that is returned is not a
number (NaN), the function sets the value of pos to the length of the array, so
that the contact information will be stored at the end of the array.
Otherwise, the newly saved data will overwrite the existing data. I’ve added
some comments to this code to make it clear what each section is doing.
Click here to view code image
function doSave() {
if(isNaN(pos)){
// if we didn't find an existing contact name
// we store the contact on the end of the array
pos = contactNames.length;
}
storeContact(pos);
}
CODE ANALYSIS
The doSave function
The doSave function implements the editing behavior of the application.
You might have some questions about it.
Question: What does the function use the length of the contactNames
array for?
Question: What happens if the user changes the name of a contact and
then saves it?
if(isNaN(pos)){
displayContactNotFound();
}
else{
displayContact(pos);
}
}
You can find the complete application in the Ch09 Objects\Ch09-02 Array
Tiny Contacts folder. If you try it, you will discover that it works fine. You
can enter contact details, save them, and search for them.
The process of creating an object does not return a value, so when you
press Enter, you will see a familiar undefined message:
As usual with the JavaScript console, you can view the contents of a
variable simply by typing the name of the variable. Type in contact and
press Enter:
> contact
JavaScript shows you that the contact object does not contain any
properties.
> contact
<- {}
Let’s add a name property to the contact object. Type in the statement
below, which sets the name property of the contact object to the string
Rob Miles. Press Enter.
Let’s take a look at what has changed in the object. Type in contact and
press Enter to view the contents of the contact object:
> contact
The contact object contains one property which is the name of the
contact.
> contact
<- {name: "Rob Miles"}
The address is added to the contact, and the console shows us the value
assigned as before.
Type in the statement below to view the contact, and press Enter to see
what has been added to the contact.
> contact
The contact object now contains a name and address. We could keep
adding properties to match the requirements of our application.
Now let’s take a look at the object that refDemo refers to. Type in refDemo
and press Enter to get the console to display the object that refDemo
refers to.
> refDemo
Because refDemo refers to the same object as contact you will see the
same properties displayed.
The refDemo variable refers to the same object as contact. We can prove
this. Enter the following statement and press Enter:
Now, view the contents of the contact variable by typing its name and
pressing Enter:
> contact
Both contact and refDemo refer to the same object, so changes made via
refDemo will also change the object that contact refers to.
> contact
<- {name: "Rob Bloggs", address = "18 Pussycat Mews}
The name property is now Rob Bloggs. This change was not made via the
contact reference; instead, it was made via the refDemo reference.
Each of the objects in the contactStore array will have a set of properties
that are the stored data for that contact. To make this work, we will have to
modify some of the functions in our program. Rather than storing the
different parts of contact data in individual arrays, the storeContact
function now adds the elements as properties, which are added to a contact
object:
The first time the contacts page is opened, there will be no contacts
store. The page displays an alert to indicate this. Click OK in the alert to
clear it and press the F12 key to open the Developer View. Now move to
the Console tab so that you can enter some JavaScript. Programs use
local storage by placing strings of text in named locations. The method
to store an item in local storage is called setItem. Type the statement
below and press Enter.
When you press Enter, the method setItem will run and store the string
This is some test data we are storing at the location test. The
setItem method returns the value undefined.
We can use the method getItem to view the contents of an item stored in
local storage. Type in the statement below.
When you press Enter, the getItem method will run and return the
contents of that location.
> localStorage.getItem("test");
<- "This is some test data we are storing"
The content of location test will still be there if we return to this web
page after having shut down the browser. It will even be present after we
have rebooted our computer. We can see how the data storage for our
Tiny Contacts application works. Type some contact details into the
application and press the Save Contact button. The contact information
is held in a location called TinyContactsStore. Type in the following
statement to read the contents of this location.
> localStorage.getItem("TinyContactsStore");
When you press Enter, you will see the contents of the contacts store
now contains the data that was entered.
If you store some more contacts, you will find that they are added to the
stored item. If you restart your PC and then load the same application,
you will find that the contact information has been retained.
The functions setItem and getItem can be used to store and retrieve data in
local storage. If you want to remove the contents of a local storage, the
removeItem function can be used to remove an item. The statement below
would remove the TinyContactsStore item from the browser storage.
Click here to view code image
localStorage.removeItem("TinyContactsStore");
The JSON string above represents a contact store that contains a single
contact. If you look at it carefully, you can see some strings that are the
names of properties (for example, phone) and some strings that are values
(for example, +44(1234) 56789). The string above actually creates an array
(which is why the outer characters are square brackets—[ and ]). The array
contains a single object (which is the element enclosed in braces—{ and })
inside the array.
This is a quick way of creating JavaScript objects that we have not seen
before. Rather than creating an empty object, we have populated a new
object with three properties. Each property is given as the name of the
property, followed by a colon (:) and the value for that property.
Successive properties are separated by the comma (,) character. We now
have a variable called contact, which contains my details. If we just type
the name of the variable, the console will show us the contents:
> contact
<- {name: "Rob", address: "Rob's House", phone: "1234"}
The JSON string version of an object looks very like the JavaScript
representation, with the difference that the names of properties are also
enclosed in double quotes ("). Another method, called parse, can be used
to convert this string back into an object:
We can combine local storage and JSON to make two methods that will
save and load the contacts in the Tiny Contacts application.
The loadContactStore function is called when the page is first loaded. The
saveContactStore function is called each time a contact is saved. The name
of the local storage item to be used to store the contact data is held in a
variable called storeName. The value in this variable is set when the
application is started.
Click here to view code image
function doStartTinyContacts(storeNameToUse){
storeName = storeNameToUse;
if(!loadContactStore()){
alert("Empty contact store created");
}
}
<body onload='doStartTinyContacts("TinyContactsStore");'>
CODE ANALYSIS
Using JSON
JSON makes it much easier to move data between JavaScript
applications and also to store data in the form of strings. But you might
have some questions about it:
Answer: The reference is followed and the contents of the object are
inserted into the JSON. We’ve seen this in action already. The
contactStore in the Tiny Contacts application is an array of
references to objects. When it is converted into objects, each
reference is followed, and the object contents are inserted into the
string.
Answer: We’ve seen that JavaScript variables can hold values such
as Not an Number (NaN) or infinity. These values are stored in a
JSON string as the special value null, which is used in JSON to
indicate that a value is missing.
Question: What happens if the program tries to parse a string that does
not contain valid JSON text?
A JavaScript program can create an empty object and then add properties to
it. The two statements above create a contact object and adds a phone
property to the object. The new property is the string "+44(1234) 56789".
We have seen that programs can add properties to an object. The object acts
as a container for the property values that have been added to it. We can
identify these properties in the program by name as you can see above,
where we create a property called phone. This method is called dot notation
because the name of the property is given after a dot (.) in the program text.
A property accessor looks a lot like an array indexer. It is called bracket
notation because the property identifier is enclosed in square brackets. It
works a bit like an array, except that the item used as an index can be any
value. This makes a JavaScript object behave like a dictionary. One of my
favorite jokes is to tell someone that the word “gullible” is not in the
dictionary and then watch as they look up the word and proudly read it out
to me. A dictionary lets you look up definitions starting from a given word.
If you look up the word “gullible,” you will get a result along the lines of
“easily persuaded to believe something.” In JavaScript, if you look up a
property accessor, you get the value of the property with the specified
name:
The statements above show this works. The first statement creates an empty
object called contact. The second statement adds a property “phone” to the
empty object by using a property accessor. Note that the property accessor
is the string “phone.” This is a very powerful feature of JSON, but it can
also be a confusing one, particularly when you try to compare JavaScript
objects with JavaScript arrays. Let’s see if we can’t make things clearer.
Creating a new variable does not return a value, so the console displays
the familiar message undefined.
> contact
JavaScript will tell us that the contact object is empty by printing a pair
of curly brackets with nothing between them.
> contact
<- {}
Now, let’s add a name property to the contact object. Enter the
following and press Enter:
This statement returns the value being assigned, so the console prints the
value "Rob".
The contact object now contains a property called name, which contains
the value "Rob". Now let’s add another property, but this time, we will
refer to the property using a property accessor. Type in the statement
below and press Enter.
This statement adds a property called address, which is set to the value
"House of Rob". It also displays the value being assigned, as usual.
If we look at the contents of the contact object, we will see both of these
properties. Type in the statement below and press Enter to take another
look at the contents of the contact object:
> contact
At this point, you might start to think that a property accessor makes
every object look like an array. Let’s see what happens if we try to use an
object in the same way we would an array. The following statement tries
to store the string "Hello world" at element 0 of an array. Let’s try to do
that with the contact object. Type in the statement below and press
Enter.
Let’s take a look at the contents of the contact object. Type in the object
name and press Enter:
> contact
This is very confusing. The contact object now has a property called 0,
which contains the string "Hello world".
Click here to view code image
> contact
<- 0: "Hello world", name: "Rob", address: "House of Rob"}
> contact.0
JavaScript will not let you use a number as an object property identifier,
so this will generate an error:
> contact.0
VM142:1 Uncaught SyntaxError: Unexpected number
Property identifiers in a program must obey the same rules that are
applied to all JavaScript identifiers. However, we can still access this
property by using 0 as a property accessor. Type this statement and press
Enter to prove this:
> contact[0]
You have correctly identified a property and so JavaScript shows you the
value it holds:
> contact[0]
<- "Hello world"
The first statement creates a variable called propertyName that contains the
word "phone" as a string of text. The second statement uses the contents of
propertyName as property accessor. The effect of these statements would be
to change the phone property of the contact variable. If I want to create an
object with a particular set of properties, I can now do this from within the
program, rather than having to create the code by hand. Why is this useful?
Because it is how we can create a schema that describes the design of an
object and then use that schema to create the objects themselves.
PROGRAMMER’S POINT
Design the system before you build it
If you were making an airplane, you would make sure you had a design
before you started putting the wings on. The same is true with a
software project. It is vital that you consider what data is to be stored
and how it fits together before you start to write any code.
A large software system will contain many different components. At the
start of the design process, a programmer will focus on identifying the
components and how they are related. For example, a banking
application would contain customers, accounts, addresses, statements,
and transactions. The first part of the design process would be deciding
the relationships between these components in the system. For the bank,
we might decide that a customer can have multiple accounts but only
one home address. At this point, we are working at a high level of
abstraction. You can think of abstraction as a way of “stepping back”
from the problem you are trying to solve and trying to think about the
“bigger picture” surrounding the code that you are writing.
As soon as we had a high-level design, we would work with the
customer to make sure that the design can be made to do what they
want. Then we would move on to creating schemas for each of the
components, making sure to check with the customer that each
component holds the data that is required.
We are trying to avoid a situation right at the end of the project when
the customer asks something like, “Where do you hold the date of each
transaction?” If we had created the software as soon as we thought we
knew what was needed, this might be the first time we’ve heard of this
requirement, and it would need a lot of work to add it to the finished
system.
JavaScript property accessors let us create data objects that describe the
data items that are to be stored. These can then be used by the application to
create objects that will hold the data. We’ve already done this kind of thing
in the multiplication table and ice cream sales applications, where an
application creates the HTML page that will be used to enter data. Now we
are extending this process to allow an application to create bespoke objects
to hold data. If you look in the HTML page of the Ch09 Objects\Ch09-05
Universal Tiny Contacts application, you will find a call of a function—
doBuildPage.
function makeElement(description) {
// Create the enclosing paragraph
var inputPar = document.createElement("p");
case "textarea":
inputElement = document.createElement("textarea");
inputElement.className = "inputTextarea";
inputElement.setAttribute("rows",
description.rows);
inputElement.setAttribute("cols",
description.cols);
break;
// add new kinds of element here
}
The schema array holds the application together. It describes each of the
data items to be displayed by the editor and it is used to build the HTML
page and also to create each data object for storage. We can extend the
schema design by adding new types of data input, perhaps a number input
type.
You should be able to achieve this by only changing the contents of the
HTML file. If you get stuck, you can take a look at my version, which
you can find in Ch09 Objects\Ch09-07 Game Scores.
We can make the find process much easier by making the test ignore
whether the text was typed in UPPERCASE or lowercase. This can be
achieved by converting the search string and all the items it is searching for
to lowercase before performing the test:
Click here to view code image
function findDataPos(name) {
name=name.toLowerCase();
for(let pos=0;pos<dataStore.length;pos=pos+1){
let storedName=dataStore[pos].name;
storeName = storedName.toLowerCase();
if(storedName==name) {
return pos;
}
}
return NaN;
}
PROGRAMMER’S POINT
User ideas are often the best kinds of ideas
Making a great application is only the first step in making a successful
one. You also have to work hard to engage with your users and make
them into your sales force. We have seen that one way to do this is to
always respond constructively to error reports. Another good technique
is to engage with users and encourage them to suggest improvements.
This is a win-win proposition. They get a solution tailored to their
needs, and you get another feature that you can use to sell your solution.
Solve a problem
Making Super Search work is an interesting problem. I suppose you could
call it our first “proper” programming problem. By that, I mean that it is not
obvious how we can solve it. With all the other applications we have
created, we have been automating a behavior that we know how to do. We
knew how to calculate multiplication tables and add up ice cream sales
before we went anywhere near a computer. But for this problem, we don’t
know how to do what is being requested. So the best possible answer we
can give our lawyer friend is that we will think about it and get back to her
later.
The first step toward solving a problem is to determine whether the problem
can be solved. Trying to do the impossible never ends well. In this case, I
can tell you that I’ve used systems that work in a similar way to that
suggested by the lawyer, so it is possible. So with that useful knowledge,
let’s work out how we can solve the problem. The first step to solving the
problem is to write down the sequence of actions that need to be performed
to use the action in the application:
1. Type part of the name into the name input. (for example, “R”).
2. Press the Find Contact button. The first contact (meaning the one
nearest the start of the contactStore array) with a name that starts with
R will be displayed.
3. If the user presses Find Contact again, the next contact with a name
that starts with R will be displayed.
4. If the user enters a new name, the Find behavior resets, and the Find
Contact button now searches for the new name.
After thinking about it, I found three things that the application needs to be
able to do to make these behaviors work:
1. The application needs to be able to test whether one string starts with
the search string. This is so it can match the contact with the name
“Rob” to the search string “R.”
2. The application needs to store the search string and the search position
it has reached in the connectStore array. This needs to happen because
when the user presses Find Contact, the application knows what to
search for and where to start the search from.
3. The application needs to know when the user types in a new name.
This needs to happen because when the name changes, the application
can reload the search string and restart the search at the start of the
data array.
var name="Rob";
if(name.startsWith("R")){
alert("Rob starts with R!")
}
The JavaScript code above shows how this works. So now we know that we
can search the contacts for names that start with a string, and then we can
move on to the next problem. The program needs to store the current search
string and the position it has reached in the array of contacts.
We start by setting the find string (findString) to an empty string ("") and
the find position (findPos) to 0. This means that if the user presses the Find
Contact button as soon as the application has been started, the search will
match all the contacts (all names start with an empty string) and search
from the start of the contact store. (Remember, arrays are indexed from 0.)
When the user presses the Find Contact button, the doFind function is called
to search. We can make this function start searching with the find string at
the current find position:
The resetFind function gets the name element from the HTML document
and then uses a JavaScript string feature that we’ve not seen before. The
trim function returns a version of the string that has had all its leading and
trailing spaces removed. It would convert “R” to “R.” This is very useful.
The user will become confused if a search for “Rob” doesn’t find “Rob,”
and this prevents that problem from happening. The value of findString is
then set to this trimmed value, and findPos is set to 0 to make the next
search start at the beginning of the stored contacts.
CODE ANALYSIS
Investigating Super Search
The Super Search version of Tiny Contacts is in the Ch09
Objects\Ch09-09 Tiny Contacts Super Search examples folder. Let’s
open it and take a look inside. Open the application in your browser and
press F12 to open the Developer View of the application.
Answer: Good question. Try it. Enter some data, save it, enter the
first letter of one of the names into the name field, and press Find
Contact. The application will display the first match and continue to
display matches up to the end of the data.
Question: What happens if I enter an empty name to search for?
Answer: Try it. The behavior of the startsWith function means that
all strings start with an empty string. So the findStartsWithDataPos
function will match every contact. The user of the Tiny Contacts
program will really like this, as it provides them with a way of
stepping through all the saved contacts.
Question: How does the application add the oninput behavior to the
name input field?
Answer: Changes to the name input field must be detected and used
to update the search string. If you use the Elements tab in the
Developer View to take a look at the web page HTML, you will see
that the oninput attribute has been added to the name input field.
However, it has not been added to the address underneath. How does
this work?
I’ve made a tiny change to the function that generates the HTML for
each data item that needs to be stored. The makeElement function
regards the element, which has the id name as special. When it
generates that element, it adds the attribute to it. Open the Sources
tab in the Developer View and take a look in the tinyData.js file.
Question: How hard would it be to add this feature to the Recipe and
Video Game Score applications?
Answer: The wonderful thing about the way that our solution works
is that such a change would require no programming effort at all. We
simply have to update the versions of tinydata.js with the Super
Search version.
She would like to add an “email” input so that the program can keep
track of the email address of each contact.
She would like a button that clears the HTML form to make it easy to
enter new contacts.
She would like the search to “wrap around,” so that when she
searches through to the end of the list, she then returns to searching at
the start.
See if you can make these features work. If you need ideas, you can take
a look at my solution, which you can find in the Ch09 Objects\Ch09-10
Super Tiny Contacts examples folder.
OceanofPDF.com
Part 3
Useful JavaScript
In the final part, we take our JavaScript knowledge to the next level,
starting by picking up some new design skills and using them to build a
complete “business worthy” application. Then we move on to investigate
the popular node.js platform and use it to create a JavaScript web server.
Next, we will write some applications that can consume network services.
And we’ll round off the book by having some serious fun with a look at
game creation in JavaScript. We start by drawing simple graphics and then
move on to create a complete game with computer-controlled artificial
intelligence (AI) opponents.
OceanofPDF.com
10
Advanced JavaScript
The statements above create a JavaScript object called test, which contains
name and age properties. The contents of this object are then converted into
a string called JSONstring by the stringify method.
{"name":"Rob", "age":21}
This is the string that would be stored in JSONstring. This string can be
converted back into a JavaScript object by using the JSON parse method:
Click here to view code image
Now press F12 to open the Developer View and select the Console tab
so that we can investigate the application. The JSON parse method fails
by throwing an exception. Let’s see what that means. Type in the
following statement, which attempts to parse a string with the dangerous
sounding contents kaboom. Press Enter to see what happens.
> JSON.parse("kaboom");
The JSON parse method is not able to make sense of kaboom, and it
indicates this by throwing an exception. We have not included code to
catch the exception, so the JavaScript console displays an error message
in red:
> JSON.parse("kaboom");
Uncaught SyntaxError: Unexpected token k in JSON at position
0
at JSON.parse (<anonymous>)
at <anonymous>:1:6
The error created by parse is called an exception. It denotes the fact that
the requested action can’t be performed. If the exception is not caught,
the sequence of execution will end. Statements that might throw an
exception can be placed inside a try block of code. The try block is
followed by a catch block, which contains statements to be performed if
an exception is thrown. This is called a try-catch construction. Let’s
type one in. Enter the code below, remembering to press Enter at the end
of every line.
> try {
JSON.parse("kaboom");
} catch {
console.log("bad json");
}
When you press Enter after the closing curly bracket of the catch block,
the JavaScript code runs. The parse method will fail and throw an
exception, but this time the exception is thrown inside a try block, and
the associated catch clause will run and log a message on the console:
Click here to view code image
> try {
JSON.parse("kaboom");
} catch {
console.log("bad json");
}
bad json
Enter the same construction replacing the word kaboom with some valid
JSON, such as {}. Note that this time, the bad json message is not
displayed because parse doesn’t throw an exception if the JSON string is
valid.
Catching exceptions
The JSON validator above uses the try-catch construction to display an
appropriate message.
The doValidate function is called when the Parse button is pressed in the
JSON validator web page. If the user types in valid JSON, the JSON.parse
method doesn’t throw an exception, and none of the statements in the catch
block are performed. Instead, execution goes straight to the end of the
method. However, if the JSON.parse method can’t parse the string that was
typed in, the exception is generated and execution transfers immediately to
the block of code under the catch keyword.
The try block can contain many statements. However, this might make it
hard for you to work out which statement caused the exception.
CODE ANALYSIS
Exception handling
You might have some questions about how exceptions are handled.
Question: How does the exception stop the display of the Valid JSON
message?
This is the code that runs in the catch part of the try-catch
construction. It displays the error value (which is highlighted) on an
element in the HTML to give the display above. You can find this
version of the validator application in the example files in the Ch10
Advanced JavaScript\Ch10-02 JSON Validator Error folder.
Answer: Yes, you can. The throw statement is followed by the value
that is being thrown to describe the error.
Answer: Yes. It turns out that there are some JavaScript objects that
can’t be saved into a string of text. Let’s see if we can make one. Go
back to the Developer Console in the browser and start by making an
empty object called infiniteLoop. Type the statement below and
press Enter.
When you press Enter, the JavaScript console adds a new property to the
infiniteLoop variable that contains a reference to the infiniteLoop
variable. In other words, this variable now contains a reference to itself.
Now, let’s try and stringify the value in infiniteLoop. Type the
following and press Enter:
> JSON.stringify(infiniteLoop)
When you press Enter the stringify method tries to save the contents of
infiniteLoop. It does this by working through each of the properties
inside the value and saving each one in turn. It finds the loopRef
property, so it follows that reference to save that value. The reference
leads to the infinfiteLoop variable, so with stringify, this save process
would go on forever, rather like a reflection between two parallel
mirrors. Fortunately, the people who created the stringify method are
aware of the problem and have added a test for what is called a
“circular” reference. If you try to stringify an object that contains a
reference to itself, you will get an error.
> JSON.stringify(infiniteLoop)
Uncaught TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
--- property 'loopRef' closes the circle
at JSON.stringify (<anonymous>)
at <anonymous>:1:6
These values have been declared using the keyword const. This means that
their value cannot be changed by the program when it runs. This is sensible
because they are being used to indicate status values. The return values
from loadDataStore are used by the function doStartTinyData. If the store
is empty or invalid, an alert is displayed for the user.
It is very important that once we have created some error-handling code, we
also create a way of testing it. In this case, I created a new application that
breaks the storage. You can see it in Figure 10-1 and find the application
itself in the folder Ch10 Advanced JavaScript\Ch10-04 Store Breaker in
the examples. You can use this application to “break” the data storage for
the Tiny Contacts application.
Figure 10-1 Store breaker
<!DOCTYPE html>
<html lang="en">
<head>
<title>Store Breaker</title>
<link rel="stylesheet" href="styles.css">
<script src="breakstore.js"></script>
</head>
<p>
<button class="menuButton" onclick="doBreakStore()">Corrupt
the data store</button>
</p>
<p>
<button class="menuButton" onclick="doEmptyStore()">Remove
the data store</button>
</p>
</body>
</html>
This is the HTML for the store breaker application. It contains two buttons.
One button is pressed to corrupt the data store. It stores the string kaboom in
the data store, which will cause JSON.parse to fail. The second button is
pressed to remove the data store completely. These allow us to test the two
possible errors.
These functions use a feature of JavaScript that we haven’t seen before. The
confirm function allows a user to confirm an action. It pops up a message
box containing the prompt string and offers the user a chance to either
confirm the action or cancel. If the user confirms the action by clicking the
OK button, as shown in Figure 10-2, the confirm function returns the value
true.
Figure 10-2 The confirm function display
PROGRAMMER’S POINT
Error management is crucial
Dealing with errors is time consuming and difficult. It can be hard to
test an error handler. We had to write a special “breaking” program to
test the error handling in the Tiny Contacts application. However, error
management is a crucial part of software. Viruses and malware often
attack systems by causing errors and then exploiting badly written or
non-existent error handlers. When you are deciding how long it will
take to create an application, make sure that you include the time it will
take you to decide how errors are to be handled and write and test the
components to deal with them.
Class design
From what we’ve learned up to now, we can regard a Java object as a
container. We’ve seen that a program can add properties to an object so that
it can assemble related items. We explored this by creating an object-based
application that stores contact details. Object properties were added by the
program one at a time, building up a complete set of contact information by
adding name, address, and phone number properties to an “empty” object.
This works well for small applications, but sometimes you want to map out
your class design, rather than building it up as the program runs. And, as we
shall see, using classes to design objects also brings benefits by reducing
the amount of code that we write.
Figure 10-4 shows the main menu of the program. Imogen can click the
buttons to select pages to add dresses, pants, skirts, and tops to her stock.
She can select an update page to edit any existing stock items to change
their description or stock levels. She can also obtain a list of all her stock
items by pressing the List button.
Figure 10-4 Fashion shop main menu
Figure 10-5 shows what Imogen would see when she presses the Dress
button on the main menu to add a dress to stock. When she clicks Save on
this page, the program will assign a stock number to the item and save it.
Figure 10-5 Fashion shop add item
When a new item is added to the store, the program displays an alert, as
shown in Figure 10-6. This gives the stock number, which was assigned to
the new item.
The Update stock item button on the main menu starts a search for a given
stock number that is to be updated. Figure 10-7 shows the search page.
When the Find button is clicked, the program will search for a stock item
with the given id value and display the item for editing.
The final button on the main menu shown in Figure 10-4 is the List button.
Imogen will press this to generate a list of stock items that she can look
through. Each item has an Update button that she can click (see Figure 10-
8) to open the update page for that item.
Imogen thinks this will be a good start for the application; you agree a price
in stylish clothing and start working on the program. The first thing that you
need to do is decide how the different stock items are going to be stored.
MAKE SOMETHING HAPPEN
Manage Imogen’s Fashions
The application in the sample folder Ch10 Advanced JavaScript\Ch10-
05 Fashion Shop implements a working fashion shop store. It creates a
set of test data that you can view. You can also create your own fashion
items, store them, and then search for them by their stock reference. You
should spend some time adding and editing stock items to get a feel for
how it is used. Then we can start working out how each part works.
The statements above create an object called myDress that contains all the
data for the dress in Figure 10-3. However, there is a much easier way of
creating objects that contain properties. We can create a class that tells
JavaScript how to make a Dress object and what the object contains:
Click here to view code image
class Dress{
constructor(stockRef, stockLevel, price, description,
color, pattern, size){
this.stockRef = stockRef;
this.stockLevel = stockLevel;
this.price = price;
this.description = description;
this.color = color;
this.pattern = pattern;
this.size = size;
}
}
The JavaScript above doesn’t store any data. Instead, it tells JavaScript the
properties that are stored inside a Dress object and how to construct one.
The constructor method is called to create an instance of the Dress class.
Now we can create a new Dress much more easily:
Click here to view code image
myDress=new Dress(221,8,60,"Strapless evening
dress","red","swirly",10);
The new keyword tells JavaScript to find the specified class and run the
constructor method in that class to create a new instance of the class. When
the constructor method runs, it copies the parameter values into properties
in the newly created object. The keyword this, which you can see in the
constructor method above, means “a reference to the object that this method
is running inside.”
The confusing-looking statement above takes the price value that was
supplied as an argument to the constructor and assigns it into a newly
created price property on the object that is being created.
Click here to view code image
yourDress=new Dress(221,2,50,"Elegant party
dress","blue","plain",12);
herDress=new Dress(222,5,65,"Floaty summer
dress","green","floral",10);
If the word this is confusing, consider the two statements above. They
create two Dress instances. Each time the constructor in the Dress class
runs, it must set up a different object. In the first call of the constructor to
set up the yourDress the keyword, this represents a reference to the
yourDress object. In the second call of the constructor to set up herDress,
the keyword this represents “a reference to the herDress object.”
CODE ANALYSIS
Objects and constructors
Question: What happens if I create a class that doesn’t contain a
constructor?
This statement would create a Dress with the stock reference (221),
stock level (0), and price (50), but the description, color, pattern, and
size properties would be set to the value undefined.
Object-oriented design
It would make sense to create a class to hold each kind of data we wish to
store. Programmers call this object-oriented programming. The idea is that
elements in a solution are represented by software “objects.” The first step
in creating an application is to identify these objects.
In the English language, words that identify things are called nouns. When
trying to work out what classes a system should contain, it’s a good idea to
look through the description of a system and find all the nouns. As an
example, consider the following description of a fast-food delivery
application.
“The customer will select a dish from the menu and add it to his order.”
I’ve identified four nouns in this description, each of which will map to a
specific class in the application. If I were working for the fast-food delivery
company, I would next ask them what data they stored about customers,
dishes, menus, and orders.
PROGRAMMER’S POINT
Don’t write any code before you have
completed your data design
For a commercial project, you would spend a lot of time on the design
of the classes in your system before you wrote a single line of code.
This is because design mistakes are much easier to fix at the beginning
of the project, rather than after code has been written.
In the case of our fast-food management example above, we would
want to make sure that the customer class holds all the information
required to make the business work. We would do this by creating
“paper” versions of the classes and then working through all the usage
scenarios (creating an order, cooking an order, and delivering an order)
to make sure that all the data the application needs is being captured.
If the application must store a customer telephone number so that the
delivery driver can call for directions if needed, it is best to discover
this at the beginning of the project, rather than after the entire user
interface has been created.
We will write code and discuss it as we go along because we are
learning about data design and JavaScript programming. However, if I
were creating a professional solution, I’d spend a lot of time away from
JavaScript working out the design before I created any classes.
When we talk to our fashion shop customer, she’ll talk about the dresses,
pants, hats, tops, and other items that she wants the application to manage.
Each of these could be objects in the application and can be represented by
a class. Each class will contain the properties that describe that item of
clothing. Let’s start by considering just the information for dresses and
pants and create some classes for these objects. We already have a class for
Dress, so let’s make one for Pants.
class Pants{
constructor(stockRef, stockLevel, price,
description, color, pattern, length, waist){
this.stockRef = stockRef;
this.stockLevel = stockLevel;
this.price=price;
this.description=description;
this.color = color;
this.pattern = pattern;
this.length = length;
this.waist = waist;
}
}
When I wrote this sample code, I found myself using a lot of block-copy
commands in the editor when I created the constructor. This is not
necessarily a good thing.
PROGRAMMER’S POINT
Try to avoid repeating code
The Dress and Pants classes have quite a few elements in common.
They both contain stockRef, stockLevel, and price attributes. You
might think that would be a good idea to have two copies of the code
that deals with these attributes, one in the Dress class and the other in
the Pants class. However, this is not a good idea. I try to avoid having
repeated copies of code in a project because if I find a bug in one copy,
I then have to find all the other places I’ve used that code and fix those
as well.
A good programmer will try to write a piece of code exactly once. If the
code is used more than once in an application, a good programmer will
convert the code into a method or function and then call the method
each time it’s needed.
This is not about making sure that our programs are as small as we can
make them. It’s about self-preservation. If you block copy a piece of
code into lots of different places in your application, you’ll have a real
problem if you find a bug in the copied code. You’ll need to go through
your entire application and fix all the broken copies of that code. On the
other hand, if you find a bug in a method, you can fix it just once, and it
is fixed for every situation in which that method is used. Fortunately,
there is a way we can remove the need for numerous copies of the same
code, which we will discuss now.
If I find myself copying program text from one place to another, I take
this as a trigger to step back from the problem and think about different
ways of structuring my solution.
In real life, inheritance means stuff that you get from people who are older
than you. In JavaScript terms, inheritance means the attributes a subclass
gets from its superclass. Some programmers call the superclass the parent
class and the subclass the child class.
The key to understanding inheritance is to focus on the problem it is
solving. We’re working with a collection of related data items. The related
items have some properties in common. We want to implement the shared
properties in a superclass and then use this superclass as the basis of
subclasses that will hold data specific to their item type. That way, we only
need to implement the common properties once, and any faults in the
implementation of those properties need only be fixed once.
Working in this way has another advantage. If the fashion shop owner
decides that she would find it useful to be able to store the manufacturer of
the items she’s selling, we can add a manufacturer attribute to the StockItem
class, and all the subclasses will inherit that attribute, too. This will be
easier than adding the attribute to each class.
CODE ANALYSIS
Understanding inheritance
Here are some questions about object-oriented design and inheritance.
Try to come up with your own answers before reading the answers I’ve
provided.
Answer: This is a good question and one that has confused me for a
long time. The word “super” usually implies something better or
more powerful. A “superhero” has special powers that ordinary
people do not. However, in the case of a superclass, this doesn’t
seem to be the case. The superclass has fewer powers (fewer
properties) than the subclass that extends it.
Answer: If you can work out the answer to this question, you can
start to consider yourself an “object-oriented ninja.” Remember that
we use abstraction as a way of “stepping back” from the elements in
a system. We’ll say “receipt” rather than “cash receipt” or
“StockItem” rather than “Pants.”
The reason I haven’t done this is that I think that the fashion shop
might sell some stock items that have no pattern—for example, items
of jewelry. I want to avoid a class having data properties that aren’t
relevant to that item type, so I’ve put pattern values into the Dress
and the Pants class instead.
Some programming languages, such as C++, Java, and C#, allow you
to specify that a class definition is abstract, which stops a program
from making instances of that class. In these languages, an abstract
class exists solely as the superclass for subclasses. However,
JavaScript does not provide this feature.
Question: The owner of the fashion shop thinks that one day she might
like to keep track of which customer has bought which item of stock.
This will allow her to look at their past purchases and make
recommendations for future purchases. Here are three ways to do this.
Which would make the most sense?
Option 2 is a bad idea because several customers might buy the same
StockItem. The customer details cannot be stored inside the
StockItem.
class StockItem{
constructor(stockRef, stockLevel, price, description,
color){
this.stockRef = stockRef;
this.price=price;
this.description=description;
this.stockLevel = stockLevel;
this.color = color;
}
}
This is the StockItem class file. It contains a constructor method to set up a
StockItem instance. The StockItem class will be the superclass of all the
objects that the fashion shop will be selling. We can create a Dress class that
is a subclass of the StockItem class to hold information about dresses that
the fashion shop will be selling.
Click here to view code image
class BrokenDress extends StockItem{
constructor(stockRef, stockLevel, price, description,
color, pattern, size){
this.pattern = pattern;
this.size = size;
}
}
The BrokenDress class extends the StockItem class. It only contains the
properties that are specific dresses. However, we have a problem if we try
to use the BrokenDress class:
Click here to view code image
The first statement above creates a dress object called myDress. The second
statement uses the getDescription method on the myDress object to display
a description of the dress. It would display the following:
Click here to view code image
The Fashion Shop application will use the getDescription method to build
an HTML element to be displayed in a stock list.
A great thing about the getDescription method is that other parts of the
Fashion Shop application don’t need to know how the Dress and Pants
classes store their data or even what data is stored inside them. A part of
the program that needs to produce a description of a Dress doesn’t have
to pull out the various properties from a Dress instance; it just has to call
the getDescription method to get a string that describes that particular
dress. What’s more, this part of the program doesn’t need to care
whether it is dealing with dresses or pants, it can just view these items as
“things I can use getDescription to get a description of.”
Polymorphism means thinking about objects in terms of what they can
do, rather than what they are, and allowing each object to perform a
particular action in a way specific to that object. A given object can be
viewed in many ways, depending on what you want to do with it.
Different parts of the Fashion Shop will view objects in terms of abilities
such as “get a description string,” “set a discount,” “save,” and “load.”
Each of these abilities can be provided by methods inside the object with
a characteristic name, which can then be used by the rest of the system to
perform that action. Part of an object-based design process involves
identifying the behaviors required of objects and specifying them as
methods.
Question: What would happen if you tried to use super in a class at the
top of a hierarchy?
CODE ANALYSIS
Understanding static
The example application in the folder Ch10 Advanced JavaScript
\Ch10-09 Fashion Shop Static Members contains Dress and Pants
classes that contain static getTestItems method that create large amounts
of data that can be used to test our system. However, you might also
have some questions.
Answer: Static members are things that you want to store for the
entire class. Suppose that you wanted to set a maximum price for all
the dresses that the fashion shop sells. This could be used to help
detect when someone mistypes a price value. This value should be
stored in a static member of the class since it does not need to be
stored with every dress. If we need to change the maximum price of
a dress, we can just update the static value and the maximum price
for all the dresses will be changed.
You make a method member of a class static when you want to use
the method without creating an instance of the class. The JavaScript
Math class contains lots of static methods to perform mathematical
functions. These are declared as static so that we don’t have to create
an instance of the Math class to be able to use them.
Question: Where does the stock ref number come from when we create
a new stock item?
{"stockRef":1,"stockLevel":"11","price":"85",
"description":"red plain
dress","color":"red","pattern":"plain","size":"8"}
The text above is a JSON string that describes a dress. It contains all the
properties in a Dress instance, including those in the StockItem object
superclass. When we load this object back into our program we want to be
able to use it as a Dress object. Unfortunately, there is nothing in the JSON
string that tells a program reading it that this is a stored Dress value.
The JSON above describes a dress that contains a type property. I’ve
highlighted the type information in yellow. What we need now is a way of
creating a Dress instance from this JSON source string. I created a member
function in the StockItem class to do this. The function is called JSONparse.
It takes in a string of JSON and returns an object of the type specified by
the type value in JSON. It uses a switch construction to decide what type of
object to create.
The JSONparse method also uses a method that we have not seen before. It
is called Object.assign, and you can see it used in the last but one
statement in the method. The Object.assign function copies all the data
properties from one object to another. The program uses this to take all the
data properties from the JSON object that we read and copy them into the
empty object that we have just created. The first argument to the assign
function is the destination object for the copy. This is the newly created
object of the required type. The second argument to the assign function is
the rawObject that was loaded from JSON. This contains all the data
properties.
CODE ANALYSIS
Load and save
The example application in the Ch10 Advanced JavaScript \ Ch10-10
Fashion Shop No Test Data folder is a version of the Fashion Shop that
doesn’t generate test data when first started. You can create and store
stock items and they will be persisted when the browser is closed. It uses
local storage in exactly the same way as the Tiny Contacts program, but
it creates an array of JSON strings to store the data.
Question: The object that we loaded from the JSON object contains all
the data properties that the program needs. Why do we have to copy it
into another object?
Answer: No. The nice thing about this is that a single copy of the
JSONparse method in the StockItem class will load data for any of the
classes because it just copies what has been saved. However, you do
need to make sure that the switch statement in the JSONparse method
is kept up to date. If you add a new type of stock (perhaps hats), you
would have to add a case for that type to the switch.
The code above shows the display schema for the StockItem class. This is
the same schema design as we used for the Tiny Contacts application. There
is an entry for each item to be displayed. The item gives the id of the
property, the prompt to be displayed, and the type of the input. Three of the
items are single-line inputs, and one is a text area. If you take a look at
Figure 10-5 from earlier in this chapter, you will see how this schema
defines the display of the top four values to be entered.
The buildElementsFromSchema method works through the elements in a
schema and uses a function called makeElement to create each element from
the schema information and add it to an HTML element. It is the same
mechanism that was used to create the display of the Tiny Contacts
application.
Click here to view code image
getHTML(containerElementId) {
StockItem.buildElementsFromSchema(containerElementId,
StockItem.StockItemSchema);
}
CODE ANALYSIS
Creating HTML
A great programming language is one where you can create code that
you are proud of. I’m quite proud of this HTML-generating code. It is
easy to use and easy to extend. We can add more stock types and easily
express what each stock type contains. However, you might have some
questions about it.
Answer: Good question. Remember that our data design has given
us some classes that hold all the different data properties in a stock
item. We have used inheritance to create a superclass called
StockItem that holds all the properties shared by all the stock items
(such as the price and the number of items in stock). Then we’ve
created subclasses of StockItem that hold data specific to that type of
item (such as the length and waist properties of Pants).
If we want the user to interact with these properties, we will need to
create HTML (labels and input elements) in the HTML document
displayed by the browser. We could do this by hand, but it would be
tedious. When we made the Tiny Contacts application, we created a
schema object that defined the properties to be displayed and then
wrote a method that that worked through the schema making HTML
elements to edit each item. Think of a schema as a “shopping list” of
items to be displayed.
The process described above takes the same approach as we used for
Tiny Contacts and adds a schema to each type of stock item. It uses
the super keyword so that the display builder (the getHTML method)
in Dress can call the getHTML method in the StockItem class. It is
necessarily complicated, but if you stare at it hard enough, it does
make sense. And if you understand it, you can call yourself a “class
hierarchy ninja.”
When the Fashion Shop starts, these variables must be set up. The body
element of the HTML document containing the application contains an
onload attribute that specifies the function to be called when the page is
loaded. This function starts the Fashion Shop running. The function is
called doStartFashionShop.
Click here to view code image
<body onload="doStartFashionShop('mainPage','fashionShop')"
class="mainPage">
The last statement in doStartFashionShop displays the user menu. Lets take
a look at how that works.
function doShowMainMenu() {
openPage("Main Menu");
showMenu(
[{ desc: "Add Dress", label: "Dress", func:
"doAddDress()" },
{ desc: "Add Pants", label: "Pants", func:
"doAddPants()" },
{ desc: "Add Skirt", label: "Skirt", func:
"doAddSkirt()" },
{ desc: "Add Top", label: "Top", func: "doAddTop()" },
{ desc: "Update stock item", label: "Update", func:
"doUpdateStock()" },
{ desc: "List stock items", label: "List", func:
"doListFashionShop()" }]);
}
I’m using yet another schema to describe each menu option. The function
showMenu works through the schema and builds the display. If you look back
to Figure 10-4, you can map the application main menu onto the items in
the schema above. The function openPage removes all the elements on the
page and displays a heading.
function doAddDress() {
addStock(Dress);
}
It calls the addStock function and does something we’ve not seen before. It
uses the Dress class as an argument to the call of addStock. We do this so
that we can have a single addStock function that can create any type of
stock item.
The addStock function makes a new item of the required class (the class is
supplied as a parameter). It then creates a new display page and fills it with
the HTML generated by the new item. At the end of the page, the function
builds a menu containing Save and Cancel buttons. The function handler for
the Cancel button just displays the main menu. The function for the Save
button copies the inputs from the HTML elements into a new copy of the
stock item. This function has the name doSaveAdd. The job of doSaveAdd is
to copy the data from the HTML document into the currently active item.
This item is then stored in the data store.
Exploring the Fashion Shop application
There is a lot to explore in the Fashion Shop and you can learn a lot by
exploring it. The application is heavily based on the Time Tracker
application. I would strongly advise you to spend some time going through
the code. You can use the Developer View debugger to work through the
code as it runs. The great thing about the application is that it is very clear
what the intent of each function is. For example, the edit function, which
we have not explored in this chapter, must find a stock item to be edited,
make that item the active item, and when the edit is completed, copy the
edited properties from the HTML document into the data store.
Note that we have not explored the function that provides a list of stock
items. You can use it, and you can look at the code that makes it work, but
we will be investigating that function and adding some great features to it in
the next chapter.
Add a new type of clothing called suit. A suit has the properties
jacket size, pant size, color, pattern, and style. You can do this by
adding a new class that is a subclass of StockItem.
Add a new property called manufacturer, which is to be stored for all
the items in stock. You can do this by adding a new attribute to the
StockItem class.
Add some data validation to the application. At the moment the user
can save stock item records that have missing data fields. Write a
function that tests for empty fields and only allows a record to be
saved if all the fields have been filled in.
Create a totally new data storage application, which can store
information for another business, perhaps a fishing tackle store. You
should find this quite easy to do. You can use the Fashion Shop
application as a great starting point.
10. A class can contain static data and method members which are stored
as part of the class rather than being part of any instance of a class. A
static method is a way that class can provide a behavior or data
property that can be used without the need to create an instance of the
enclosing class.
Here are some questions that you might like to ponder about what we have
learned in this chapter:
What happens if a JavaScript program doesn’t catch an exception that
has been thrown?
If an exception is thrown in some JavaScript that is not part of a try-catch
construction the exception will be caught by the browser and the execution
sequence will end. If you have the Developer View open, you will see the
exception displayed in the form of a red error message.
When should a JavaScript program throw an exception?
Exceptions should only be used in exceptional circumstances. Some
JavaScript functions, for example JSON.parse, use exceptions to signal error
conditions. You can also make your code generate exceptions. When you
start work on a project you need to decide on all the possible error
conditions and then decide how each should be handled. Exceptions are
useful because they provide a way that a low-level failure can be quickly
propagated to a higher-level error handler.
Must my JavaScript programs catch all exceptions?
No. For me, the biggest concern when I write a program is not that the
program might fail. It is that the user might think that it has worked when it
has not. If an application fails with an obvious error, the user will get upset.
If an application “pretends” that it has worked and the user later finds out
that they have lost all their data, they will get very upset. You should ensure
that exceptions are logged and reported in a way that makes their error
reports useful.
Do I have to use classes in my programs?
No. However, they can make some kinds of programs (particularly those
that need to deal with different types of related data) easier to write.
Can a JavaScript class have multiple constructors?
No. Some programming languages have a mechanism called “overloading”
where a class can contain multiple versions of a method that all share the
same name but have different parameters. JavaScript does not support
overloading, so a class can only contain a single constructor method. If you
want to provide different ways to construct an object, you must write code
in the constructor method to decide what the parameters to the function
mean.
What is the difference between a method and a function?
A method is declared as part of a class, whereas a function is declared
outside any class. Both can accept parameters and return a result.
Can the this reference be used as an argument to a function call?
Yes. Within a method, the this reference refers to the object that the
method is running within. If an object wants to send another object a
reference to itself, it can pass the value of this as a function argument. This
is like me calling you on the phone and telling you my phone number.
Can I use the this reference inside a static method?
No. A static method is a member of the enclosing class and is not associated
with an existing instance.
OceanofPDF.com
11
Creating applications
Data analysis
Create extra Fashion Shop functions
Read the weather
Node.js
Install and test Node.js
Deploying a Node.js server
What you have learned
Data analysis
We are going to start off by performing some analysis for the Fashion Shop
application that we created in Chapter 10. This will allow us to explore
some advanced features of JavaScript functions and discover how easy it is
to perform analysis of the contents of arrays of data. We are going start by
considering how a JavaScript program can display a list of items.
The Fashion Shop application produces a stock list, as shown in Figure 11-
1. Each stock item is displayed on a line of text. The item details on each
line of the list are preceded by an Update button that can be pressed to
update the stock details for that item. Let’s look at how the stock list is
produced. When the user presses the button to produce the stock list, the
following JavaScript function runs:
Click here to view code image
function doListFashionShop() {
createListPage("Stock List", dataStore);
}
<p><button class="itemButton"
onclick="doUpdateItem('4')">Update</button>
<p class="itemList">Ref:4 Price:10 Stock:14 Description:red
plain dress
Color:red Pattern:plain<ic:ccc> Size:14</p>
</p>
We don’t need to know how the sort method sorts the dataStore any more
than we need to know how JavaScript adds two numbers together. One
thing that it is useful to know, however, is that the sorting process will not
move any StockItem values around in memory. The datastore contains an
array of references. We can change the order of the references without
having to move anything in memory.
Click here to view code image
function stockOrderCompare(a, b) {
return a.stockLevel - b.stockLevel;
}
function doListStockLevel() {
dataStore.sort(stockOrderCompare);
createList("Stock Level Order", dataStore);
}
This is the code that produces a list of stock item sorted by stock level. The
function doListStockLevel above is called when Imogen selects the option
to display the stock sorted in the order of stock level. It sorts the dataStore
array and then uses the createList function to display the sorted list.
CODE ANALYSIS
Sorting stock items
The Fashion Shop application in the Ch11 Creating
Applications\Ch11-01 Fashion Shop Stock Sort example folder
contains the analysis feature that can be used to display a list of stock
items that have been sorted by stock level. You might have some
questions about how it works.
Answer: The JavaScript above shows how we would this. The first
statement creates an array of strings, which is called names. The
seconds statement tries to sort the names using stockOrderCompare as
the comparison function. This will not work because the strings in
the names array do not have a stockLevel property, but what would it
do?
This function can be used to sort the name array we created earlier.
The stringOrderCompare function is declared within the Ch11
Creating Applications\Ch11-01 Fashion Shop Stock Sort
example.
Click here to view code image
> names.sort(stringOrderCompare)
["ethel", "fred", "jim"]
Anonymous functions
We can control how sort behaves by changing the function that is used to
perform the comparison, but it is rather unwieldly to have to create the
function and then use it as an argument to the call of sort. JavaScript makes
it easier to do this by allowing us to declare the comparison function
directly in the arguments of the sort call:
Click here to view code image
dataStore.sort(function(a,b){
return a.stockLevel-b.stockLevel;
});
This sort does the same job as the original one, but the comparison
function is provided as an argument to the call of sort. This type of
function declaration is called an anonymous function because it has no
name. The function can’t be called by any other code. It has the double
advantage of making the program slightly smaller and also binding the
comparison directly to the call of sort. With the above code, you don’t have
to go and find out what the stockOrderCompare function does. The
application in the Ch11 Creating Applications\Ch11-02 Fashion Shop
Simple Function example folder uses this simplified function format to
control the sort behavior.
Arrow functions
Arrow functions are a way of making programs even faster to write. Rather
than having to type function to create an anonymous function, you can
express the function like this:
Click here to view code image
dataStore.sort((a,b) => { return a.stockLevel - b.stockLevel});
The parameters to the function are given before the arrow (=>), and the
block of statements that make up the body of the function is given after the
arrow. If your function contains only one statement, you can dispense with
both the statement block and the return keyword to make a very short arrow
function:
Click here to view code image
The statement above would sort the datastore in ascending order with the
lowest stock levels first. What change do you think you would have to make
to sort in descending order?
Click here to view code image
This turns out to be a very small change to the program. We just have to
reverse the order of the subtraction, as shown in the statement above.
CODE ANALYSIS
Anonymous functions
Anonymous functions and arrow functions are very powerful JavaScript
features, but they are also rather confusing when you first see them.
Answer: Because it has no name. Up until now, all the functions and
methods that we’ve created have been given names so that we can
refer to them in other parts of the program. However, with an
anonymous function, I just want to describe a particular behavior to
be performed at one point in the program. I could give the behavior a
name (as in stringOrderCompare) above, but it is much easier if I can
just drop the JavaScript code directly into my application at the point
where I want to use it. Programmers sometimes call anonymous
functions lambda functions.
Answer: No. The only place that the code in an anonymous function
can be used is the point when it is declared. It can’t be accessed
anywhere else because it has no name.
Answer: We have seen that there are two ways we can describe an
anonymous function:
This version uses an arrow function to perform the same task. For the
task above, you can use function or arrow interchangeably.
However, there are differences between how the two anonymous
functions work. The most important one is the way that the keyword
this works inside an anonymous function. We know about this
because we’ve used it to access elements of an object from methods
running inside the object. If you want to write an anonymous
function that makes use of this to get hold of elements in an
enclosing object, you must use the arrow function notation to create
the anonymous function. When you use the word function to make
an anonymous function, you create a new object that the function
code runs inside. Code running inside this kind of anonymous
function can only access elements declared inside that function body,
which is not usually what you want.
The first argument to the reduce method is the function that will be called to
update the total. The second parameter is the initial total value, in this case,
zero. We can convert the addValueToTotal function into an arrow function,
in which case, the call of reduce looks like this:
Click here to view code image
var total = dataStore.reduce(
(total, item) => total + (item.stockLevel * item.price),
0);
This single statement will do the job. The map method accepts a function
that has a single parameter. The parameter is the item to be worked on. The
statement above will drop the price of every item in stock by 5 percent. You
can find this example program in the Ch11 Creating Applications\Ch11-
05 Fashion Shop Discount folder.
Asynchronous operation
There are two ways that I can go shopping. I can go to a shop, select what I
want, pay for it, and take it home. My actions are synchronized with the
shop because I must wait for the sales assistant to accept my payment and
hand over the goods before the shopping is completed. Alternatively, I can
email my shopping list to the shop and ask them to deliver my purchases.
Now I can do other things, such as dig in the garden while I wait for my
shopping to arrive. My actions are not synchronized with the shop, meaning
they are asynchronous. If the shop takes a long time to deliver, it just means
that I might have more time for gardening (which is actually not a win for
me as it turns out—I’d rather stand in a shop than work in the garden). Up
until now, when a JavaScript program has asked for something to be done,
the action has been performed synchronously. For example, consider this
statement.
Click here to view code image
descriptionPar = document.createElement("p");
JavaScript promise
To get around this problem, JavaScript introduces the idea of promises. A
promise is an object that is associated with a task that a program wants to
perform. JavaScript provides a method called fetch, which is used to fetch
data from a server. However, the fetch function does not return the data;
instead, it returns a promise to deliver the data at some point in the future.
Click here to view code image
var fetchPromise =
fetch('https://www.begintocodewithjavascript.com/weather.html')
;
The statement above uses fetch to fetch the contents of the file at
'https://www.begintocodewithjavascript.com/weather.html'. This call of
fetch returns a promise object. The variable fetchPromise refers to this
object. The fetch will start to happen asynchronously. You can think of this
as the point in the process where I call the shop and ask them to deliver my
shopping.
The fetchPromise object is a link between our application that requested the
data and the asynchronous process fetching the data. We set a property on a
promise object to identify a function to be called when the promise is kept.
A promise object provides a method called then, which accepts a reference
to the method to be called when the promise has been kept.
Click here to view code image
fetchPromise.then(doGotWeatherResponse);
This is the JSON that describes the weather. You can see that the object
contains a main property that contains a temp property that is the
temperature value. Note that the temperature is delivered as a value in
degrees Celsius, not Fahrenheit. The application in the Ch11 Creating
Applications\Ch11-06 Weather Display example folder contains these
functions and will display the weather information when the FETCH
button (shown in Figure 11-4) is pressed.
Figure 11-4 Weather display
You can see the two catches in the doGetWeather function above. They
display an alert that contains any error message that was produced when the
promise failed.
Use finally to enable a button after a fetch
The weather application we have created makes a fetch request each time
the FETCH button is clicked. This can lead to problems. One thing that
users quite like to do is repeatedly click a button if they don’t get a response
within a second of their first click. In the weather application, this would
cause lots of fetch requests. A well-written application would disable the
FETCH button once it has been clicked to prevent this behavior. So let’s
make our application well-written. A JavaScript program can disable a
button by adding a disabled attribute to the button:
These two statements disable a button with the ID fetchButton. Once the
fetch has completed, the program can enable the button. We could add code
to the then and catch functions to enable the button, but as you know, I hate
writing the same code twice. Instead, we can add a finally function to a
promise that identifies code to run when the promise has completed,
regardless of whether it succeeds. This would guarantee that the FETCH
button is enabled once the fetch is complete.
This is the code that I added to remove the disabled attribute from the
FETCH button. You can find it in the sample application in the Ch11
Creating Applications\Ch11-09 Weather Finally example folder.
CODE ANALYSIS
Investigating promises
The application in the Ch11 Creating Applications\Ch11-10 Weather
Error Handling example folder uses the doGetWeather function above to
display the temperature. It also contains two other buttons that activate
two broken fetch behaviors. The first attempts to load the weather from
a nonexistent network address, and the second loads a file that does not
contain JSON data. You can use these to experiment with failed
promises.
Answer: Yes, you can. If you click the FETCH ERROR button in
the example above, you will notice that it takes several seconds for
the error message to appear. While you are waiting for the error, you
can click the FETCH and JSON ERROR buttons to perform their
fetch behaviors.
Answer: Yes, you can. We will be doing this in the next chapter
when we create a promise that is fulfilled when an image has been
loaded into our game.
Answer: If you understand this question and the answer, you can
consider yourself a “promise ninja.” JavaScript code can throw an
error object when things get tough. This is called an exception.
We’ve seen that code working with JSON throws exceptions if it
can’t convert a string into a JavaScript object. Look in Chapter 10 in
the section “Catching exceptions” to find out how this works. You
might think that we could just put a call of fetch inside a try-catch
construction in our application to pick up any errors when they occur.
Node.js
Up until now, all the JavaScript applications that we have written have run
inside the browser and used the HTML document to interact with the user.
This is fine for creating client applications (meaning applications that fetch
data and work with it), but it would be useful to be able to create JavaScript
applications that could work as servers that provide data for client
applications. In this section, we are going to discover how to use a platform
called Node.js to create a server application written in JavaScript. Node.js
was created by taking the JavaScript component out of a browser and
making it into a freestanding application that can host JavaScript code.
Click the installer for your machine and go through the installation
process. Once you have completed the installation, you can start to work
with Node.js. The first thing you can do is test that the installation has
worked correctly. We can do that by using the terminal in Visual Studio
Code. Start Visual Studio Code, open the View menu, and select
Terminal. The terminal window will open in the bottom right-hand
corner of Visual Studio Code. You use this window to send commands to
the operating system of your computer. I’m using a Windows PC, so my
commands will be performed by Windows PowerShell. Enter the
command node and press Enter.
The Node application starts and displays a command prompt. You should
find this remarkably familiar. If you enter a JavaScript command, it will
be obeyed in the same way as if you were using the console in the
Developer View in your browser.
You can exit from the Node.js command prompt by holding down the
CTRL key and pressing D.
The statement above uses the createServer method supplied by the http
object to create a simple web server. The variable server is set to refer to
the new server. The createServer method accepts a single argument, which
is an arrow function that works on two parameters. This function provides
the behavior of the server. It will be called each time a client makes a
request of the server. The first parameter to the function describes the
request that has been received. The second parameter will hold the response
that is to be produced. Our server behavior is implemented by an arrow
function that accepts the parameters request and response. The function
above ignores the contents of the request and just prepares a response that is
a text message 'Hello from Simple Server'. Now that we have our server
object, we can make it listen for incoming requests.
server.listen(8080);
The listen method starts the server listening for incoming requests. The
listen method is supplied with an argument specifying the port that the
server will listen on. Each computer on the Internet can expose a set of
numbered ports that other computers can connect to. When a program
connects to a machine, it specifies a port that it wants to use. Port number
80 has been set aside for HTTP access, and browsers will use this port
unless told otherwise. Our server will listen on port 8080.
CODE ANALYSIS
Using a server
You can find this sample server application in the examples for this
chapter. We will not be using this application from the browser; we will
start the server running from within Visual Studio code and then view
the page that it generates with a browser. Start by opening the Visual
Studio Code application and then open simpleServer.js in the Ch11
Creating Applications\Ch11-11 HTML Server example folder, as
shown below:
To start the server, you need to run the program in simpleServer.js.
Make sure that this file is selected in the file browser as shown above.
Open the Run menu and select the Start Debugging option. There are
several different ways that Visual Studio Code can run your application,
so you will be asked to select the environment you want to use:
Click the Node.js option, and the server will start. Now you can open
your browser and connect to this server. Because the server is running on
your machine, you can use the Internet address localhost. You need to
add the port number that you are using to this address, so enter the
address localhost:8080 address into the browser and press Enter to open
the site.
When you do this, you will see the message from the function that is
running inside the server. You might have some questions about what
you have just done:
Answer: Yes. You are running both the server (the Node.js program)
and the client (the browser) on your PC. However, you could run the
server on one machine and access it from the browser on another. If
the server machine were on the Internet, it would be possible for
distant machines to access the server. One thing to bear in mind,
however, is that modern operating systems include a firewall
component to manage their network connections. The firewall limits
the network services that one machine exposes to another in case
malicious programs try to take advantage of too much connectivity.
If you want to create a server and allow people access to it, you can
use Node.js to do this, but you would have to configure the firewall
on the host machine and also take steps to ensure that you provided
the services in a secure way.
Answer: Yes. The call to the listen method will never return. You
can use Visual Studio Code to stop the program by clicking the red
square box stop button on the right-hand side of the program
controls.
Answer: The server creates a response object that is sent back to the
client. The response tells the client if the server could satisfy the
request and contains the data that was requested. The server
application performs four statements to create and send the response
that is received by the browser:
response.statusCode = 200;
The first statement sets the status code of the response. A status code
of 200 tells the browser that the page was found correctly.
The write method writes the content of the page being returned. This
server always sends the same text: Hello from Simple Server. It
could, instead, send a very large amount of data.
response.end();
The end method tells the server that it can now send the response and
the content back to the browser client.
Routing in HTML
In the “Fetching web pages” section in Chapter 2, we saw that the URL
expressing the location of a web page contains a host element (the Internet
address of the server) and a path element (the path on the host to the item
that the client wants to read). The simple server above returns the same text
for any path that you use to read from the host. In other words, the URLs
http://localhost:8080/index.html and http://localhost:8080/otherpage.html
both return the message Hello from Simple Server, as would any other
path. The first web server used the path component of a URL to identify the
file that the server should open and send to the client. We can improve our
simple web server to allow it to respond differently to different paths.
The code above implements a server that recognizes two paths: index.html
and otherpage.html. If the client tries to access any other path, the sever
responds with a “page not found” message. Note that the “page not found”
message has a status code of 404 to represent this. The program parses the
url property of the request parameter to extract the path that was requested
in the URL. This path is then used to control a switch construction that
selects the response to be sent. You can find this example server in the
example folder. This server program could be expanded to serve a number
of different pages.
CODE ANALYSIS
Using multiple paths
You can find the multiple page server in the Ch11 Creating
Applications\Ch11-12 Multi page server example folder. Start Visual
Studio Code and from the examples folder, open multiPageServer.js.
Ensure that the multiPageServer.js file is selected in the file browser.
Now click Run -> Start Debugging to start the application. Select the
node.js environment when prompted by Visual Studio Code. Now open
your browser and navigate to: http://localhost:8080/index.html.
The browser will show the text for this URL. Now change the address to
http://localhost:8080/otherpage.html and reload the page.
The browser will now display the response for the other page. Finally,
you can try a missing page. Change the address to
http://localhost:8080/missingpage.html and reload.
Question: How does the server get the path to the resource that the
client has requested?
Answer: The URL is the entire address sent by the browser to the
server to request a particular web page. The path part of a URL
describes the location of a resource on the server. For example, the
server might receive the URL http://robmiles.com/index.html. The
path in this URL is /index.html. The URL that was given to the web
request is provided as the url property of the response parameter to
the method called by createServer. The method called by
createServer must extract the path from this URL so that the server
can decide what to send back to the browser. The server does this by
using the URL module that was loaded at the start of the program.
The parse method creates an object that exposes different parts of the
URL as properties. The statement above creates a parsed URL object
(called parsedUrl). I use parse because I am lazy and don’t want to
have to write JavaScript that extracts the path from the URL string.
case "/aboutpage.html":
sendResponse(response, "hello from aboutpage.html");
break;
Answer: Yes, you can. However, you need to change the content
type from text/plain to text/html so that the browser knows how to
process the response.
response.setHeader('Content-Type', 'text/html');
Answer: You could build server like this, but it would be hard work.
Your server would also have to serve out the image and style sheet
files along with the HTML files. I just want to show you how this
works so that you can understand how servers work. The Express
framework (which we will see later) provides a much quicker way of
creating a JavaScript application that will act as a server. However, it
uses the same fundamental principles that we have been using.
http://localhost:8080/index.htm?no1=2&no2=3
The URL above contains two query values: no1 (set to the value 2) and no2
(set to the value 3). These query values are sent to the server in the URL
string. We could create a server that accepted these values and returned their
sum. The server could use the parse method from the url module to extract
the query values.
Click here to view code image
var parsedUrl = url.parse(request.url,true);
Once I’ve done this, I can extract the value of the two queries from the
parsedUr, as shown above. Now my addition program can convert these two
query strings into numbers and perform the required calculation:
Click here to view code image
The query values are always sent as strings of text. Our application uses the
Number function to convert the query values into numbers. It then calculates
their sum. The listing below is the complete source of an “addition” service,
which accepts a query containing two numbers and returns their sum.
Click here to view code image
var http = require('http');
var url = require('url');
});
server.listen(8080);
The addition service that we created above does not produce a web page as
a result. It returns a string that contains the result of adding two query
values together. This kind of service is called a web service. It uses HTTP to
transfer messages, but the messages do not contain HTML documents. A
more complex web service could return an object described by a string of
JSON. We’ve already used one web service, the weather service from
openweather.org. Now we know how to create our own web services using
JavaScript and Node.js to host them. A Node.js application could also use
the file system module fs to open files held on the server and send them as
responses.
CODE ANALYSIS
Investigate the addition server
You can find the addition server in the Ch11 Creating
Applications\Ch11-15 Addition Server example folder. Start Visual
Studio Code and open additionServer.js in the example folder. Ensure
that the file additionServer.js is selected in the file browser. Now use
Run -> Start Debugging to start the application. Select the node.js
environment when prompted by Visual Studio Code. Now open your
browser and navigate to http://localhost:8080/index.html?
no1=2&no2=3.
The server program will work out the result of the calculation (2+3) and
return the result. Try changing the values of no1 and no2 and reload the
page. The page will update with the new result.
fetch(url).then(response => {
response.text().then(result => {
let resultParagraph =
document.getElementById('resultParagraph');
resultParagraph.innerText = "Result: " + result;
}).catch(error => alert("Bad text: " + error)); // text
error handler
}).catch(error => alert("Bad fetch: " + error)); // fetch
error handler
This is the JavaScript that performs the fetch to get the result from
the service. The service responds with text that is used to set the
value of the resultParagraph element on the web page. This code is
very similar to the code that was used to read the weather from
openweather.org.
This is a big moment. Almost all this book has been leading up to
this point. You now know how web applications work. The HTML
document describes the page, and the JavaScript in the page can do
things. If the JavaScript wants to get data from a server, it creates a
request and sends it to the server, which decodes the request,
generates the result, and sends it back. You should spend some time
taking a long hard look at the web page, the server, and the client
code until you understand what each part does.
OceanofPDF.com
12
Creating games
When you press Enter, a variable called myCanvas is created and made to
refer to the canvas element. This process does not return a value, so the
JavaScript console displays undefined.
Click here to view code image
You might think that we could now call methods on the myCanvas
reference to draw things on the canvas in the HTML document.
However, this is not how it works. A canvas provides a drawing context
that is used to perform drawing operations. We want to use the 2D
drawing context, so we have to ask the canvas for it. Enter the statement
below and press Enter:
When you press Enter, a variable called myContext is created that refers
to the 2D graphics context of the canvas. This process does not return a
value, so the JavaScript console displays undefined.
The context object can be used for all further graphics operations. It
exposes many methods for drawing on the canvas. One way to draw is to
define a path and then ask the context to draw the path. Enter the
following statement to begin a path:
> myContext.beginPath();
A path contains move and draw operations. You can add many of these
operations to the path. We are going to start the path by moving to the
origin. The moveTo method accepts two parameters. The first is the “x
coordinate” or distance across the screen of a pixel position. The second
parameter is the “y coordinate” or distance down the screen. The
position (0,0) is known as the origin of the graphics coordinates. Let’s
move the path position to the origin. Enter the following statement to
move the path position to (0,0).
> myContext.moveTo(0,0)
Moving doesn’t draw anything on the canvas. To draw a line, we use the
lineTo method, which also accepts x and y coordinates as parameters.
Enter the following statement to draw a line to the position (800,600).
> myContext.lineTo(800,600);
We have told JavaScript to draw a line, but the line has not appeared on
the screen yet. This is because the context saves all the move and draw
operations until the stroke method is called. Enter the following
statement to draw the line on the canvas:
> myContext.stroke();
When you enter the stroke method, you should see a diagonal line
drawn down the entire canvas. This is because the canvas has been
defined as being 800 pixels wide and 600 pixels high.
Canvas coordinates
You might have been surprised by the line that has just been drawn. You
might have expected the line to start at the bottom-left corner, rather than
the top. This is because placing the origin in the top-left corner is standard
practice when drawing graphics on a computer. The important thing to
remember is that the origin, which is the point with the coordinate (0,0), is
the top-left corner of the display. Increasing the value of x moves you
toward the right of the screen, and increasing the value of y will move you
down the screen, as shown in Figure 12-1. If you draw outside the range of
the canvas dimensions—for example, if we tried to draw something at
location (1000,1000)—this would not be displayed, but it would not cause
an error in the program. I’ve chosen a canvas size of 800 pixels wide and
600 pixels high because this results in a reasonable game display on most
devices.
Computer art
We can use JavaScript graphics to create some nice-looking images. The
program below draws 100 colored lines and 100 colored dots. The program
uses functions that create random colors and positions on the display area.
The computer art program can produce some rather nice-looking images, as
you can see in Figure 12-2. You can find it in the example Ch12 Creating
Games\Ch12-02 Art Maker folder. Each time you run the program, it will
generate a different image because the positions of each item are
determined randomly.
Figure 12-2 Computer art
CODE ANALYSIS
Random artwork
As you can see in Figure 12-2, the program above can produce some
vaguely artistic-looking images. However, you may have some questions
about the code.
Answer: These variables are global. They are not declared in any
function, so they can be shared by all of them. I’ve decided that it
makes the program easier to write if these values are shared by all
the functions in the program. The value of context (the context to be
used for all the drawing operations) is set at the start of the doDrawArt
function.
You can use this method to draw interesting curves by only drawing
part of the circle. This will also provide a very good workout of your
trigonometry skills.
Question: Why does the program subtract the radius value from the
random dot positions?
Answer: Above, you can see the statements that pick a random
position to draw a round dot. The radius of a dot is between the
values 5 and 100. When the dot is drawn, I don’t want it to “go off”
the picture. This is an artistic decision—JavaScript will happily draw
items that don’t all fit on the screen. The getRandomInt function picks
a random number between start and end values. By making sure that
the start position is never less than the radius of the dot or greater
than the canvas size subtracted from the radius, I can make sure that
my dots never go off the screen. If your artistic judgment is different
from mine, you are welcome to change this code.
The statements above would fil the entire canvas with blue.
Answer: Yes. The art program above uses fixed color names such as
“red,” but you can also create a color by calling the rgb function with
three arguments giving the intensities of red, blue, and green in the
color:
rgb(255,0,0)
The intensity values can range from 0 to 255. The above call of rgb
would produce the value bright red.
function getRandomColor() {
var r = getRandomInt(0,255);
var g = getRandomInt(0,255);
var b = getRandomInt(0,255);
return "rgb("+r+","+g+","+b+")";
}
The statements above are all completely correct. They create a new Image,
tell the image that the path to the image resource is the URL cheese.png,
and then draw the image on the canvas context at the top-left corner of the
screen (coordinate 0,0). Unfortunately, these statements will not work. This
is because loading images is like fetching everything else from the network.
It takes a while to complete. The image starts to load when the src attribute
is set, but the JavaScript code above draws the image before it has loaded.
This means that the cheese would not be displayed. Loading an image is
performed asynchronously. We first saw asynchronous operation in Chapter
11 in the “Fetch data from a server” section. In that section, we used the
fetch function to get weather data from a server.
These statements would draw the cheese as soon as it was loaded. The last
statement binds an arrow function to the onload event so that the image is
drawn when it has been loaded. You can find a program that draws cheese
in this way in the Ch12 Creating Games\Ch12-04 Image Load Event
folder in the example programs. We can also bind an event handler to the
onerror event that an image will generate if the image cannot be loaded.
This statement binds an arrow function to the onerror event. The arrow
function displays an image not loaded alert. You can find a program that
produces this error alert in the Ch12 Creating Games\ Ch12-05 Image
Load Fail example programs folder.
Figure 12-4 shows the result produced for each of the images in the game
that have been loaded from the image files.
Figure 12-4 Game images that have been loaded and displayed
Question: Does using await cause the browser user interface to lock up?
PROGRAMMER’S POINT
Invest some time in understanding Promise and
await
The effort of understanding Promise and await will make your head
hurt. At least it did mine. But it is worth it. It lets you create
applications that can load huge chunks of data and spend ages
processing it without having users complain that their user interface
gets stuck. It also lets you understand the code in frameworks that you
will want to use, many of which use asynchronous behaviors. If you are
finding it difficult to understand what they do, keep going back to the
two problems that they were created to solve.
Animate images
The drawImage function is given x and y values that specify where the
image is to be drawn.
context.drawImage(cheese,x,y);
The statement above would draw the Image referred to by cheese on the
canvas. The values in the variables x and y specify where in the canvas the
image above would be drawn. We can make an image appear to move by
repeatedly drawing the image at slightly different positions. This is how all
games work. To perform the game animation, we need a regular source of
update events. In Chapter 3 in the “Create a ticking clock” section, we used
the setInterval function to repeatedly call a function at regular intervals
and make our clock tick. We could use this to trigger game display updates,
but this would not be a very good idea because it would result in the game
display flickering.
If the browser redraws the screen while our game is halfway through
updating the positions of objects on the screen, the player would see the
display appear to flicker. To avoid flickering, we need to synchronize the
game updates with screen updates from the browser. Fortunately, there is a
way to do this. The browser maintains a window object, which contains
methods that we can use in our applications. One of these is the
requestAnimationFrame method. This method accepts a single parameter,
which specifies a function to call the next time the browser is updating the
display.
Click here to view code image
window.requestAnimationFrame(gameUpdate);
The statement above asks the browser to call the gameUpdate method the
next time the browser is updating the display. The game can then redraw the
canvas as part of this process.
This is a gameUpdate function that will draw the cheese image moving down
the screen. The screen is cleared before each redraw. After each draw, the
values of the x and y positions of the cheese are increased by 1, which will
move the cheese draw position.
Most browsers update the display 60 times a second. The screen is 600
pixels high, and the cheese is moved down the screen one pixel each
time it is updated. This means that after around 10 seconds, the cheese
will vanish off the bottom of the screen. If you want to make the cheese
appear to move more quickly, you can increase the amount you add to
the position. The amount you change the position of an item on the
screen gives you the speed of that item. See if you can change the
program to make the cheese move twice as fast down the screen. These
are the two statements that you need to look for:
x = x + 1;
y = y + 1;
By changing the values to 2, you can double the speed. You can find my
faster version in the Ch12 Creating Games\Ch12-10 Speedy Cheese
example folder.
Control gameplay
Now that we know how to make things move around the screen, the next
thing we need is a way that a player can control them. We are going to use
the keyboard to steer the cheese with the arrow keys. When the user presses
an arrow key, we want the cheese to move in the corresponding direction.
To make this work, we are going to create an event listener that runs when
the player presses a key on the keyboard.
Window events
We have already used the requestAnimationFrame function to ask the window
object to tell our game when it is time to redraw the screen. Now we are
going to ask the window object to bind a function to events generated by the
keyboard. The addEventListener provided by the window object lets a
program connect a JavaScript function to a particular event. The events are
specified by name, and there are many events. We can start by investigating
how events work. We are going to use the keydown event.
The function above adds an arrow function to the keydown event. The
function is supplied with an event parameter. It displays the code attribute
of the event in a paragraph in the document.
CODE ANALYSIS
Keyboard events
You can find the keyboard event handler code in the Ch12 Creating
Games\Ch12-11 Keyboard Events example folder. Use the browser to
open this page and investigate what it does.
Above, you can see the display that is produced when I pressed the A
key on the keyboard. Try some other keys, including nonprinting ones
such as Shift and Control. Also, try holding down the Shift key and
pressing letters.
Question: Why does it not display the character produced by that key on
the keyboard?
Answer: The code values that are captured by this event are more
concerned with the actual key rather than the character that is sent to
a program when a key is pressed. Each key has a name (the A key is
called “KeyA”), including the Shift keys. This event even
distinguishes between left and right Shift keys, calling them
“ShiftLeft” and “ShiftRight.” This is very useful for our game.
Answer: Yes. The window will call each of the functions bound to a
particular event in turn.
The code above binds an event listener to the keydown event and then uses
key values to control the x and y positions of the cheese. When the cheese is
drawn at its new position, it will appear to move under the control of the
player.
CODE ANALYSIS
Cheese steering
You can find the cheese steering code in the Ch12 Creating
Games\Ch12-12 Keypress Cheese Control example folder. Use the
browser to open this page and investigate what it does.
You can press the arrow keys to move the cheese around the screen.
Each time you press an arrow key, the cheese moves one pixel in that
direction.
Question: Why does the value of y increase as the cheese moves down
the screen?
Answer: This is because the origin of the coordinates (the point with
the coordinate 0,0) is the top-left-corner. This means that increasing
the value of y will move the cheese down the screen.
These variables control the speed and position of the cheese in our game.
The speed and position values are used in the function gameUpdate, which
updates the cheese position and then draws it.
Each time this function is called, it will clear the screen, update the position
of the cheese, and then draw the cheese at the new position. If the speed
values are zero, the cheese will not move with each redraw.
Click here to view code image
This event hander starts the cheese moving when the user presses a key. It
doesn’t move the cheese on the screen; instead, it sets the speed value of the
cheese so that it will move in the selected direction the next time the update
method is called. If the cheese is to move backward or upward, the speed
for that direction will be negative. Because the position of the cheese is
being updated repeatedly by the gameUpdate function, this will mean that the
cheese will start to move as soon as the key is pressed down.
Click here to view code image
window.addEventListener("keyup", (event) => {
switch(event.code){
case 'ArrowLeft':
cheeseXSpeed=0;
break;
case 'ArrowRight':
cheeseXSpeed=0;
break;
case 'ArrowUp':
cheeseYSpeed=0;
break;
case 'ArrowDown':
cheeseYSpeed=0;
break;
}
});
This is the event handler that causes the cheese to stop moving when the
player releases a key. It sets the speed value for the particular direction to
zero.
Losing focus
You can find this cheese steering code in the example program Ch12
Creating Games\Ch12-13 Steerable Cheese. If you open the page in
this folder with a browser, you will find that you can control the cheese
movement very well. If you hold down two arrows you can even make
the cheese move diagonally. However, the code does have a problem. If
you start the cheese moving and then select another window on your
desktop the cheese doesn’t stop when you release the movement key.
This is because a modern windowed operating system like Windows 10,
macOS, or Linux has the idea of focus.
At any given instant, the events from the keyboard and mouse are sent to
the currently selected window, which is called the one that has focus. As
soon as you select another application, the browser moving our cheese
around loses focus and keyboard events are no longer sent to it. This
means that there is no keyup message to stop the cheese moving, which
causes it to keep moving and eventually vanish off the canvas.
We can fix this by binding a handler to a window event that is fired when
the application loses focus. This is called the blur event. When this event
fires, the game must stop the movement of the cheese.
The code above shows how we would do this. When the window loses
focus, it now sets the speed values for the cheese to 0, causing it to stop
moving. The application in the Ch12 Creating Games\Ch12-14
Steerable Cheese with focus example folder uses this event handler to
stop the cheese moving when browser loses focus. If you repeat the
experiment you performed with the earlier version, you will find that the
cheese stops moving as soon as you select a different window from the
browser.
Game sprites
Each of these screen objects is called a sprite. A sprite has an image drawn
on the screen, a position on the screen, and a set of behaviors. Each sprite
will do the following things:
1. Initialize itself when the game is loaded.
2. Draw itself on the screen.
3. Update itself. Each sprite will have a characteristic behavior.
4. Reset itself between games. When we start a new game, we must reset
the state of each sprite.
Sprites might have other behaviors, but these are the fundamental things
that a sprite must do. We can put these behaviors into a class:
CODE ANALYSIS
Sprite superclass
The code above defines the superclass for all the sprites in the game. You
may have some questions about it.
Answer: When the game creates a new sprite, it must tell the sprite
which game it is part of because some sprites will need to use
information stored in the game object. For example, if a cracker is
“captured,” the score value in the game will need to be updated. The
sprite constructor makes a copy of the game reference so that it can
interact with the game when it needs to.
Programmers say that the sprite class and the game class will be
tightly coupled. Changes to the code in the CrackerChaseGame class
might affect the behavior of sprites in the game. If the programmer of
the CrackerChaseGame class changes the name of the variable that
stores the score from score to gameScore, the Update method in the
Cracker class will fail when a cracker is captured.
I think about coupling in the same way I think about global variables.
Global variables are an easy way to allow several functions to share
application data. However, when I write the code, I have to make
sure that none of my functions change the value of a global variable
in a way that the other functions weren’t expecting. A mistake I make
in one function might cause another to fail.
Answer: The game will create a list that contains all the sprites in it.
Once all the sprites have been created, the game will then create a list
of initialise promises from the sprites that it will feed into a call of
Promise.all. In other words, the promise behavior that we used to
load individual images in the previous section has been moved into
the Sprite class.
The Sprite class doesn’t do much, but it can be used to manage the
background image for this game. The game will take place on a
“tablecloth” background. We can think of this as a sprite that fills the
screen. We can now make our first version of the game object that
contains a game loop that just displays the background sprite.
Question: How does the game pass a reference to itself to the sprite
constructor?
Question: Why does the game call the draw method on the sprite to draw
it? Can’t the game just draw the image held inside the sprite?
For instance, adding smoke trails to some of the sprites in this game
by drawing “smoke” images behind the sprite would be much easier
to do if I could just add the code into the “smoky” sprites rather than
the game having to work out which sprites needed smoke trails and
draw them differently.
Question: Does this mean that when the game runs, the entire screen
will be redrawn each time, even if nothing on the screen has changed?
<body onload="doGame()">
<canvas id="canvas" width="800" height="600">
This browser does not support a canvas.
</canvas>
</body>
Below, you can see the gameStart method. The first statement calls the
gameReset method to reset the game and make it ready to play. The second
statement calls window.requestAnimationFrame to connect the gameUpdate
method to the next screen animation event. We need to have a detailed look
at the code here because it tells us some important things about the this
reference.
Investigating this
We started using the this reference when we created the stock storage
objects in the Fashion Shop application in Chapter 10. We discovered that
in a method inside a class the keyword this means “a reference to the
object that this method is running inside.” If this seems confusing, consider
the sequence of statements that are being performed. The function doGame
contains the following statement to start the game running:
activeGame.gameStart();
The statement means “follow the reference activeGame to an object and call
the gameStart method on that object.” The JavaScript system finds the
object and calls the gameStart method in it. Just before it runs the code in
gameStart, the JavaScript system sets the keyword this to refer to the same
object as activeGame. The gameStart method contains the statement:
this.gameReset();
The problem is that the code above does not work because the gameUpdate
method will not be called from a reference to the activeGame object. It is
called by the JavaScript window object when it is time to redraw the display.
In other words, the this reference inside gameUpdate will refer to the wrong
thing when the function runs. We can fix this by explicitly binding the this
reference in the call of gameUpdate to a reference to the active game object:
Click here to view code image
window.requestAnimationFrame(this.gameUpdate.bind(this));
this.speed = 5;
this.xSpeed = 0;
this.ySpeed = 0;
update(){
super.update();
if(this.x<0) this.x=0;
if(this.x + this.width > this.game.canvasWidth){
this.x = this.game.canvasWidth - this.width;
}
if(this.y<0) this.y=0;
if(this.y + this.height > this.game.canvasHeight){
this.y = this.game.canvasHeight - this.height;
}
}
draw() {
this.game.context.drawImage(this.image, this.x, this.y,
this.width, this.height);
}
}
CODE ANALYSIS
Player sprite
The code above defines the Cheese sprite. You can find it in the Ch12
Creating Games\Ch12-16 Background and Cheese sample code
folder. Use your browser to open the web page there.
You can use your cursor to move the cheese around the canvas. Note
what happens when your cheese reaches the edge of the canvas. You
might have some questions about this.
Question: Why does the Cheese object have width and height
properties?
draw() {
this.game.context.drawImage(this.image, this.x, this.y,
this.width, this.height);
}
This also makes it possible for the game to change the size of the
cheese during the game.
Question: How does the program stop the cheese from moving off the
screen?
Answer: If you try to steer the cheese off the screen with the arrow
keys, you will find that you can’t. The image above shows how this
works. The game knows the position of the cheese and the width and
height of the canvas. If the x position plus the width of the cheese is
greater than the width of the screen (as it is in the image above), the
update method for the cheese will put the cheese back on the right
edge:
The cheese update method also makes sure that the cheese cannot be
moved off the other edges of the canvas. The game also uses the
width and height properties to place the cheese in the middle of the
canvas at the start of the game.
constructor(game, url) {
super(game, url);
getRandomInt(min, max) {
var range = max - min + 1;
var result = Math.floor(Math.random() * (range)) + min;
return result;
}
reset() {
this.x = this.getRandomInt(0, this.game.canvasWidth-
this.width)
this.y = this.getRandomInt(0, this.game.canvasWidth-
this.height)
}
draw() {
this.game.context.drawImage(this.image, this.x, this.y,
this.width, this.height);
}
}
The Cracker class is very small because it gets most of its behavior from its
superclass, the Sprite class. The constructor sets the width of a cracker to a
20th of the screen size. The reset method for the cracker picks a random
location on the canvas. It uses the same random number function that we
used to position dots in the art program. We can add a Cracker to our game
by creating it and then adding it to the list of sprites in the game:
Click here to view code image
this.sprites = [];
Figure 12-8 shows how the test will work. In this figure, the two sprites are
not intersecting because the right edge of the cheese is to the left of the left
edge of the cracker. In other words, the cheese is too far to the left to
intersect with the cracker. This would also be true if the cheese were above,
below, or to the right of the cracker.
We can create a method that tests for these four situations. If any of them
are true, the rectangles do not intersect.
Click here to view code image
intersectsWith(sprite) {
if ((this.x + this.width) < sprite.x) return false;
if ((this.y + this.height) < sprite.y) return false;
if (this.x > (sprite.x + sprite.width)) return false;
if (this.y > (sprite.y + sprite.width)) return false;
return true;
}
The method can be added to the Sprite class. The method returns true if
the sprite intersects with a particular target. We add this method to the
Sprite class so that all sprites can use it. Now we can add an update method
to the Cracker class that checks to see whether the cracker intersects with
the cheese:
Click here to view code image
update() {
if (this.intersectsWith(this.game.cheese)) {
this.reset();
}
}
Add sound
At the moment our game is silent, which is a bit boring. We could improve
the cracker class so that it plays a sound when it is eaten. We’ve made
JavaScript programs that play sound in the past. We added a sound element
to the egg timer in Chapter 2. Our game can make sound by using an Audio
object:
The constructor for the Cracker class now accepts an additional parameter
giving the URL that specifies the location of the sound resource. When the
Cracker constructor runs, it creates an Audio object for the sound effect and
then sets the src property of the new Audio object to the sound resource
location.
Click here to view code image
this.cracker = new Cracker(this, 'images/cracker.png',
'sounds/burp.wav');
When the cracker is created, the constructor is given a path to the sound file
to be used. The update method can now play the sound whenever the cheese
“eats” a cracker:
You can find the noisy version of the game in the Ch12 Creating
Games\Ch12-20 Eating with sound example folder. If you want to create
your own sound effects, you can use the program Audacity to capture and
edit sounds. It is a free download from http://www.audacityteam.org/ and is
available for most types of computers.
Adding scores
Keeping score is another great way to motivate the player of a game. In
Cracker Chase, the player will increase their score by 10 each time they eat
a cracker.
The Cracker update method above adds 10 to the score in the game each
time a cracker is eaten. The score value is held in the CrackerChaseGame
class and is drawn each time the screen is updated:
We draw the score on the canvas using a set of methods from the canvas
context that we’ve not seen before. The fillText method draws filled text
on the screen. The fillStyle method lets us set the color of the text, and we
can set the text size and style by assigning a value to the font property of
the context.
Figure 12-9 shows how the score is displayed. You can find the scoring
version of the game in the Ch12 Creating Games\Ch12-21 Eating with
scores example folder.
Figure 12-9 Score display
PROGRAMMER’S POINT
When you write a game, you control the
universe
One of the reasons I like writing games so much is that I have complete
control of what I’m making. If I’m solving a problem for a customer, I
must deliver certain outcomes. But in a game, I can change what it does
if I find a problem. I can also redefine the gameplay if I make a mistake
in the program. Sometimes, this produces a more interesting behavior
than the one I was trying to create. This has happened on a number of
occasions.
PROGRAMMER’S POINT
Making game elements “intelligent” makes
games much more interesting
Artificial intelligence (AI) is the field of computing that aims to make
software that can do things that normally require human intelligence.
Making a “killer tomato” that always chases the cheese is not
necessarily creating AI, but it is a great way to make gameplay more
interesting for the player. It gets especially interesting if you have a
number of different objects with different “intelligent” behaviors for the
player to deal with.
The initial speed of the tomato is set to zero, so each time the tomato is
updated, the speed (and hence the distance it moves) will increase. If we do
this in conjunction with “artificial intelligence,” we get a tomato that will
move rapidly toward the player.
Add friction to a sprite
If we just allowed the tomato to accelerate continuously, we’d find that the
tomato would just get faster and faster, and the game would become
unplayable. The statement below adds some “friction” to slow down the
tomato. The friction value is less than 1, so each time we multiply the speed
by the friction, it will be reduced, which will cause the tomato to slow down
over time.
Click here to view code image
this.xSpeed = this.xSpeed * this.friction;
The friction and acceleration values are set in the constructor for the Tomato
sprite:
Click here to view code image
constructor(game, imageUrl) {
super(game, imageUrl);
PROGRAMMER’S POINT
When you write a game, you can always cheat
When you’re writing a game, you should always start with the simplest,
fastest way of getting an effect to work and then improve it if necessary.
The “physics” that I’m using are not really an accurate simulation of
physical objects. The way that I’ve implemented friction is not very
realistic, but it works and gives the player a good experience. I find it
interesting that six or seven lines of JavaScript can make something that
behaves in such a believable way. The Cracker Chase game uses very
simple collision detection, a form of artificial intelligence, and physics,
but it is still fun to play. It really feels as if the tomatoes are chasing
you. Making the physics model completely accurate would take a lot of
extra work and would add very little to the gameplay.
This code uses a loop to create 5 tomato sprites with delay values starting at
300 and going up in steps of 600. The constructor in the Tomato class stores
the value of entryDelay for that tomato.
The entryDelay value is used to delay the entry of the sprite:
Click here to view code image
update() {
this.entryCount = this.entryCount + 1;
The update method is called 60 times per second. The first tomato has an
entry delay of 300, which means that it will arrive at 300/60 seconds, which
is 5 seconds after the game starts. The next tomato will appear 10 seconds
after that, and so on, up until the last one. When I played the game with 5
tomatoes chasing me, I noticed that the gameplay was not very thrilling
because all the sprites merged into one another, making them very easy to
avoid. This is because they were all accelerating at the same rate. To fix
this, I used the entry delay to calculate a change to the acceleration. This
means that the later sprites accelerate more quickly and don’t bunch
together.
The example program in the Ch12 Creating Games\Ch12-22 Killer
tomatoes folder shows how this works. It can get rather frantic after a few
tomatoes have turned up and are chasing you.
PROGRAMMER’S POINT
Make sure you tell people how to play your
game
In my long and distinguished career in computing, I’ve judged quite a
few game development competitions. I’ve lost count of the number of
games that I’ve tried to play and failed because the game doesn’t tell
me what to do. The problem is usually that everyone focuses on making
the game and not on telling people how to play it. Failing at a game
while you work out which keys you are supposed to press doesn’t make
for a very good introduction to it, so make sure that you make the
instructions clear and present them right at the start.
We saw the screen drawing methods earlier when we added code to the
update method that drew the score on the screen. The displayMessage
method also uses the measureText method to get the width of the text so that
it can be centered on the screen. It draws the text twice. The first time, the
text is drawn in black, and then the text is drawn again in red. The second
time the text is drawn, it is moved slightly to make it appear that the black
text is a shadow.
PROGRAMMER’S POINT
Don’t worry about making the graphics
hardware work for you
You might think it’s rather extravagant to draw all the text on the screen
twice just to get a shadow effect. However, modern graphics hardware
is perfectly capable of many thousands of drawing operations per
second. I’ve been known to draw text 20 times just to get a nicely
blurred shadow effect behind it. If you think something might look
good, my advice is to try it and only worry about performance if the
game seems to run very slowly after you’ve done it.
The gameRun method runs the game, sets gameRunning to true, and then
triggers the first animation frame in the game. When the game is running,
the gameUpdate method updates the sprites and then checks to see if any of
them have ended the game. If the game is over, it displays the start screen
and the final game score:
The test in the update method for the Tomato sprite checks to see if this
tomato intersects the cheese. If it does gameEnd method is called to end the
game.
PROGRAMMER’S POINT
Always make a playable game
Something else I noticed while judging game development
competitions was that some teams would produce a brilliant piece of
gameplay but not attach it to a game. You’d start playing the game and
find that it never actually ended. You should make sure that your game
is a complete game from the very start. The game should have a
beginning, middle, and end. As you have seen in this section, it’s easy
to do this, but when people start making a game, they seem to leave it to
the last minute to create the game start screen and the game ending
code, so that what they produce is not a game. Instead, it is more of a
technical demo, which is not quite the same thing. Making your game
into a proper game right from the start also makes it much easier for
people to try it and then give you feedback.
You can find the completed game in the Ch12 Creating Games\Ch12-24
Complete Crackerchase folder. It’s fun to play for short bursts,
particularly if there are a few of you trying to beat the high score. My
highest score so far is 740, but then I never was any good at playing video
games.
Now that you know how a game works, you can take a look at some
game engines, which do a lot of the hard work for you. The Phasor game
engine is a great place to start, with many example games you can use as
starting points. You can find it at https://phaser.io. If you want to create
multiplayer games, you should take a look at Socket.io, which you can
use to create a game that is hosted on a Node.js server and can be played
by people all over the world. You can find it at https://socket.io/.
A
<a> tag, 41–42
about this book, xv–xvii
abstraction, 305, 344–345
acceleration values, 458
activeGame object, 442
addEventListener method, 429
adding machine program, 122, 124–126
addition service, 398, 399–400
addStock function, 361–362
alert function, 12, 52, 213
alertInputText ID, 46
aligning text, 71, 88
alternative text, 39
analyzing data, 370–371
Andreessen, Marc, 28
animating images, 427–429
anonymous functions
awaits contained in, 468
code analysis of, 375–376
explanation of, 374, 402, 405
simplifying promises using, 383
appendChild method, 200
applets, 5
applications
adding machine, 122, 124–126
data-processing, 96–97
digital dice, 222–232, 236
egg timer, 52–56
fashion shop, 335–363, 368–379
ice cream sales, 242–269
multiplication table, 196–203
pizza calculator, 127–131
ride selector, 161–172, 178–196
temperature conversion, 130–131
ticking clock, 72–77
tiny contacts, 276–316
totalizer, 133–137
weather information, 379–387
See also programs
arc drawing method, 417
arguments
arrays of, 221
code analysis of, 214–216
maximum number of, 238
ordering of, 18
parameters and, 216–217
references used as, 219–220
arrays, 221, 246–251
bounds of, 271
code analysis of, 267–268
counting from zero in, 249
filter method, 377
investigating and creating, 246–248
as lookup tables, 265–266
map method, 378–379
processing data in, 249–251
reduce method, 378
size of, 268, 271
sorting data in, 371–373
storing data in, 246–248, 281–283
arrow functions, 374–375, 376, 402, 405, 463
artificial intelligence (AI), 456–457
artwork
computer-generated, 414–419
drawing on canvas, 410–413, 419–425
assign function, 356
assignment operation, 46
asterisk (*) character, 52, 101
async keyword, 424–425, 426
asynchronous operations, 380, 420
attract mode for games, 468
attributes
data, 184–188
image tag, 38
properties vs., 60
style, 64, 80, 87
Audacity program, 453
audio
adding, 55, 140, 452–453
playback control, 56, 140
audio element, 55, 56
await keyword, 424–425, 426, 467–468
Azure account, 401
B
backslash (\) character, 120, 141
backtick (`) character, 119, 141, 143
bad nesting, 37
Berners-Lee, Tim, 28
binary representation, 104
binding event handlers, 421
bits, 103, 104
block-copy commands, 342
blocks of statements
for loop and, 193
if construction and, 160–161
blur event, 435
Boolean expressions, 149–150
Boolean function, 147, 149
Boolean values, 146–149, 173, 174
bounds of the array, 271
<br> tag, 31, 34
bracket notation, 300, 317
break keyword, 171
breakpoints, setting, 262
browsers. See web browsers
bugs
faults vs., 67, 181
fixing in programs, 181–183
responding to reports of, 181
See also errors
buildElementsFromSchema method, 358
buttons, creating HTML, 42–44
C
C# and C++ programming languages, 4, 346
calculations
examples of, 10–12
performing, 110–112, 244–245
calling functions, 208, 209, 210–211
camel case, 108
canvas, 410–425
computer art program, 414–419
coordinates, 413–414
drawing on, 410–413, 419–425, 468
cascading styles, 85–86, 88
case sensitivity, 310, 317
catch block, 326, 327, 328
catch method, 384, 386, 426
changeArrayElement function, 267
children property, 189
class attribute, 82, 84, 90
classes, 335, 363–364, 365
constructor method for, 339–340, 342
diagram created for, 343–344
game sprite, 438, 440–441
hierarchy of, 345, 347–348
inheritance mechanism for, 343–344, 345–347
method members added to, 348–349
object-oriented design and, 341–342
static members of, 352–355, 357
style, 82, 84
className property, 180
cloning repositories, 18–19
code
avoiding repeated, 343
bugs vs. faults in, 67, 181
building web pages from, 196–201
debugger for running, 260–264
finding and fixing bugs in, 181–183
importance of well-designed, 183–184
code analysis, xvi
addition service, 399–400
anonymous functions, 375–376
arguments, 214–216
arrays, 267–268
Boolean values, 147–149
code errors and testing, 109–110
commands and responses, 10–12
comparison operators, 151–152
doSave function, 286–287
doShowAlert function, 47–48
evaluating expressions, 100–102
exception handling, 327–330
findContacts function, 284
floating-point values, 114–115
for loop, 192–194
functions, 209–212
game class, 440–441
getNumberFromElement function, 230–231
HTML from JavaScript, 199–201
if constructions, 160
input generation, 256–257
JSON, 299
keyboard events, 430–431, 432–433
logical operators, 154–156
multiple path use, 394–396
performing calculations, 112
player sprite, 445–446
promises, 385–387
reading numbers, 259–260
server use, 390–392
sorting items, 372–373
Super Search, 314–315
ticking clock program, 75
whole vs. real numbers, 113
collections
arrays as, 221
for-of loop and, 195–196, 221
collision detection, 455
colors
adding, 64–65
creating, 418
keyword, 24
mouse rollover, 66–67
comments
adding to programs, 131–133, 141
HTML, 38, 133
comparison function, 371–372, 373, 374, 402
comparison operators, 150–152
compiled languages, 23, 102
computers
art generated by, 414–419, 440
data processing by, 96–97, 140
minimum requirements for, xvii
concat method, 272
concatenation, 119, 272
confirm function, 334
console.log statement, 192
Console window, 9
const keyword, 332, 354
constructive laziness, 195
constructor method
class creation and, 339–340, 342
objects and, 340–341
contacts app, 276–316
displaying contacts in, 285
finding contacts in, 283–285, 287, 309–315
helper functions, 280–281
JSON for encoding data in, 295–298
local storage for, 292–295
objects used in, 291–292
property accessors in, 300–304
prototype creation, 277–280
saving contacts in, 285–287
schemas created for, 304–308
storing contacts in, 281–283
Super Search feature for, 310–315
user ideas for improving, 310, 316
container element, 306
control variables, 191
controller function, 422
coordinates, canvas, 413–414
Cracker Chase game, 436–465
AI added to, 456–457
class definition, 438, 440–441
code analysis, 438, 440–441
collision detection, 455
end detection, 464
game object, 439–440
physics and friction, 457–458, 459
running, 463–464
scores added to, 453–454, 464
sound added to, 452–453
sprites in, 436–438, 443–452, 456–460
start screen added to, 461–462, 463
createElement method, 199, 255, 380
createListElement function, 369–370
createListPage function, 369
createServer method, 389–390, 395, 404
CSS (Cascading Style Sheets), 82, 85–86, 89, 91
See also style sheets
curly braces { }, 161, 173, 288, 296, 319
currentDate variable, 72, 73
D
data
analyzing, 370–371
fetching, 380–385
information vs., 103
sorting, 371–373, 376–377, 402
text vs. numeric, 112
data attributes, 184–188
adding to HTML elements, 184–185
code analysis of, 186–187
data processing
arrays and, 249–251
computers and, 96–97, 140
expressions for, 100–102
JavaScript, 99, 100, 104
programs and, 98–99
data schemas. See schemas
Date object, 72, 149
debugger feature, 260–264
default selector, 170
defining functions, 208, 209–210, 213
delimiters, 119
designing
systems before building, 305, 341–342
user interface for customers, 162, 252–254
Developer view, 7–8
digital dice program, 222–232
double dice version of, 236
error handling added to, 227–232
random number calculations in, 222–226
disabled attribute, 385
displayContact function, 292
displayElementValue function, 280, 285
displaying
images, 57
symbols, 32–33
text, 49–50, 462
displayMessage function, 462
<div> element, 84–85, 88, 90, 253
doAddition function, 9, 124
doAddToTotal function, 136
doBuildPage function, 305, 306, 307
doBuildSalesInputItems function, 253–254, 256
doCalc function, 244–245, 251, 262
doClockTick function, 74, 76–77
Document Object Model (DOM), 45, 252
documents
deleting elements from, 201–202
HTML formatting of, 41
style sheets added to, 80, 88
doEndTimer function, 52, 54
doFind function, 287, 312–313
doGame function, 441
doMouseOver function, 66
doSave function, 285, 286–287
doSaveAdd function, 362
doShowAlert function, 47–48
doStartClock function, 76–77
doStartFashionShop function, 360
doStartTimer function, 52
doStartTinyContacts function, 298
dot notation, 300, 317
double quote (") character, 119, 141, 143
doUpdateItem function, 370
doValidate function, 327, 328
downloads for book, xviii
draw method, 440, 445
drawImage function, 427, 445
drawing
on canvas, 410–413, 419–425, 468
computer-generated, 414–419, 440
drawStartScreen method, 462, 463
E
egg timer program, 52–56
functions used in, 52
investigation exercise, 53–54
sound added to, 55
Eich, Brendan, 5
elements, 37, 46, 58, 246
Elements window, 8
else keyword, 159, 160, 174
<em> tag, 30, 60
em units, 70, 88, 90
emojis, meanings of, 33
empty objects, 288, 300, 316
encapsulation, 234
end method, 392
end tags, 32
entryDelay value, 459–460
equality operator, 151, 152, 153, 174
equals (=) character, 47, 107
error handling
adding to applications, 227–232
JavaScript promises and, 384
errors
exceptions and, 330–334, 363
finding in advance, 228–233
floating-point values and, 114–115
importance of managing, 335
logic, 109–110
spelling, 110
testing for, 110, 126
See also bugs; faults
escape sequences, 120, 141, 143
event handlers, 421
events
attributes of, 87
definition of, 421
keyboard, 430–435
window, 429–430
exceptions
catching, 327
errors and, 330–334, 363, 386
explanation of, 299, 324, 364–365
handling of, 327–330
JSON use of, 299, 324, 325–326
Express system, 401
expressions
Boolean, 149–150
evaluated by JavaScript, 100–102, 111
operators and operands in, 100, 110, 141
processing data with, 100
F
F12 key, 7, 23
false keyword, 146, 147–148
fashion shop application, 335–363, 368–379
adding stock items, 361–362
class hierarchy, 347–348
code exploration, 362
data analysis, 370–371
data storage solutions, 355–356
HTML creation, 359–360
illustrated overview, 335–338
menu options, 361
sorting data, 371–372, 376–377
starting the program, 360
static class members, 352–355
store stock data, 339–340, 368–370
suggestions for expanding, 363
user interface, 357–359, 361
faults
bugs vs., 67, 181
fixing in programs, 181–183
responding to reports of, 181
types of, 330–331
See also errors
fetch function, 381–382, 403, 404
fetching data, 380–385
asynchronous operation for, 380
calling web services and, 399–400
disabling FETCH button after, 384–385
promises used for, 381–384
fetchPromise object, 381
files
finding, 21
saving, 20
fillRect function, 418
fillText method, 454
filter method, 377, 402
finally function, 385, 387, 403
findContactPos function, 283, 284, 285, 286, 287
findContacts function, 284
finding
files in Visual Studio Code, 21
info in contacts app, 283–285
Super Search for, 310–315
findStartsWithDataPos function, 313, 314
firewalls, 391
fixed-width layouts, 268–269
floating-point numbers, 114–116
equality and, 153
errors related to, 114–115
real numbers and, 114
floor function, 117, 118, 129, 141
focus, loss of, 435–436
fonts
families of, 68, 69, 87
monospaced vs. proportional, 36
selecting for text, 68–69, 70
serif vs. sans-serif, 68, 70
size specification, 70–71
for loop, 191–195
code analysis, 192–194
elements of, 191, 203
findContacts function and, 284
for-of loop, 195–196, 204, 221, 259
friction, game, 457–458, 459
functions, 43, 61
anonymous, 374
arguments given to, 214–216
arrow, 374–375
calling, 208, 209, 210–211
code analysis of, 209–212
defining, 208, 209–210, 213
designing with, 228
explanation of, 43, 208–213
giving information to, 213
helper, 280–281
local variables in, 233–236
methods distinguished from, 61, 341, 365
multiple parameters in, 218
naming, 213, 239
side effects of, 136, 137
values returned from, 222–226
G
game engines, 465
gameEnd method, 464
gameplay controls, 429–436
event listener, 429–430
keyboard events, 430–435
lost focus and, 435–436
window events, 429–430
gameReset function, 442
gameRun method, 463
gameRunning property, 463, 464, 468
games
animating images for, 427–429
artificial intelligence in, 456–457
attract mode for, 468
building your own, 465
classes for, 438, 440–441
code analysis for, 438, 440–441
collision detection for, 455
controls for playing, 429–436
drawing images for, 419–421
end detection for, 464
event listener for, 429–430
fixing problems in, 456
friction in, 458, 459
image loading promise for, 421–425
including instructions with, 461
keyboard events for, 430–435
losing focus in, 435–436
making playable, 465
objects for, 436–460
party, 137–140
physics used in, 457–458, 459
running, 441, 463–464
scores added to, 453–454, 464
sound added to, 140, 452–453
sprites in, 436–438, 443–452, 456–460
start screen for, 461–462, 463
gameStart method, 441, 442, 463
gameUpdate function, 428, 433–435, 442–443, 463
“get” requests, 29
getAttribute method, 185, 186–187
getDescription method, 349, 350–352
getElementByID method, 45–46, 47, 55
getElementValue function, 281
getHighest function, 250
getHours method, 72
getHTML method, 358–359
getImages function, 423, 424
getItem method, 294, 295
getLargestStockRef method, 353, 354
getLowest function, 250
getNumberFromElement function, 226, 229, 230–231, 260, 263
getRandomColor function, 418
getRandomInt method, 353, 417
getTestItems method, 353, 354
getTotal function, 250
Gimp program, 419
Git program, 13–14
installing, 14
repositories in, 17
GitHub service, xviii, 16
private work on, 24
repositories on, 17
global variables, 134–136, 142, 143, 235, 417
H
headers
function, 227, 237
response, 404
heading tags, 35
helper functions, 280–281
hierarchy of classes, 345, 347–348
High and Low game, 139
highlighting elements, 269
host element, 29, 393
hover selector, 87
href attribute, 41
HTML (Hypertext Markup Language), 12, 27–50
audio element, 55, 56
badly formatted, 37–38
button creation, 42–44
canvas element, 410–425, 468
comments added in, 38, 133
creating, 359–360
data attributes in, 184–188
document formatting, 41
heading creation, 35
how it works, 29–32
images added in, 38–40
input element, 44–45, 244
JavaScript and, 45–48, 58, 199–201
links used in, 41–42
origins and development of, 28
paragraph layout, 34
prototype example, 277–278
routing in, 393–394
schema for building, 305–308, 358–359
styles added to, 64–85
symbol display, 32–33
text display, 49–50
validator site, 38
web servers and, 396
<html> tag, 41
HTTP and HTTPS protocols, 28, 29
Node.js platform and, 389–390, 404
server requests vs. responses, 406
stateless description of, 407
I
i variable, 233, 236
ice cream sales program, 242–269
arrays used in, 246–248, 265–268
collections of data in, 242–246
detecting invalid values in, 251–252
finding highest/lowest sales in, 249–251
fixed-width layouts for, 268–269
highlighting elements in, 269
user interface for, 252–264
id attribute, 44, 58, 90
identifiers, 108–109
identity operator, 152, 173, 174
if construction, 158–161, 173, 174
blocks of statements in, 160–161
else keyword added to, 159–160, 174
Math.random function used in, 172
images
adding to web pages, 38–40
alternative text for, 39
animating, 427–429
drawing on a canvas, 419–425
example of moving, 428–429
file types for, 419–420
loading and drawing, 420–421
program for displaying, 57
promises for loading, 421–425
<img> tag, 38–40, 57, 419
index values, 271–272
indexer or subscript, 246
infinity value, 11, 148
information vs. data, 103
inheritance, 343–344, 345–347, 364
innerText property, 51, 243
<input> tag, 44–45, 244, 278, 318
input paragraphs, 254–257, 258
input validation, 175
installing
Git program, 14
Node.js program, 387–389
Visual Studio Code program, 15–16
Internet of Things (IoT), 97
Internet vs. World Wide Web, 59
isNaN function, 230
J
Java programming language, 5, 346
JavaScript
Boolean thinking in, 146–157
data processing in, 99, 100, 104
evaluating expressions with, 100–102
examples of talking to, 10–12
exceptions thrown by, 324, 364–365
functions and statements in, 43
HTML and, 45–50, 58, 199–201
identifiers in, 108–109
local storage, 292–295
origins and intention of, 5
programming languages and, 4–5, 6, 23
prototype example, 279–280
tools for working with, 13
variables in, 46, 58, 105–108
web browsers and, 6
JPEG file format, 419
JSON (JavaScript Object Notation), 295–299
adding type info to, 355–356
class hierarchy and, 355
code analysis of using, 299
encoding object data with, 295–298, 317
example of working with, 296–297
exceptions thrown by, 299, 324, 325–326
fetched data and, 382
validator web page, 327
JSONparse method, 356, 357
K
keyboard events, 430–435
code analysis, 430–431, 432–433
gameUpdate function, 433–435
object position control, 431, 432–433
keydown event, 429–430, 433, 463
keyup event, 431, 433
keywords, 24
L
label element, 244, 255
lambda functions, 375
layouts
fixed-width, 268–269
paragraph, 34
styles vs., 81
length property, 271
let keyword, 193, 205, 235–236, 238
letDemo function, 236
<li> element, 164, 188
lineTo method, 412
<link> element, 81
links, HTML, 41–42, 81
listen method, 390, 392, 404
lists
creating, 369–370
investigating, 189–190
ordered, 164
unordered, 188
loadDataStore function, 331–332
local storage, 292–295, 317
explanation of, 292–293
investigating the use of, 293–295
web browsers and, 293, 318
local variables, 135, 233–236
let keyword for, 235–236
scope of, 234–235
localhost address, 391
LocalStorage object, 293
logic errors, 109–110
logical operators, 154–157
lookup tables, 265–266
loops
for, 191–195
for-of, 195–196
while, 201–202
M
makeElement function, 307–308, 315
makeInputPar function, 254, 255, 256
management
error, 335
local storage, 293
style, 86
manifest configuration file, 401
map method, 379, 402
margins, text, 77–79, 88
markup languages, 29–30
Math class, 354
Math.random function, 172
max attribute, 230–231, 254
measureText method, 462
menuInput style, 229
menuInputError style, 229
menuLabel style, 269
message variable, 46
methods, 45–46
adding to classes, 348–349
functions distinguished from, 61, 341, 365
overriding in subclasses, 350–352
Microsoft Paint program, 419
Microsoft Press resources, xix
min attribute, 230–231, 254
mobile devices, xviii
modules, 389
monospaced font, 36
mouse rollover
color highlighting on, 66–67
rollover style and, 87
moveTo method, 412
moving images, 428–429
multiplication table program, 196–203
code analysis, 199–201
deleting elements from, 201–202
displaying scores in, 270
ideas to investigate for, 202–203
myCanvas variable, 411
myContext variable, 412
N
names
function, 213, 239
sorting array of, 373
NaN value, 11, 125, 141, 142, 148, 230, 231
Nerves of Steel game, 138
nesting, bad, 37–38
Netscape Communications Corporation, 5
networks
JSON data received from, 383
text received from, 384
new keyword, 72, 75, 339, 364
Node.js program, 387–401, 403–404
HTTP module, 389–390, 404
installing and testing, 387–388
multiple path use, 394–396
node package manager, 401, 404
purpose and limitations, 389
server deployment, 401
web server creation, 389–400
node package manager (npm), 401, 404
notation
dot vs. bracket, 300, 317
JavaScript Object, 295–299
null value, 299
Number function, 124, 125, 141, 142, 213
numbers
combining text and, 120–121
converting text into, 122–123
entering invalid, 125–126
floating-point, 114–116
random, 116–118, 137–139, 222–226
reading, 259–260
real, 112–113, 114, 141
whole, 112–113, 141
numeric operators, 111
O
obfuscator programs, 23–24
object-oriented design
explanation of, 341–342
inheritance mechanism in, 343–344
objects, 288, 316–317
abstraction using, 344–345
class creation and, 339–340
constructors and, 340–341
creating, 288–291, 339
empty, 288, 300, 316
example of using, 291–292
JSON for encoding data in, 295–298
polymorphism and, 350
position control for, 431
promise, 381–382, 424, 426
properties of, 50–51, 300, 316–317
references to, 49, 60, 290–291, 299, 317
schema for building, 308
storing data in, 288, 292–293, 295
<ol> element, 164
onclick attribute, 43, 225, 236
onerror event, 421
oninput function, 313–314, 315
onload event, 74, 77, 253, 421, 441
onmouseout event, 67
onmouseover event, 66, 86
openPage function, 361
OpenWeather service, 379, 398
operands, 100, 110, 141, 142
operators, 100, 110, 141, 142
comparison, 150–152
logical, 154–157
numeric, 111
ordered lists, 164
overlapping elements, 37
overriding methods, 350–352
P
<p> tag, 34
paragraphs
creating input, 254–257, 258
laying out text in, 34
parameters
arguments and, 216–217
functions with multiple, 218
as values, 217
parse method
JSON strings and, 297, 299, 317, 325–326
URL strings and, 395–396, 397
party games, 137–140
paths
defining and drawing, 412
in URL structure, 29, 393
using multiple, 394–396
Petzold, Charles, 104
Phasor game engine, 465
physics of games, 457–458, 459
pixels, 39, 78, 88, 90
pizza calculator, 127–129
playback control, 56, 140
player sprite, 445–446
plus (+) operator, 111, 119, 120
PNG file format, 419
polymorphism, 350
pos variable, 284, 285
<pre> tag, 35–36
preformatted text, 35–36, 59
Preview image editor, 419
print function, 12
problem solving, 311
programming languages, 4–5, 6
compiled, 23
determining the “best,” 5
scripting, 23, 102
programs
audio added to, 55
bugs vs. faults in, 67
comments added to, 131–133, 141
data processing in, 98–99
error handling for, 227–232
good specifications for, 134
interpreting, 102
user interface for, 162, 163–165
variables in, 105–108
See also applications
Promise.all method, 422–423, 426
promises, 381–387, 405–406
controller function for, 422
explanation of, 381–382, 386, 403, 405
finally function in, 385
handling errors in, 384
image loading, 421–425
importance of understanding, 427
investigating, 385–387
JSON delivery process, 382
managing multiple, 422–423, 426
simplifying with anonymous functions, 383
text delivery process, 384
waiting for results of, 424–425, 426
properties
attributes vs., 60
explanation of, 300
object, 50–51, 300, 316–317
property accessors, 300–304
explanation of, 300, 305, 319
investigation of, 301–303
property identifiers, 303
propertyName variable, 304
proportional fonts, 36
prototypes
HTML, 277–278
JavaScript, 279–280
style sheet, 278–279
pseudocode, 249
px unit, 78, 88, 90
Q
query strings, 397–398, 404, 406
quote character, double (") and single ('), 119, 141, 143
R
random artwork, 417–418
random function, 116, 117, 118
random numbers, 116–118, 137–139, 222–226, 469
Raspberry Pi computers, xviii
real numbers
floating-point numbers and, 114–116
whole numbers vs., 112–113, 141, 142
recursion, 212
reduce method, 378, 402
refDemo variable, 290–291
references
as arguments, 219–220
array of, 372
game, 440
object, 49, 60, 290–291, 299, 317
property accessors and, 319
stored in JSON strings, 299
relational operators, 152
removeChild method, 201, 204
removeItem function, 295
repeating code, 343
repositories, 17–19
requestAnimationFrame method, 427, 429
requests, HTTP, 406
require function, 389, 401, 403
resetFind function, 314
resource information, xix
responses
contents of, 404
JavaScript commands and, 10–12
requests vs., 406
result variable, 125
return keyword, 222
rgb function, 418
ride selector program, 161–172
code added to, 165–168
example of modifying, 178–181
fixing faults in, 181–183
switch construction in, 168–170, 171
user interface for, 162, 163–165
rollover style, 87
running games, 463–464
S
salesItems element, 259–260
sans-serif fonts, 68, 70
saving files, 20
scaffolding, 401
schemas, 304–308
data storage created from, 309
designing for applications, 304–305
HTML built from, 305–308, 358–359
objects built from, 308
scope of variables, 234–235
scores
adding to games, 453–454, 464
displaying in programs, 270
<script> element, 43, 58
scripting languages, 23, 102
searching. See finding
selectors
color highlighting using, 86–87
style sheets using, 80
semicolon (;) character, 76
sendResponse function, 395
serif fonts, 68, 70
servers
code analysis of using, 390–392
deploying Node.js, 401
process of building, 396
See also web servers
service function, 404
setAttribute method, 187
setInterval function, 74, 77, 88, 427
setItem method, 294, 295
setTimeout function, 52, 54, 57, 58
setup element, for loop, 191
shadow effect, 164–165, 462
side effects, 136, 137
single quote (') character, 119, 141, 143
slide shows, 57
software. See programs
solving problems, 311
sort method, 371–373, 374
sorting data, 371–373, 376–377, 402
sound
adding, 55, 140, 452–453
playback control, 56, 140
source code, 13
source code highlighting, 24
source code management (SCM) software, 14
Source Control dialog, 18
<span> element, 84–85, 88, 90
specifications, 134
spelling errors, 110
sprites, 436–438, 443–452, 456–460
AI added to, 456–457
cheese, 443–444
cracker, 447–452
friction added to, 458
killer tomato, 456–458
physics of, 457–458, 459
player, 445–446
superclass for, 438
timed, 459–460
square brackets [ ], 189, 288, 296, 319
src attribute, 39, 55, 57, 420
start and end tags, 32
start screen for games, 461–462, 463
startsWith method, 312, 314, 317
statements
alert, 43
assignment, 105
blocks of, 160–161, 193
for loop, 191
static class members, 352–355, 357, 364
static keyword, 353, 354
status code, 404
Step control, 262–263
stockItemCompare function, 372–373
storage
arrays used for, 246–248, 281–283
class hierarchy and, 355
examples of breaking, 333–334
local, 292–295, 317
schema produced for, 309
storeContact function, 283, 292
storeData function, 308
stories, user, 336
stringify method, 296, 297, 317, 325, 329–330
stringOrderCompare function, 373
strings of text. See text
stroke method, 412–413
<strong> tag, 32
<style> tag, 80
style sheets
adding to documents, 80, 88
exploring the use of, 83
file created for, 80–81, 88
prototype example, 278–279
See also CSS
styles, 64–91
cascading, 85–86, 88
classes of, 82, 84
color, 64–67
conflicting, 89
explanation of, 64
font, 68–71
layouts vs., 81
managing, 86
margin, 77–79
menu label, 269
overriding, 86
selectors for, 80, 87
style sheet for, 80–81
text alignment, 71
subclasses
class hierarchy and, 345
extending classes and, 346
inheritance mechanism and, 343–344
overriding methods in, 350–352, 364
template for, 438
subscript, 246, 271
super keyword, 348, 352, 364
Super Search feature, 310–315
code analysis of, 314–315
problem solving for, 311
solutions for creating, 312–314
superclasses
class hierarchy and, 345
game sprites and, 438
inheritance mechanism and, 343–344
super keyword and, 348, 352
switch construction, 168–171
explanation of using, 168–170
missing breaks in, 171
path for controlling, 394
symbols, HTML display of, 32–33, 58
synchronized actions, 380
T
TCP/IP protocol, 29
temperature conversion program, 130–131
template, subclass, 438
test element, for loop, 191
testing
error, 110, 126
Node.js, 388
text
aligning, 71, 88
alternative, 39
arrays of, 265
combining numbers and, 120–121
converting into numbers, 122–123
delimiters for, 119
displaying, 49–50, 462
emphasizing in HTML, 30
encoding with JSON, 295–299
escape sequences for, 120
fonts selected for, 68–71
getting from networks, 384
heading creation, 35
indicating with quotes, 10
margins around, 77–79
paragraph layout, 34
preformatted, 35–36, 59
as property accessors, 300–304
shadow effect, 164–165, 462
styling, 64, 71
text method, 384
textarea element, 278, 318
textContent property, 49, 50–51
Theme Park Ride Selector. See ride selector program
then method, 381, 382, 384, 386, 403, 405–406
this keyword, 340, 341, 364, 365, 376, 440, 442–443
threads, 426
throw statement, 329
ticking clock program, 72–77
code analysis, 75
creating, 74–75
time display, 72–73
timed sprites, 459–460
timeString variable, 73
Tiny Contacts application. See contacts app
toFixed method, 130
Torvalds, Linus, 14, 24
total variable, 135, 136
totalizer program, 133–137
trim function, 314, 317
true keyword, 146, 147–148
try block, 326, 327, 328
try-catch construction, 326, 327, 328, 363, 386–387
Twitter information, xix
two-dimensional arrays, 272
type attribute, 44
type property, 356
U
<ul> element, 164
undefined value, 106, 107, 141, 142
unordered lists, 188
update element, for loop, 191
update method, 434, 438, 451, 453, 460, 464
URLs (uniform resource locators)
parse method and, 395–396, 397
query strings added to, 397–398, 406
structure of, 28–29, 59, 393
user interface
designing for customers, 162, 252–254
examples of building, 163–165, 252–264, 357–359
improving for contacts app, 309–316
input paragraph creation, 254–257
users
reading input from, 44–45
receiving ideas from, 310, 316
written stories for, 336
V
validator site, 38, 327
value attribute, 44
values
Boolean, 146–149, 173, 174
floating-point, 114–115
functions returning, 222–226
NaN, 11, 125, 141, 142, 148, 230, 231
parameters as, 217
query, 397
undefined, 106, 107, 141, 142
var keyword, 48, 72, 75–76, 205, 235, 238
variables
control, 191
creating, 48, 72, 75–76, 193, 236, 239
function of, 46, 105, 141
global, 134–136, 142, 143, 235, 417
local, 135, 233–236
scope of, 234–235
working with, 106–108
video walkthroughs, xviii
Visual Studio Code program, 13, 25
App Service Extension, 401
cloning repositories with, 18–19
color styles added in, 65
editing files with, 19, 20–22
finding files in, 21
font selector in, 69
installing, 15–16
keywords in, 24
Node.js test in, 388
server run in, 390–391
Visual Studio suite, 25
W
weather application, 379–385
web browsers
badly formatted HTML in, 37–38
JavaScript used in, 6
local storage managed by, 293, 318
web pages, 28
building from code, 196–201
fetching with URLs, 28–29
ideas for creating, 57
images added to, 38–40
viewing code on, 6–9, 273
web servers
creating with Node.js, 389–400
deploying Node.js, 401
JavaScript and, 23
web services, 398, 402
websites, 28
while loop, 201–202, 204
whole numbers, 112–113, 141, 142
window events, 429–430
window object, 427, 429
World Wide Web (WWW)
HTML and, 28
Internet vs., 59
World Wide Web Consortium (W3C), 28
write method, 392
OceanofPDF.com
OceanofPDF.com
Code Snippets
Many titles include programming code or configuration examples. To
optimize the presentation of these elements, view the eBook in single-
column, landscape mode and adjust the font size to the smallest setting. In
addition to presenting code and configurations in the reflowable text format,
we have included images of the code that mimic the presentation found in
the print book; therefore, where the reflowable format may compromise the
presentation of the code listing, you will see a “Click here to view code
image” link. Click the link to view the print-fidelity code image. To return
to the previous page viewed, click the Back button on your device or app.
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
Image
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
OceanofPDF.com
Contents
Cover Page
Title Page
Copyright Page
Dedication Page
About the author
Contents at a glance
Contents
Introduction
How this book fits together
How you will learn
What you will need
Downloads
Acknowledgments
Errata, updates, and book support
Stay in touch
Part 1: The world of JavaScript
1. Running JavaScript
What is JavaScript?
Our first brush with JavaScript
Tools
What you have learned
2. Hypertext Markup Language (HTML)
HTML and the World Wide Web
What is HTML?
Making active web pages
Egg timer
An image display program
What you have learned
3. Cascading Style Sheets (CSS)
Putting on the style
Cascading styles
What you have learned
Part 2: Coding with JavaScript
4. Working with data
Computers as data processors
Data and information
Variables in programs
Working with text
Making applications
Global and local variables
What you have learned
5. Making decisions in programs
Boolean thinking
The if construction
Use decisions to make an application
What you have learned
6. Repeating actions in programs
App development
Building web pages from code
What you have learned
7. Creating functions
What makes a function?
What you have learned
8. Storing data
Collections of data
What you have learned
9. Objects
Make a tiny contacts app
Use JSON to encode object data
Use property accessors
Use a data schema
Improving the user interface
What you have learned
Part 3: Useful JavaScript
10. Advanced JavaScript
Manage errors with exceptions
Class design
What you have learned
11. Creating applications
Data analysis
Read the weather
Node.js
Deploying a Node.js server
What you have learned
12. Creating games
Use the HTML Canvas
Animate images
Control gameplay
Create game objects
Complete the game
What you have learned
Index
Code Snippets
i
ii
iii
iv
v
vi
vii
viii
ix
x
xi
xii
xiii
xiv
xv
xvi
xvii
xviii
xix
xx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
OceanofPDF.com
Table of Contents
Cover Page
Title Page
Copyright Page
Dedication Page
About the author
Contents at a glance
Contents
Introduction
How this book fits together
How you will learn
What you will need
Downloads
Acknowledgments
Errata, updates, and book support
Stay in touch
Part 1: The world of JavaScript
1. Running JavaScript
What is JavaScript?
Our first brush with JavaScript
Tools
What you have learned
2. Hypertext Markup Language (HTML)
HTML and the World Wide Web
What is HTML?
Making active web pages
Egg timer
An image display program
What you have learned
3. Cascading Style Sheets (CSS)
Putting on the style
Cascading styles
What you have learned
Part 2: Coding with JavaScript
4. Working with data
Computers as data processors
Data and information
Variables in programs
Working with text
Making applications
Global and local variables
What you have learned
5. Making decisions in programs
Boolean thinking
The if construction
Use decisions to make an application
What you have learned
6. Repeating actions in programs
App development
Building web pages from code
What you have learned
7. Creating functions
What makes a function?
What you have learned
8. Storing data
Collections of data
What you have learned
9. Objects
Make a tiny contacts app
Use JSON to encode object data
Use property accessors
Use a data schema
Improving the user interface
What you have learned
Part 3: Useful JavaScript
10. Advanced JavaScript
Manage errors with exceptions
Class design
What you have learned
11. Creating applications
Data analysis
Read the weather
Node.js
Deploying a Node.js server
What you have learned
12. Creating games
Use the HTML Canvas
Animate images
Control gameplay
Create game objects
Complete the game
What you have learned
Index
Code Snippets
OceanofPDF.com