CS559 Spring 2021 Sample Solution - Workbook 1
Written by CS559 course staff
You can try out the example solutions here. The interesting code is on page 6.
Box 1: Where does my code go?
Here is a miniature web page 01-03-01.html. It’s boring but it does have a little program in it.
The output of this program, from the
console.log function, will be in the “console” of your web browser. Now is a good time to look for it (it should say “Box 1’s initial message to the console”, but you’ll also see the output from box 3 and 4). You might try opening the box as a separate web page (here’s a link). See what the console shows for this.
Box 2: Another place to put code
When you make a button (or other element), you can attach code to it right in place, as in this example (again, look at the console and the code). Since this is the second box,
In general, we prefer not to put much code hidden inside of the html. It’s fine for short things, but when the code gets complicated (as it will), it’s easier to have it in a separate file.
Just to make sure you’re reading along, change this box so that when you press the button, the message in the console is a grammatically complete sentence like “Button one was pressed.” (yes, there are points on the rubric for this).
- change text on button press (Box: 01-03-02) (Points:2)
Box 3: Where to put code
Here’s another simple example:
If you’re curious (and you should be) the
Box 4: When to run code
There is a question of when those little snippets of code get run. In some cases, it’s simple: for the button in Box 2, we assigned code to the
onclick event of the button, so the code was run when this even happened (we’ll discuss events more later). But, for the code in the script tags (especially when the script tag loads another file), the code will be executed when the script tag is processed - and there’s no guarantee of what order that will happen in. This becomes even more complicated because the web browser can do things asynchronously - it doesn’t wait until the first thing finishes before starting the second.
to access our web page, but we don’t know if the web page has finished
loaded (and is ready to be accessed) when our program is run.
Note: We are showing you the “old school way” to defer execution until after the page loads. We’ll show you the newer method later. We’re purposefully showing you the old way since it is instructive. And it will be useful later.
When you look at the code, notice (look in 01-03-04.html ) how there is a script inside the paragraph (like in box 1), but there is also a script at the beginning. This script creates a function (that is not named) and assigned to
window.onload (the handler for the event that occurs when the window finishes loading). Because this function is called after the window is called when the window is finished loading, it happens after processing the web page (so it’s output happens after the other output).
Make sure you understand this simple example - as it is quite important. It uses some key concepts (like creating functions and assigning them to handlers).
In the example, I chose to define the function anonymously. I could have used the other function declaration syntax:
These are pretty much equivalent. The version on the right names the function
main so it can be used elsewhere, but it means we need to be careful not to use it again by mistake. By not naming it, we prevent it from being used again.
There is one other subtlety here: when we embed 01-03-04.html as an
iframe on this web page, it is treated as a separate web page. The
window referred to in the code is the inner web page (not the outer one). The onload happens after the inner web page is finished loading. On a web page like this (with many embedded web pages), we may not know what order the different web pages will finish loading. This generally isn’t an issue, because usually we don’t do much embedding.
Almost always, when we add code to a web page, we will set things up to run after the page finishes loading.
Box 5: Multiple Start Functions
Having a start function is so useful that we often want to have many of them. But, the window has only a single
onload function. So, if we tried:
In this case, it’s easy to fix things (because the 2 statements are in the code next to each other, we could re-write it as one function). More generally, the solution is to have the function call the function that was previously defined.
A simple workaround is to have each function remember what function was defined before it. We could replace line 2 above with:
There are many downsides to doing things this way - you have to change each of your functions, and you need to invent a variable for each one to store the information. A more elegant implementation is given in 01-03-05.html. We define a function called
addStart that adds things to a list of functions that should be called at window onload.
We’ve given you addStart, so you don’t need to write it yourself (it will be part of future workbooks). However, you should look at the code for it carefully and make sure you understand it. It’s a nice example of the use of a
closure - an important tool in functional programming that we will use a lot in class.
We’ll talk more about functional programming in class and later in this (and future) workbooks.
The modern way to defer loading
The “modern” way to have a script run after the page has finished loading is to specify that in the script tag.
Normally, a script tag that loads a file, such as
<script src="01-03-03.js"></script>, gives the browser some flexibility in when it chooses to run the script. However, we can add the
defer flag like this:
<script src="01-03-03.js" defer></script> which tells the browser to run the script only after the page has finished loading. This is explained on the W3 Schools documentation on defer and HTML documentation for the script tag.
Unfortunately, this only works when we load scripts from a file (which is the usual thing to do, but wouldn’t work in the examples above). Most of the workbook code still uses the
windows.onload method - mainly for historical reasons.
But, the big reason for emphasizing them early in the class is that they really are a convenient way to do graphics programming. They will come up a lot in the programming we do for class. So, it’s good to get familiar with them now.
Part of the reason for this is that we like to (or, as we will see on the next page, are often forced to) think about out programs in terms of functions that get called when events happen. In the examples so far, we had functions that executed when a button was pressed or when the page finished loading - each of these are events.
It’s worth looking at a simple example before we move on… Here is Box 01-03-02, re-written to put the script in a different place.
This is now example 01-03-06.html. Let’s look at the key lines…
Line 15 finds the button by searching for an HTML element on the page with the name button1. Good programming practice would have checked that button was actually found. We’ll do this often - we find objects on the web page by ID and do things to them.
The more interesting thing is what we do to the button: we assign something to its
onclick property. This stores a function that gets called when the button is pressed. But notice that we put the definition right in the assignment. We are defining the function in place. You can think of the
function keyword not just as defining a function, but as effectively running the compiler and producing a “function object” that can be stored in an attribute of the button (or any other variable).
Effectively, the code inside the braces on lines 16-18 doesn’t get compiled until the
function expression is executed. Line 17 doesn’t get executed when this code is run - it just gets fed to the compiler. The output of the compiler - which is a “function object” - can be produced and stored somewhere, and called later.
(note: this idea of “running the compiler” is a simplification of what really happens in order to give you a mental model of how things work)
The fact that we’re effectively running the compiler as our code runs brings up interesting possibilities. We can define new functions as our program is running, and those functions have access to the current state of the program.
Here’s a slightly different example…
You can see this in 01-03-06.html. The code is a little different…
number in the middle of the string.
So, the big question… what is the value of this variable?
A thing to notice is that the variable
number is declared outside of the function we are creating. When we “compile” the function, the variables that enclose the function (defined outside, but available inside) are kept. This is called closure - it is a fundamental functional programming concept. It is tricky to learn. Most students have to hear it several times before they get it. I will explain it multiple times during class. There will (almost certainly) be exam questions involving closure.
Consider what happens with this program. When the code is executed,
function calls the compiler. At this point, the variable
number is 1. However, line 16 doesn’t execute - it is just compiled. It keeps a reference to the variable
number. This is closure. After the compiler is done creating the function
number is set to 2. Later on, when the button is pressed, the function is executed. At this time, it refers to the
number, which has value 2.
That’s a closure. It lets functions access data defined outside. We’ll see a lot more examples. Don’t worry if you don’t get it the first time.
So now we’ve seen where code can go and how functional programming lets us define the functions we can put in various places. Now let’s see how to make it do something useful on the Next Page
- (Box: 01-03-02) (2 pts) change text on button press