JavaScript

A hike through JavaScript

By October 7, 2016 No Comments

As a frontend designer I bump into JavaScript on a daily basis. Whether it is code snippets, code solutions, or just JavaScript doing what it does… I am surrounded. So I decided that it is about time to learn. This blog article is my hike through JavaScript from the beginning until the end. Its intention is to help me learn by explaining but also to help others who are also learning, doubtful or just need a second opinion.

Before I start this hike I need to make sure that I have all my tools. Here’s the list of tools I’ll be using:

and on every hike you should always take a bottle of water with you!

So as from tomorrow I will start my hike and I hope that I will have many fellow hikers because a journey alone can be very lonely.

Setup Backpack

So we all have our ways and means of hiking through the forest, I mean JavaScript. This is mine! You can either do it this way or find your own way!

WARNING!! I use an OS 10.12

First, I open terminal (this part you can do through terminal or manually on your laptop). I create a folder named Eloquent Javascript:

Linux/OSX/Windows

mkdir eloquentJavascript

 

Then I go into that folder to create a html file:

Linux/OSX

$ cd eloquentJavascript

$ls
$ touch day1.html
$ ls
day1.html
$

Windows

> cd temp
> New-Item day1.html -type file
> ls

 

open it up with atom

atom day1.html

 

In the document open and close script tags so that the browser knows that we are working with JS

<script>

</script>

 

Drag this document to a new tab in your browser (if this fails to work: right click it, copy full path and paste that into your nav bar).

Open up DevTools Console (on mac that is cmd + alt + j) and we are ready to go!

TIP! I like to split my screens in two so it looks like this:

setup-screen-javascript

This can be done very easily with spectacle.

Day 1. Language: Value, types and operators

Ok so here we go, using Eloquent JavaScript as our map let’s begin! I recommend you type everything out yourself that you see in the code boxes to get comfortable with the language!

We will start by learning what values, numbers, strings,… are. Here’s a list and their definition:

Bits: What a computer reads, known as 0’s and 1’s. They are any kind of two valued things. We don’t need to go too much into detail here.

Values: are made of bits. To make it easier to understand they can be numbers, strings, Booleans, objects, functions, and undefined values.

Numbers: yes they are numbers. Inside numbers you have:

Integers which are whole numbers (2, 54, 23,..)

Fractional numbers which are written with a dot (2.5, 3.24,…)

For very big or small numbers an exponent can be used by adding “e” followed by the exponent of the number (2.998e8)

Arithmetic

In JavaScript we use signs to do our arithmetic and these signs are called Operators:

addition: +
multiplication: *
subtraction: -
division: /
*remainder of: %

It’s important to note that in JavaScript the order in which the operators are applied is determined by the precedence of them. So in other words, unless you use parentheses a multiplication comes before an addition.

Example:

100 + 4 * 11

What will happen: 4*11 = 44
100+44=144

*remainder of how will this show? Ok so this might seem a bit confusing but here’s an example to clarify it: 314 % 100 = 14. So the remainder of 314 / 100 = 14 (this is only the remainder of).

Special numbers: of course there are special numbers! These are ones that do not behave like normal numbers. The first two are:

Infinity and – Infinity. I wouldn’t put too much trust into these.

NaN: Stands for Not a Number. This one will appear from time to time.

Strings: are used to represent text and that text is surrounded by quotation marks.

Example:

“My name is Ana and JavaScript will print me out just like text”

you can use both single and double quotation marks for this but be careful because this can get tricky. For example, if you use single quotations and need to add the abbreviation of it is (it’s). But we will not go into too much detail right now, step by step we will finish this hike!

Note: you cannot separate the text with pressing ENTER, the string has to stay on a single line. So if you do need to separate the text you can use \n
A backslash is a special character that tells JavaScript that something is about to happen… …. But what if you need to use a backslash in your text?!?! Well you use two \\ and only one will show.

Unary operators:These are the operators that aren’t symbols.
typeof: will tell you the type of value you have given.

Example:

console.log(typeof 4.5) 
//> number
typeof “hello” 
//> string

Binary operators:

Operators that take on two values. The minus operator can be used as both a binary and a unary operator:

(- (10 - 2))
//> -8

Boolean Vales:
These have two values: true and false (which are written like that).

Comparisons:

One way to produce boolean values are through a comparison:

10 > 4 = true
10 < 4 = false
> greater than>
< less than
>= greater than or equal to
<= less than or equal to
== equal to
!= not equal toThese comparisons can also be used on strings!

Logical operators:
There are some operations that can be applied to Booleans themselves.

&&: represents logical and

console.log(true && true);
//> true
console.log(true && false );
//> false

|| operator is a logical or

console.log(false || true);
//>true
console.log(false || false);
//>false

!: is not

console.log(!true);
//>false

Order in which JavaScripts executes operators
|| are the lowest
then &&
then comparison operators (>, ==, and so on)
then the rest

Ternary operators are conditional operators that work with a ? and a :

console.log(false? 1:2);
//>2
console.log(true ? 1:2);
//>1

When it is true the value before the colon is chosen.
When it is false the value after the colon is chosen.

Undefined Values

null and undefined are both used to say there is an absence of a value.

Automatic type conversion
So JavaScript goes out of its way to accept almost any program you give it. This can be both good or bad. Right now we’re going to see one of the reasons why this is good!

console.log(8*null)
//> 0
console.log(“5” - 1)
//> 4
console.log(“five” * 2)
//> 10

In the last two cases it will recognise the two strings as numbers..

Short-circuiting of Logical operators
As logical expressions are evaluated left to right, they are tested for possible “short-circuit” evaluation using the following rules:
false && (anything) is short-circuit evaluated to false.
true || (anything) is short-circuit evaluated to true.
The rules of logic guarantee that these evaluations are always correct.

Tune in tomorrow for more!

Day 2. Program Structure part 1

Know that we now the very basics let’s go further up the mountain.

Expressions and Statements
We just saw how we made some values, applied operators and got new values. This is very useful but there is so much more we can do.

Expression: is every fragment of code that produces a value. Every value that is written literally is an expression. An expression between parentheses is… an expression.

Statement: is a collection of expressions, almost. Let’s put this differently. In the human language an expression would be a fragment of a sentence and a statement the whole sentence.

Program: is a list of statements.

Variables: are basically a name (or value) that we give to a set of data. So say we have a chunk of code, we can give that chunk of code a value to make things easier.

Example:

var boots = “boots may come in handy for the usual hike but maybe not so much for this one..” 
console.log(boots);
//>“boots may come in handy for the usual hike but maybe not so much for this one..” 

var caught = 5*5;
console.log(caught);
//>25

let’s have some fun!

anaCidre = 150
anaCidre = anaCidre-30
console.log(anaCidre);
//>120

If we were to create a JavaScript document (add link to Javascript document), add the line about and run boots on DevTools Console it would return us everything that comes after the equal sign. Now this may seem a bit silly now but wait until we get into it 😉

No idea what I was going on about in the previous paragraph, head over to my JavaScript setup section here.

Keywords and Reserved words

These are a bunch of words that JavaScript already uses so you cannot use them for your variables. Here’s the list:

break case catch class const continue debugger
default delete do else enum export extends false
finally for function if implements import in
instanceof interface let new null package private
protected public return static super switch this
throw true try typeof var void while with yield

The Environment
Is where you have your collection of values, variables at a given time.

Functions: In the previous chapter when describing values I mentioned functions. Let’s have a closer look at those. AGenerally speaking, a function is a “subprogram” that can be called by code external (or internal in the case of recursion) to the function. Like the program itself, a function is composed of a sequence of statements called the function body. Values can be passed to a function, and the function will return a value.

Ok let’s test this out by using the variable alert which is an already existing JavaScript function:
alert(“A wild brown bear appeared!”);

KNOW YOUR LANGUAGE: if you execute a function you say: “I’m invoking a function” or “I’m calling a function” or “I’m applying a function”.

A function is called by putting a parentheses after an expression that produces a function value. Normally you will give that function a variable name and that is what will be used. The values within the parentheses are given to the program inside the function.
Arguments: Values given inside the parentheses calling a function.
Let’s have a look at a different very well used function

The console.log function

This function prints out its arguments to some text output device. If you are using the same setup as I am then it will print it to your DevTools Console. Try this:

write this in your html file, save it and refresh your browser.

var x = 30;
console.log(“the value of x is”, x);

Return values

When a function produces a value we say it has returned that value.

Prompt and confirm

Just like the alert function we can have a confirm function which will make the end user choose between “ok” and “cancel”

confirm(“isn’t this is brilliant Hike?”);

and the prompt function will allow the end user to write something, for example replying to a question.

prompt(“where to next?”,”...”);

Day 3. Program Structure part 2

 

Control Flow

JavaScript will read your code from “top to bottom” unless told otherwise. The general flow in JavaScript is a straight one.

var theNumber = Number (prompt("Pick a number",""));
alert("Your number is the square root of " + theNumber * theNumber);

what this is doing is: it is giving the function “Number” a variable name “theNumber”. The function “Number” is calling the argument prompt which has it’s own arguments: “Pick a number” and “”. The latter is for the person to write a number in there.
Now we are telling the browser to create an alert which gives back the string “your number is the square root of” and then does the square root of the number given. It is all in a straight line.

Conditional Execution
This is one option to tell JavaScript that there will be two different routes based on a Boolean value and not just a straight line.

The conditional execution is written with the if keyword in JavaScript. The if statement executes a statement if a specified condition is true. If the condition is false, another statement can be executed.

Now let’s say in the previous example someone wrote down something that was not a number they would probably get “undefined” back. Let’s make sure they do not get anything back.

var theNumber = prompt("Pick a number","");
if (!isNaN(theNumber))
     alert("Your number is the square root of " + theNumber * theNumber);

the argument to this “if” keyword is what appears in the parentheses after it, in this case it is a !isNaN this expression means (with the if keyword): if it is not, not a number what is given in the argument (theNumber) give the alert.

Now say we wanted to give the end user something back when he or she does not type a number. We can use the else keyword like this:

var theNumber = prompt("Pick a number","");
if (!isNaN(theNumber))
     alert("Your number is the square root of " + theNumber * theNumber);

else
     alert("Hey. Why didn't you give me a number?");

Now what if we needed an extra path? Say for example we ask for a number and depending on what number they give we classify it as small, medium or large. Let’s take a look:

var num = Number(prompt("Pick a number" + ""));
if (num < 10)
    alert("Small");
else if (num < 100)
    alert("Medium");
else
    alert("Large");

Let’s continue our hike onto loops!

while and do loops
Imagine you had to write code that prints off every even number from 0 to 1000… if we did console.log(2) for every single one of these we wouldn’t finish in a day and we would get so bored! Luckily that’s where loops come in, to stop repetition!

Looping control flow allows us to get back to some point in the code and repeat it until it has come to the end. This way to check out while loops:

var number = 0;
while (number <= 12) {
  console.log(number)
  number = number + 2;
}

here we’re telling javascript that WHILE the variable “number” is less than or equal to 12, to print that number and add two.

do loop: is basically the same as a while loop but it will always execute the body at least once, it starts testing whether it should stop only after that first execution. The body is what is inside the curly brackets!

Example:

do {
var yourName = prompt("Who are you?");
} while (!yourName);
console.log(yourName);

what this does is it won’t leave you alone until you write something down that isn’t an empty string

for Loops: these are like while loops but because the pattern seen in the while loop is so commonly used JavaScript provides an slightly short and more comprehensive form, the for loop.

Example:

for (var number = 0; number <=12; number = number + 2) console.log(number); //>0
//>2
//>4

this is exactly the same as the example we saw with the while loop, take a close look at it and try to understand what is going on, if you don’t just leave a comment or send me an email

Breaking Out of a Loop
So when we do these loops we are working with booleans. How? Well we are asking JavaScript if “number” is <= (less than or equal to) 12, if this is true the loop will continue. So returning a false will break the loop.
There is another way to do this and it is by using the statement break that makes the loop break immediately.

Let’s see how this can be useful

for (var current = 20; ; current++) {
  if (current % 7 == 0)
  break;
}
console.log(current);
//>21

here we’re telling JavaScript to start with the number 20, if it is divisible by 7 with no remainder (% 7 == 0) then stop if it has a remainder to add 1 and try again.

Next we’ll go over the structure more in detail and talk about indents, capitalization and more.

Day 4. Program Structure: how to walk the walk

Indenting Code
In most programming languages we use spaces before some code to make it more legible. Even though the program will accept the code without any lines breaks or spacing we must practice and make sure to put the lines breaks and spacing in the right places so that everybody can understand it.
It makes the text more legible. I use the “standard” indentation so I recommend that you copy my code’s indentation to get practice and a feel of it.

Capitalization

Each coder has it’s own way and I recently found out from a friend how you call all these different ways of typing variable names.

bestHikeEver //lower camel case
BestHikeEver //upper camel case
best_hike_ever //underscore case
besthikeever // all lower case

As you can see the last one is very difficult to read so I would not recommend this one. I prefer lower camel case but this is a matter of tastes and who you are working with.

NB: You can use which ever you like but make sure you stay consistent and whatever one you choose for the variable name will have to be exactly the same throughout the code as JavaScript is case sensitive.

Comments

Comments are very handy in JavaScript and all programming languages. They allow you to leave yourself little notes within your code and not get processed by the program, they will be completely ignored.

If you want to write a single line comment just add //.

//this Hike is so lovely and green
//Hey I'm just another comment but don't worry the program won't read me!

for full blocks of text with line breaks it’s best to use /* */

/* I could write a whole poem about hiking here
only if I knew how to write poems.
Maybe I should get back to coding 
just because I am no poet.*/

Handy DIY tips for variables
Updating Variables Shortly

So when looping a program needs to “update” a variable. We can do it like this:

counter = counter + 1

or in a more shorter way (hence shortly)

counter += 1

we can shorten this even if it’s just +=1 or -=1 more by typing:

counter ++
counter--

Dispatching on a Value with switch
There is a more awkward way than doing a line of if statements and this is called switch. Like I said it’s more awkward and I’m not sure to what extent you will need this but let’s have a look at it anyway. It’s like when you are on your hike and you see a massive big spider, you don’t want to but you look at it anyway.

So remember the if looked like this:

if (variable == "value1") action1();
else if (variable == "value2") action2();
else if (variable == "value3") action3();
else defaultAction

ok now let’s look at switch.

switch (prompt("What is the weather like?")){
case "rainy":
console.log ("Remember to bring an umbrella.");
break;
case "sunny":
console.log ("Sunglasses it is.");
case "snowy":
console.log ("Skiing time!.");
break;
default:
console.log ("I have no idea what weather type that is!");

You can put as many case labels you like!

 

Exercises, I would highly recommend you do the ones from the book Eloquent Javascript, he has an online version here

Day 5. Functions

We have already seen function values such as alert and prompt. Functions are like walking boots in a hike, they are needed and there’s no going without. Therefore I’m going to divide this up into three parts to make sure we understand it!

 

Defining a Function

We define a function like we would a variable. Remember how we define a variable? If not here is a quick Example:

var boots = “boots may come in handy for the usual hike but maybe not so much for this one..” 
console.log(boots);
//>“boots may come in handy for the usual hike but maybe not so much for this one..”

To define a function we use the same sort of “equation”:

var square = function(x) {
return x * x;
}
console.log(square(12));

what did we do here? Well we named a function “square” and we gave that function an argument “x”. Inside the function, the body “{}”, we return the argument of the function and times it by itself to give us the square. Then we print it by using console.log().

So a function consists of:
– The name of the function.
– A list of arguments to the function, enclosed in parentheses and separated by commas.
– The JavaScript statements that define the function, enclosed in curly brackets, { }.

A function can have a list of arguments or none at all, let’s have a look at a function without an argument (you still need to add the brackets for it to be a function).

var makeNoise = function() {
console.log("Pling!");
}

makenoise();
//>Pling!

Now let’s take a look at something a little more complex. A function that takes on two arguments

var power = function (base, exponent) {
var result = 1;
for (var count = 0; count < exponent; count ++) result *= base; return result; } console.log(power(2,10)); //>1024

remember that result *= base is the same as result = result * base

Parameters and Scopes

Local variablesVariables declared within a JavaScript function, become LOCAL to the function.

Local variables have local scope: They can only be accessed within the function.

function hiking() {
    var Forest = "Lot's of trees";
    //code here can use Forest
}

Global variablesA variable declared outside a function, becomes GLOBAL.
A global variable has global scope: All scripts and functions on a web page can access it.

var Forest = "Lot's of trees";
//code here can use Forest
function hiking() {
//code here can use Forest
}

Generally it’s recommended to use the local variables so that accidents do not happen and interfere with other functions.

Nested Scopes
Also known as nested functions, JavaScript supports these. Nested functions have access to the scope “above” them.

In this example, the inner function plus() has access to the counter variable in the parent function:

function add() {
    var counter = 0;
    function plus() {counter += 1;}
    plus();    
    return counter; 
}

 

Now let’s create the landscape we are seeing on our hike with nested functions:

 

var landscape = function() {
  var result = "";
  var flat = function(size) {
    for (var count = 0; count < size; count++)
      result += "_";
  };
  var mountain = function(size) {
    result += "/";
    for (var count = 0; count < size; count++) result += "'"; result += "\\"; }; flat(3); mountain(4); flat(6); mountain(1); flat(1); return result; }; console.log(landscape()); //> ___/''''\______/'\_

Each local scope can also see the other scopes that contain it and functions are the only things that create a new scope.

Let’s check out two more things and then we can continue tomorrow.

Functions as Values

As we have learnt, functions act as names for a specific piece of the program. Furthermore a function con do what other values do (use it as an argument to another function, store a function in a new place,..). Same goes for the variable that is holding that function (as a value), it will replace it if you assign it a new value.

 var walkThroughMountains = function(tree){
   readySet.walk("now");
 }
 if (ready)
   walkThroughMountains = function(tree) {};

this will not do anything because ready is not definied, we will go more into detail further along the mountain

Declaration Notation

You do not always have to type var mountain = function(){}; you can write just:

 function mountain (){
};

This is known as a function declaration
What you should know, function declarations are not part of the top-to-bottom control flow. What does this mean?

It means that you can do things like this:

console.log("Together", mountain());
function mountain() {
return "we WILL finish this hike!";
}

it allows you to do print before declaring the function, without worrying too much about the order

Tomorrow more!

Day 6. Functions continued

The Call Stack

I find it very helpful to take a closer look at the way control flows through functions.

This is how JavaScript would work with this functions

function greet(what){
   console.log("Hello" + what);
}

greet("bug");
console.log("Bye");

So here JavaScript starts at the top as we know, then it calls the function greet prints of the arguments in console.log finds the argument given to the function greet in this case it’s a bug. Then it print’s off the final console.log.

Something like this

top
    greet
        console.log
    greet
top
    console.log
top

Now there’s a way to actually check this which I find very useful. You just need to add a debugger; to your code, go on to your DevTools and change the console tab to the sources one and use the “step into” arrow to what JavaScript does step by step.

Let’s do this

function greet(what){
   debugger;
   console.log("Hello" + what);
}

greet("bug");
console.log("Bye");

Then you go into DevTools Source. Here’s an image to help find the step into arrow!

step-into-devtools-jshike

Optional Arguments

When calling an alert it officially only accepts one argument. However, you can pass as many arguments as you like and JavaScript will just ignore them.

If there are too many arguments to a function JavaScript will ignore the rest, and if there are too few then JavaScript will assign the value undefined.

Like everything this has it’s downsides and upsides.
Downside You do no know if you are passing the right amount of arguments, but practice will tell.

Upside You can have optional arguments. This means that you can either call one or two arguments on a functions.

check this out

function power(base, exponent) {
    if (exponent == undefined)
       exponent = 2;
    var result = 1;
    for (var count = 0; count < exponent; count ++)
       result *= base;
    return result;
}

console.log(power(4));
console.log(power(4,3));

See what is happening here? If not send me an email or a comment and I will help you 🙂

closure

Remember local variables? Good. Closures are functions that ‘remember’ the environment in which they were created.

var count = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

count();
count();
count();

console.log(count());

The variable count is assigned the return value of a self-invoking function. The self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression. This way add becomes a function. This means that it can access the counter in the parent scope and makes it possible for a function to have “private” variables.

The next topic from Eloquent JavaScript is Recursion. This is a pretty dense topic so I will leave it for tomorrow. We will need a whole post for this area!

Day 7. Recursion Functions

Recursion
This is probably the most simplified explanation I could come up with: a recursive function is simply a function that in some point calls itself.

Here’s an example to back that up

function factorial(n) {
  if (n === 0) {
    return 1;
  }

  // This is it! Recursion!!
  return n * factorial(n - 1);
}

we are doing the same thing (multiplication) over again to a particular value (an integer) until we get the desired result.

Like I have previously mentioned most things have a downside and an upside. Here are the ones for recusion:
Upside This is a more “elegant” way of doing a loop.
Downside It’s about 10 times slower than looping.

Now this is something that it discussed a lot about in programming, whether you should opt for a more straight-forward code or something more speedy. Every case and person is different and you will find yourself doing more elegant code sometimes and more efficient code other times.

Sometimes recursion is just needed, let’s look at this puzzle that is provided by Eloquent JavaScript:

by starting from the number 1 and repeatedly either adding 5 or multiplying by 3, an infinite amount of new numbers can be produced. How would you write a function that, given a number, tries to find a sequence of such additions and multiplications that produce that number? For example, the number 13 could be reached by first multiplying by 3 and then adding 5 twice, whereas the number 15 cannot be reached at all.

Solution:

function findSolution(target) {
  function find(start, history) {
    if (start == target)
      return history;
    else if (start > target)
      return null;
    else
      return find(start + 5, "(" + history + " + 5)") ||
             find(start * 3, "(" + history + " * 3)");
  }
  return find(1, "1");
}

console.log(findSolution(24));
//> (((1 * 3) + 5) * 3)

The function find is the one that does the recursing. It takes two arguments the current number “start” and a strong that records how we reached this number.
To do this the function does one of three possible actions.
1. If the current number is the target number, the current history is a way to reach that target so it is returned. if (start == target)
return history;

2. If the current number is bigger than the target it will return null, as there is no sense in further exploring the history as both adding and multiplying will make the number bigger. else if (start > target)
return null;

3. If we are still below the target then the functions tries the two possible paths that start from the current number, by calling itself twice, once for each of the allowed next steps. else
return find(start + 5, “(” + history + ” + 5)”) ||
find(start * 3, “(” + history + ” * 3)”);

Growing Functions

Functions are great so that you do not have to repeat yourself, if you find yourself repeating a function then maybe rename the initial function for it to make more sense for the rest of the code.

Naming functions correctly is essential for legibility of code. Being precise but not making the function name look like a German word is also helpful when reading over code.

Pure Functions and Side Effects
A pure function is a function that when it is given the same input it will always return the same output, produces no side effects and relies on no external state.

Side effects are those that are called for their return value.

Now go and do the exercises for Chapter 3 on Eloquent JavaScript!

Day 8. Objects and Arrays

Now that we know about Functions let’s take a look at the next big thing in JavaScript. Objects and Arrays. These are basically structures which allow you to store data in them. Now you may be asking yourself.. why two different ways? Let’s go and have a look.

Chapter 4 in the book Eloquent JavaScript looks into this in a great way and if you have some time I would recommend you take a look at it!

 

Arrays

Array objects are a way of putting chunks of data into a single variable. In other words putting several values into one variable.

Let’s take a look:

var listOfNumbers = [2,3,4,5,6];

So an array has a variable name (in this case listOfNumbers) and what makes it an array are the square brackets that surround the data and the commas are to separate each value.

Now let’s say we want to see what is in the array that we have saved and we do this:

console.log(listOfNumbers[2])
//>4

What is happening here is we are telling JavaScript to access our array and give us back what is in position 2. Now you may be wondering why it is not giving us back a 3.

Well this is because JavaScript starts counting at 0 so it would look a bit like this for our array:

0:2
1:3
2:4
3:5
4:6

Properties

Properties are the values associated with a JavaScript object. One property that will appear again and again is the .length property. This will tell you the length of a string, array,.. let’s try it!

listOfNumbers.length
//>5

JavaScript is telling us that there are 5 values in the array.

There are two common ways to access arrays and those are:
1. With a dot:

objectName.property          // person.age

2. With square brackets:

objectName["property"]       // person["age"]

What is the difference? When using a dot, the property of the value is fetched whereas with the square brackets, the value tries to evaluate the expression (what is in the square brackets) and uses the result as the property name.

Also when using a dot the property must be a valid variable name, not a string. If you wanted a string or a number you would need to use the square brackets.

Methods
Methods are properties that work as functions. Wait what did I just type. Let’s breathe the fresh air and take another look at that sentence. I am going to put this in my own english words: a method looks like a dot type property but the property is a function.

There are built-in methods such as

.push // this allows you to add values to the end of an array
.pop // removes values from the end of an array
.join // turns the array into a single string
.toUpperCase // turns to uppercase
.toLowerCase // turns to lowercase

Here is a link to all of them

Objects
Objects are a way of grouping big data. Say we have a set of values that we need to group into a single values and then those single values need to be grouped again. That is when a Object is needed.

Let’s take a look

var day8 = {
    sunny: false,
    events: ["walk", "look at bug", "touch tree", "run", "drink water"]
}
console.log(day7.sunny);
//>false

As you may have noticed an object uses curly brackets to surround it’s values, The values are written as name : value pairs (name and value separated by a colon). The values are separated by commas excluding the last one in the list. Again line spaces are only to make the code more legible.

Mutability
We have learnt that object values can be modified. Something I have mentioned is that boolean, strings and numbers cannot, they are immutable.

But objects are mutable as the content of a value can be modified. Let’s take a closer look at how objects work.

Take a look at this code:

var object1 = {value: 100};
var object2 = object1;
var object3 = {value: 100};

object1 and object3 have the same values but are different because object3 points to a different object. However, object1 and object2 grasp the same object.

Let’s write this differently to understand it better:

var bugs = {value: 100};
var insects = object1;
var birds = {value: 100};

they can be completely different things, that is why it is so important that they take on different objects

Day 9. A deeper look into objects

Objects as maps

The Map object is a simple key/value map. Any value (both objects and primitive values) may be used as either a key or a value. It is a way to go from values in one domain to corresponding values in another domain.

More Built-In Methods

.shift // works like .push but adds the value to the beginning of the array
.unshift // works like .push but removes the value from the beginning of the array
.indexOf() // returns the position of the first occurrence of a specified value in a string
.lastIndexOf //returns the position of the last occurrence of a specified value in a string.
.slice // returns the selected elements in an array, as a new array object.
.trim // removes the whitespace from the start and end of a string

The arguments object
We have previously talked about arguments. Whenever a function is called, the arguments are passed to the function.

function noArguments() {}
noArguments(1,2,3)

The arguments object has a length property that tell us exactly how many arguments were really passed.

It is a lot like an array except you do not have any array methods like slice or indexOf.

Some functions take any number of arguments, like console.log.

The Math Object

The JavaScript Math object allows you to perform mathematical tasks on numbers

Math.max // maximum
Math.min // minimum
Math.sqrt // square root
Math.round // rounded to its nearest integer
Math.ceil // rounded up
Math.floor // rounded down
Math.pow // power of
Math.cos // cosine 
Math.sin // sine
Math.tan //tangent
Math.random // returns a random number between 0 (inclusive),  and 1 (exclusive)

These are just some of the possibilities.

The Global Object
The global scope can also be approached as an object in JavaScript. Each global variable is present as a property of this object. In browsers, these are stored in the window.

Time to do the exercises in chapter 4.

Day 10. Higher-order functions

It is good to note that bigger programs are more costly not only because of the time it takes to construct them but also because of the complexity of the program. That is why it is extremely important to make the code as understandable as possible, so that complexity does not become even more complex and to avoid bugs (mistakes in code).

Abstraction
Abstraction is to hide certain details and only show the essential features of the object. Abstraction tries to reduce and factor out details so that the developer can focus on a few concepts at a time. This approach improves understandability as well as maintainability of the code.

Let’s imagine we go to a furniture shop and we buy some furniture that we have to mantle ourselves at home (I know that you are thinking of Ikea furniture but try not to for now). Think of one that adds complex language like:

Locate the package of glass shelves. The shelves may be located:
a) Inside your cabinet and secured with shipping clips. To remove the shipping clips, you
will need a Phillips screwdriver.
b) On top, underneath, or along side of your cabinet. You may need to lay the cabinet on
its backside to remove the shelves from underneath the cabinet. Use caution when
removing these shelves.
3. If available on your cabinet, turn the adjustable floor levelers, that are on the bottom of the
cabinet, all the way in (up).

Now take that trip to Ikea and checkout their manual.. No words needed. Well this quite a drastic example but abstraction consists of taking away all those fancy words that are not really necessary to leave a nice clean, legible code.

Abstracting Array Traversal

Remember the for loop we did earlier?

var array = [1,2,3];
for (var i = 0; i < array.length; i++){
    var current = array[i];
    console.log(current);
}

Let’s abstract this into a function to make it more clear but also so that we can use the function again if necessary.

function logEach(array) {
for (var i = 0; i < array.length; i++)
    console.log(array[i]);
}

Now let’s say that we want to do something other than logging the elements. “To do” something we need a function. Let’s pass our action function as a value:

function forEach(array, action) {
    for (var i = 0; i < array.length; i++)
        action(array[i]);
}

forEach(["Wampeter","Foma", "Granfalloon"], console.log)

Normally this is not what you would do but create a function value instead:

var number = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers, function(number) {
    sum+=number;
});
console.log(sum);

this may look a bit odd as you might have seen, the body is inside the function value as well as inside the parentheses of the call to forEach

Not the forEach is available as the standard method on arrays.

Higher-Order Functions

A higher-order function is a function that operates on other functions. That is, it takes functions as inputs and/or returns them as outputs.

function makeSumN(n) {//This is a higher-order function
    return function(p) {
        sum(n, p)
   }
}

You can also have functions that change other functions, this example for eloquent javascript is a brilliant one:

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);
//> calling with 0
//> called with 0 - got false

You can even write functions that provide new types of control flow by using if and for statements.

Passing Along Arguments

The example noisy we saw from the book:

function noisy(f) {
  return function(arg) {
    console.log("calling with", arg);
    var val = f(arg);
    console.log("called with", arg, "- got", val);
    return val;
  };
}
noisy(Boolean)(0);
//> calling with 0
//> called with 0 - got false

In this example f only takes on one argument, like we have discussed previously, if we add anymore arguments to this function it will only give back the first one. This example would also give us back one 1 in arguments.length even if we had passed more.

So what do we do to solve this? We can use the apply method.

The apply() method calls a function with a given this value and arguments provided as an array.

Example:

Function.prototype.construct = function (aArgs) {
  var oNew = Object.create(this.prototype);
  this.apply(oNew, aArgs);
  return oNew;
};

Tomorrow more!

High-order functions continued

JSON

JSON (pronounced as the name “Jason”): JavaScript Object Notation. JSON is a way to store information in an organized, easy-to-access manner. In other words it gives us more legible data that we can access in an easy and logical way. It looks a bit like JavaScript objects and arrays.

let’s take a closer look:

[
{"name": "Ana Cidre", "profession1": "hiker", "profession2": "developer" },
{"name": "Donald Duck", "profession1" "duck", "profession2": "actor"}
]

JavaScript gives up functions to convert data from and to JSON format, the methods used are:
JSON.stringify: turns it into a JSON and
JSON.parse: converts it into values for JavaScript to work with.

Filtering an array

Filters can be used to select certain value from arrays and be put to construct another array. In other words if we are looking at a bit data sample and we want to find people who were born between 1990 and 1995 then we could use a filter to get just those people.

[
  {"name": "Emma de Milliano", "sex": "f",
   "born": 1876, "died": 1956,
   "father": "Petrus de Milliano",
   "mother": "Sophia van Damme"},
  {"name": "Carolus Haverbeke", "sex": "m",
   "born": 1832, "died": 1905,
   "father": "Carel Haverbeke",
   "mother": "Maria van Brussel"},
  … and so on
]

// Using a for loop
function filter(array, test) {
  var passed = [];
  for (var i = 0; i < array.length; i++) { if (test(array[i])) passed.push(array[i]); } return passed; } console.log(filter(ancestry, function(person) { return person.born > 1900 && person.born < 1925; }));
 //> [{name: "Philibert Haverbeke", …}, …]

This is a function that was constructed just to show you how it works, but JavaScript had the filter method integrated and we should have done it like this:

console.log(ancestry.filter(function(person) {
  return person.father == "Carel Haverbeke";
}));
//> [{name: "Carolus Haverbeke", …}]

Transforming with map

Long story short, map is very similar to filter. While the map method is used to convert each item of an array, the filter method is used to select certain items of an array.

function map(array, transform) {
  var mapped = [];
  for (var i = 0; i < array.length; i++) mapped.push(transform(array[i])); return mapped; } var overNinety = ancestry.filter(function(person) { return person.died - person.born > 90;
});
console.log(map(overNinety, function(person) {
  return person.name;
}));
// > ["Clara Aernoudts", "Emile Haverbeke", "Maria Haverbeke"]

Summarizing with reduce
This is another method which you use to “reduce” a collection into a single variable

var hike = "";
var trails = ["hiking", "is", "great"];
for ( var i = 0; i < words.length; i++ ){
  hike += trails[i];
}

You start with a collection trails and a variable hike with an initial value ( the empty string in this case ). Then you go over the collection again and again, and then add the values to the variable.

Binding
Bind creates a new function that will call the original function but with some of the arguments that are fixed.
Less have a look at the example from the book

var theSet = ["Carel Haverbeke", "Maria van Brussel",
              "Donald Duck"];
function isInSet(set, person) {
  return set.indexOf(person.name) > -1;
}

console.log(ancestry.filter(function(person) {
  return isInSet(theSet, person);
}));
//> [{name: "Maria van Brussel", …},
//    {name: "Carel Haverbeke", …}]
console.log(ancestry.filter(isInSet.bind(null, theSet)));
//> … same result

It defines a function isInSet that tells us whether a person is in a given set of strings. To call filter in order to collect those person objects whose names are in a specific set, we can either write a function expression that makes a call to isInSet with our set as its first argument or partially apply the isInSet function.

Time to continue with exercises from chapter 5

Day 12. Methods

Methods

We have previously seen methods but have not really described them so I am going to take the chance to do so! JavaScript methods are actions that can be performed on objects and that hold function values.

let’s take a closer look:

var fox = {};
fox.talk = function(line) {
  console.log("The fox would like to say '" + line + "'");
};

fox.talk("Good hike!");
//> The fox would like to say 'Good hike!'

We created the method talk on the variable fox. And this method is a function.
See how it works?

function talk(line) {
  console.log(this.type + " fox would like to say '" +
              line + "'");
}
var mrFox = {type: "Mr", talk: talk};
var redFox = {type: "red", talk: talk};

mrFox.talk("What a beautiful day, " +
                  "I hope your hike is going splendidly");
//> Mr fox would like to say 'What a beautiful day, I hope your hike is going splendidly'
redFox.talk("Can I borrow your boots?");
//> Red fox would like to say 'Can I borrow your boots?'

see how in this example we use the this keyword to specify which type of fox we are talking about? This can come in handy!

The apply method calls a function with a given this value and arguments provided as an array (or an array-like object). Then there is a method call. It calls a function and it is a method but takes its arguments normally, rather than as an array.

talk.apply(brownFox, ["Wonderful!"]);
//> Brown fox would like to say 'Wonderful!'
talk.call({type: "great"}, "Oh my.");
//> Great fox says 'Oh my.'

Day 13. Prototypes

Prototypes

Almost every JavaScript object has a prototype and that prototype is also an object. Also all JavaScript objects inherit their properties and methods from their prototype.

let’s take a look:

var empty = {};
console.log(empty.toString);
//> function toString(){…}
console.log(empty.toString());
//> [object Object]

So when an object gets a request for a property that it does not have a prototype will be searched for, then that prototype’s prototype…To get an objects prototype you use:

Object.getPrototypeOf({});

An Example:

console.log(Object.getPrototypeOf({})== Object.prototype);
//>true

Some objects do not get their prototype through Ojbect.prototype for example:

Object.getPrototypeOf(isNaN) == Function.prototype
Object.getPrototypeOf([]) == Array.prototype

Yes, you can create prototypes with Object.create().

Take a look:

var protoFox = {
  speak: function(line) {
    console.log("The " + this.type + " fox says '" +
                line + "'");
  }
};
var hungryFox = Object.create(protoFox);
hungryFox.type = "hungry";
hungryFox.speak("MMMMM!");

The protoFox acts as a box for the properties

Constructors

Constructors are useful when you want to create multiple similar objects with the same properties and methods. To do this you need to call a function with the new keyword in front of it.

Here is an example:

function Fox(type) {
    this.type = type;
}

var hungryFox = new Fox("hungry");
var wonderfulFox = new Fox("wonderful");
console.log(wonderfulFox.type);
//>wonderful

As we have seen all objects including functions have their own prototype. So to make this fox speak with a constructor we simply need to do the following:

Fox.prototype.speak = function(line) {
    console.log("The " + this.type + " fox says '" +
                line + "'");
};
wonderfulFox.speak("Beautiful day");

Difference between an objects prototype and a constructor: All objects have a prototype, the prototype of a constructor is Function.prototype as constructors are functions and it is no longer it’s “own” prototype.

Overriding Derived Properties

I am going to try to explain this without confusing anyone. Like I have said, when you have an object it has a prototype. If you add a property to that object it will be added to the object itself. If there is a property by the same name in the prototype, that property will no longer affect the object. The prototype will not change but the property will.

It is always easier with an example:

Fox.prototype.tail = "long";
console.log(wonderfulFox.tail);
//> long
wonderfulFox.tail = "hairy, brown with a white tip";
console.log(wonderfulFox.tail);
//> hairy, brown with a white tip
console.log(hungryFox.tail);
//> long
console.log(Fox.prototype.tail);
//> long

This can come in handy!

Prototype Interference

Like I have mentioned many times there is always an upside and downside to things. What is the upside and downside to using a prototype (considering it can be used to add any new property and/or methods to all objects at any time)?

UPSIDE Well we might need our fox to guide us better on this hike and add Fox.prototype.guide

DOWNSIDE they can and will interefere with in/for loops. This can happen when using an object as a way to associate values with names by creating properties for the names and giving them the corresponding value as their value. If the values are all numerical and the prototypes are not this will cause an error. There is a work around and it would be to use the Object.hasOwnProperty.

for (var name in map) {
    if (map.hasOwnProperty(name)) {
        //... this is an own property   
    }
}

Prototype-less Objects

Sometimes it is necessary to make sure our objects prototypes do not get in the way and to do so we would need to assign null to them.

Here is how to do it (using the example from the book)

var map = Object.create(null);
map["pizza"] = 0.069;
console.log("toString" in map);
//> false
console.log("pizza" in map);
//> true

Polymorphism

Is when a piece of code is written to work with objects that have a certain interface any kind of object that happens to support this interface can be plugged into the code, and it will work!

Day 14. Object-Oriented Programming

In the next part of the book Marijn walks us through an example like I would like to do with you fellow hikers, I think that it is a brilliant way of learning the trail better and together, so let’s do this. Hopefully I can clarify some things!

Laying out a table

In this example we are going to clarify what we saw yesterday: polymorphism and object-oriented programming. The example consists of: writing a program that, given an array of arrays of table cells, builds up a string that contains a nicely laid out table—meaning that the columns are straight and the rows are aligned.

Something like this:

name         height country
------------ ------ -------------
Kilimanjaro    5895 Tanzania
Everest        8848 Nepal
Mount Fuji     3776 Japan
Mont Blanc     4808 Italy/France
Vaalserberg     323 Netherlands
Denali         6168 United States
Popocatepetl   5465 Mexico

I love this example because it is very relevant to our hike 😉
To create a table like this we need to ask each cell how wide and tall it needs to be with a builder function, and then use this data to make the cells that width and height. Sounds simple right? Well we need an interface to be able to construct this so let’s take a look at the following:
minheight returns a number indicating the minimum height this cell requires (in lines).
minwidth returns a number indicating the minimum width this cell requires (in lines).
draw(width, height)returns an array of length height, which contains a series of strings that are each width characters wide. This represents the content of the cell.

Let’s take a look at what we’re given here:

function rowHeights(rows) {
  return rows.map(function(row) {
    return row.reduce(function(max, cell) {
      return Math.max(max, cell.minHeight());
    }, 0);
  });
}

function colWidths(rows) {
  return rows[0].map(function(_, i) {
    return rows.reduce(function(max, row) {
      return Math.max(max, row[i].minWidth());
    }, 0);
  });
}

First time I looked at this I was pretty startled but let’s go through it step by step to understand the process. Just like on a hike, step by step.

To understand it, work from the inside out:

function(max, cell) {
    return Math.max(max, cell.minHeight());
}

Given a cell and a previous maximum height, this computes the new height as the maximum of this cell’s minHeight() and the previous maximum.

 return row.reduce(function(max, cell) {

This reduces a row (an array of cells), using the above function, to get the maximum height of all the cells in the row.
Then:

return rows.map(function(row) {

runs the reduction function over every row, returning an array of all the maximum heights

colWidths does the same thing.

NOTE: Using a variable name starting with an underscore (_) or consisting entirely of a single underscore is a way to indicate (to human readers) that this argument is not going to be used.

Now let’s do the same thing for the code to build the table:

function drawTable(rows) {
  var heights = rowHeights(rows);
  var widths = colWidths(rows);

  function drawLine(blocks, lineNo) {
    return blocks.map(function(block) {
      return block[lineNo];
    }).join(" ");
  }

  function drawRow(row, rowNum) {
    var blocks = row.map(function(cell, colNum) {
      return cell.draw(widths[colNum], heights[rowNum]);
    });
    return blocks[0].map(function(_, lineNo) {
      return drawLine(blocks, lineNo);
    }).join("\n");
  }

  return rows.map(drawRow).join("\n");
}

The variables heights and widths are from the functions we created in the example above this one. So it maps through rows and calls drawRow function for each row. Let’s take a look at this function and see how it works. blocks is an array of arrays. Each inner array will be a cell in the final table.

blocks is made with the help of mapdraw method on each cell to ask them to draw themselves. We pass height of current row and width of the corresponding column for each cell to the draw method. And draw returns an array for each cell.

  function drawLine(blocks, lineNo) {
    return blocks.map(function(block) {
      return block[lineNo];
    }).join(" ");
  }

drawLinedrawTable function. All it does is it makes a string out of an array of arrays. It does this in two steps. First it flattens the blocks. And then it uses join(” “) to make a string by joining all the elements of this array with one space in between. Now that we know what drawLine does we can continue with drawRow function.

function drawRow(row, rowNum) {
    var blocks = row.map(function(cell, colNum) {
      return cell.draw(widths[colNum], heights[rowNum]);
    });
    return blocks[0].map(function(_, lineNo) {
      return drawLine(blocks, lineNo);
    }).join("\n");
  }

It maps through rows and calls the drawRow function for each row. Let’s take a look at this function and see how it works. It takes a row (for each invocation) and its corresponding rowNum. For each row, drawRow returns a string.

function drawTable(rows) {
  var heights = rowHeights(rows);
  var widths = colWidths(rows);

  function drawLine(blocks, lineNo) {
    return blocks.map(function(block) {
      return block[lineNo];
    }).join(" ");
  }

  function drawRow(row, rowNum) {
    var blocks = row.map(function(cell, colNum) {
      return cell.draw(widths[colNum], heights[rowNum]);
    });
    return blocks[0].map(function(_, lineNo) {
      return drawLine(blocks, lineNo);
    }).join("\n");
  }

So drawLine returns a string to the map and map returns an array. This array has one or two elements depending on the row that we are working on.

return rows.map(drawRow).join("\n");
}

This process will be repeated for each row, remember drawRow is in a map method. And join(“\n”) to convert it into a string.

 

Ok and now the example is suggesting we do the following, hang in there fellow hikers!
Now let’s write a constructor for cells that contain text, which implements the interface for table cells. The constructor splits a string into an array of lines using the string method split, which cuts up a string at every occurrence of its argument and returns an array of the pieces. The minWidth method finds the maximum line width in this array.

function repeat(string, times) {
  var result = "";
  for (var i = 0; i < times; i++)
    result += string;
  return result;
}

function TextCell(text) {
  this.text = text.split("\n");
}
TextCell.prototype.minWidth = function() {
  return this.text.reduce(function(width, line) {
    return Math.max(width, line.length);
  }, 0);
};
TextCell.prototype.minHeight = function() {
  return this.text.length;
};
TextCell.prototype.draw = function(width, height) {
  var result = [];
  for (var i = 0; i < height; i++) {
    var line = this.text[i] || "";
    result.push(line + repeat(" ", width - line.length));
  }
  return result;
};

It breaks line in array of lines by means of the split method which cuts line every time when in it his argument meets, and returns array of these slices. The minWidth method finds the maximum width of the line in array.

Now the 5×5 checkerboard to get a better look at this.

var rows = [];
for (var i = 0; i < 5; i++) {
   var row = [];
   for (var j = 0; j < 5; j++) {
     if ((j + i) % 2 == 0)
       row.push(new TextCell("##"));
     else
       row.push(new TextCell("  "));
   }
   rows.push(row);
}
console.log(drawTable(rows));
// → ##    ##    ##
//      ##    ##
//   ##    ##    ##
//      ##    ##
//   ##    ##    ##

Ok this is simple let’s put it to the data Marijn gives us here. Simply download it and link it to your file.

To make the top row more prominent we can underline it by doing this:

function UnderlinedCell(inner) {
  this.inner = inner;
}
UnderlinedCell.prototype.minWidth = function() {
  return this.inner.minWidth();
};
UnderlinedCell.prototype.minHeight = function() {
  return this.inner.minHeight() + 1;
};
UnderlinedCell.prototype.draw = function(width, height) {
  return this.inner.draw(width, height - 1)
    .concat([repeat("-", width)]);
};

Let’s put everything we have learnt today to practice by writing a function that builds up a grid of cells from our data set.

function dataTable(data) {
  var keys = Object.keys(data[0]);
  var headers = keys.map(function(name) {
    return new UnderlinedCell(new TextCell(name));
  });
  var body = data.map(function(row) {
    return keys.map(function(name) {
      return new TextCell(String(row[name]));
    });
  });
  return [headers].concat(body);
}

console.log(drawTable(dataTable(MOUNTAINS)));
// → name         height country
//   ------------ ------ -------------
//   Kilimanjaro  5895   Tanzania
//   … etcetera

Good job, let’s leave it here for today and finish this chapter tomorrow!

Day 15. Getters and Setters

Yesterday we specified an interface with minWidth and minHeight. It is good to know that these properties do not need to be methods. If we have made them numerical we would have had to use them in the constructor which would then lead to problems.

Therefore, many people decided to use interfaces only with method properties. This approach has the downside that you will end up writing a lot of methods.

Another great thing about JavaScript is that it allows us to find a workaround which would be specifying a property that looks like an every-day property but actually has some method inside.

Take a look at this:

var pile = {
  elements: ["eggshell", "orange peel", "worm"],
  get height() {
    return this.elements.length;
  },
  set height(value) {
    console.log("Ignoring attempt to set height to", value);
  }
};

console.log(pile.height);
//> 3
pile.height = 100;
//> Ignoring attempt to set height to 100

The get or set notation for properties allows you to specify a function to be run when the property is read or written. You can also add such a property to an existing object, for example a prototype, using the Object.defineProperty function (which we previously used to create nonenumerable properties).

Object.defineProperty(TextCell.prototype, "heightProp", {
  get: function() { return this.text.length; }
});

var cell = new TextCell("no\nway");
console.log(cell.heightProp);
//> 2
cell.heightProp = 100;
console.log(cell.heightProp);
//> 2

Right-aligning columns
Back to our table exercise from yesterday.

Remembering that prototypes themselves have prototypes, this allows us to do something clever.

function RTextCell(text) {
  TextCell.call(this, text);
}
RTextCell.prototype = Object.create(TextCell.prototype);
RTextCell.prototype.draw = function(width, height) {
  var result = [];
  for (var i = 0; i < height; i++) {
    var line = this.text[i] || "";
    result.push(repeat(" ", width - line.length) + line);
  }
  return result;
};

What we are doing here is reusing the constructor minHeight and minHeight from the regular TextCell and nowRTExtCell is basically TextCell but with a draw method which contains a function. This is called Inheritance.

So to get our table to align right we need to adjust the code from yesterday to this:

function dataTable(data) {
  var keys = Object.keys(data[0]);
  var headers = keys.map(function(name) {
    return new UnderlinedCell(new TextCell(name));
  });
  var body = data.map(function(row) {
    return keys.map(function(name) {
      var value = row[name];
      // This was changed:
      if (typeof value == "number")
        return new RTextCell(String(value));
      else
        return new TextCell(String(value));
    });
  });
  return [headers].concat(body);
}

console.log(drawTable(dataTable(MOUNTAINS)));
//> … beautifully aligned table

The InstanceOf Operator

The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor.

console.log(new RTextCell("A") instanceof RTextCell);
//> true
console.log(new RTextCell("A") instanceof TextCell);
//> true
console.log(new TextCell("A") instanceof RTextCell);
//> false
console.log([1] instanceof Array);
//> true

Note that the instanceOf can see right through inherited types.

Time to do the exercises. I have just realised that it might be a good idea if I upload my own results as they are not exactly the same as the solutions provided by the book. Once we have finished this hike I will definitely find a way to upload them!

Day 16.Project: Electronic Life

This chapter looks great! We going to build a virtual ecosystem, a little world populated with critters that move around and struggle for survival! Let’s dig in!

Definition

To be able to construct this we need to make a simplified version of a “world”. To do so we are going to build a two-dimensional grid where each entity takes up one square on the grid. On every turn, the critters get the chance to do something.

Squares for space
Turns for time

OUR PLAN

var plan = ["############################",
            "#      #    #      o      ##",
            "#                          #",
            "#          #####           #",
            "##         #   #    ##     #",
            "###           ##     #     #",
            "#           ###      #     #",
            "#   ####                   #",
            "#   ##       o             #",
            "# o  #         o       ### #",
            "#    #                     #",
            "############################"];

# are the walls and rocks
o represent the critters
The spaces are empty space.

A plan array can be used to create this world. It allows us to keep track of the size and content of the world. By using the toString method we can see what’s going on inside! The world object also has a turn method, which allows all the critters in it to take one turn and updates the world to reflect their actions.

Representing Space
Our world has a fixed height and width. Squares are identified through their x and y coordinates which will be represented by the function Vector.

Take a look!

function Vector(x, y) {
  this.x = x;
  this.y = y;
}
Vector.prototype.plus = function(other) {
  return new Vector(this.x + other.x, this.y + other.y);
};

Now we need to model the grid itself by using an object type. A grid is part of a world, but we are making it a separate object (which will be a property of a world object) to keep the world object itself simple.

To store a grid of values there are various options, but we are going to use a single array, with size width x height and say that the element (x,y) is found at position x+(y x width) in the array.

var grid = ["top left",    "top middle",    "top right",
            "bottom left", "bottom middle", "bottom right"];
console.log(grid[2 + (1 * 3)]);
//> bottom right

and here is how we define the grid object

function Grid(width, height) {
  this.space = new Array(width * height);
  this.width = width;
  this.height = height;
}
Grid.prototype.isInside = function(vector) {
  return vector.x >= 0 && vector.x < this.width && vector.y >= 0 && vector.y < this.height;
};
Grid.prototype.get = function(vector) {
  return this.space[vector.x + this.width * vector.y];
};
Grid.prototype.set = function(vector, value) {
  this.space[vector.x + this.width * vector.y] = value;
};

get and set, simply find the position of an item in the array, and read, or write the value in said position. This is the code that finds the position in the array: vector.x+this.width*vector.y. Let’s break it down:

vector.x = table column

vector.y = table row

Imagine a table 3×2 = [ ‘row0 col0’, ‘row0 col1’, ‘row0 col2’, ‘row1 col0’, ‘row1 col1’, ‘row1 col2’ ]

now we want item at col 2, row 1, so new Vector(2, 1). That’s item at position 5 in our array. So, starting at row 1
( this.width*vector.y ) = (3*1), get item at column 2 ( + vector.x) = ( + 2 )

this.width is the size of each row, so when you multiply by vector.y, it means vector.y is equivalent to a certain number of rows. Then from there, you just sum the column position (vector.x).

This is why in the trivial test

var grid = new Grid(5, 5);
console.log(grid.get(new Vector(1, 1)));
//> undefined
grid.set(new Vector(1, 1), "X");
console.log(grid.get(new Vector(1, 1)));
//> X

we get undefined before using set.

A Critter’s Programming Interface
Before we start with the world
constructor we need to get to know the Critters a bit more.

We already know that the world will ask the Critters what actions they will take. For this to work:
Each Critter object has an act method, when called returns an action. An action is an object with a type property, for example “move“. This action might also contain extra valuable information like in which direction the critter will move in.

Note. Critters have a pretty bad vision and can only see the squares directly around them. But even this can be useful. When the act method is called it is given a view object that allows the Critter to check out it’s surroundings. We name the eight surrounding squares by their compass directions:
n -> north
ne -> north-east
s -> south

Here is the object we will use to map these:

var directions = {
  "n":  new Vector( 0, -1),
  "ne": new Vector( 1, -1),
  "e":  new Vector( 1,  0),
  "se": new Vector( 1,  1),
  "s":  new Vector( 0,  1),
  "sw": new Vector(-1,  1),
  "w":  new Vector(-1,  0),
  "nw": new Vector(-1, -1)
};

The view object has a method: look which will return either a wall # or empty space ” “. The object also contains the methods find and findAll. Both take a map character as an argument.
find returns a direction in which the character can be found next to the critter or returns null if that direction does not exist
findAll returns an array containing all directions with that character..

function randomElement(array) {
  return array[Math.floor(Math.random() * array.length)];
}

var directionNames = "n ne e se s sw w nw".split(" ");

function BouncingCritter() {
  this.direction = randomElement(directionNames);
};

BouncingCritter.prototype.act = function(view) {
  if (view.look(this.direction) != " ")
    this.direction = view.find(" ") || "s";
  return {type: "move", direction: this.direction};
};

The “|| “s”” in the act method is there to prevent this.direction from getting the value null if the critter is somehow trapped

The world object
Now we are ready to check out the world object. The construtor takes a plan and a legend.
legend is an object that tells us what each character in the map means. The space character will be null.

function elementFromChar(legend, ch) {
  if (ch == " ")
    return null;
  var element = new legend[ch]();
  element.originChar = ch;
  return element;
}

function World(map, legend) {
  var grid = new Grid(map[0].length, map.length);
  this.grid = grid;
  this.legend = legend;

  map.forEach(function(line, y) {
    for (var x = 0; x < line.length; x++)
      grid.set(new Vector(x, y),
               elementFromChar(legend, line[x]));
  });
}

So here we are creating an instance of the right type by looking up the character´s constructor and applying new to it in elementFromChar. Then the property originChar is added to make it easy to find out what character the element was created from.

We will use the world’s toString methond on the originChar property to build up a maplike string from the world’s current state by performing a two-dimensional loop over the square on the grid.

let’s take a closer look

function charFromElement(element) {
  if (element == null)
    return " ";
  else
    return element.originChar;
}

World.prototype.toString = function() {
  var output = "";
  for (var y = 0; y < this.grid.height; y++) {
    for (var x = 0; x < this.grid.width; x++) {
      var element = this.grid.get(new Vector(x, y));
      output += charFromElement(element);
    }
    output += "\n";
  }
  return output;
};

A wall is a simple object, it takes no act method.

function Wall() {}

If we test the world object and call the toString method on it, we get back a string that is very similar to the plan we put in:

var world = new World(plan, {"#": Wall,
                             "o": BouncingCritter});
console.log(world.toString());
// > ############################
//   #      #    #      o      ##
//   #                          #
//   #          #####           #
//   ##         #   #    ##     #
//   ###           ##     #     #
//   #           ###      #     #
//   #   ####                   #
//   #   ##       o             #
//   # o  #         o       ### #
//   #    #                     #
//   ############################

this and its scope

As we have seen earlier the world constructor contains a call to forEach. We should note that that inside the function passed to forEach, we are no longer directly in the function scope of the constructor. Each function call gets its own this binding, so the this in the inner function does not refer to the newly constructed object that the outer this refers to. In fact, when a function isn’t called as a method, this will refer to the global object.

This means that we can’t write this.grid to access the grid from inside the loop. Instead, the outer function creates a normal local variable, grid, through which the inner function gets access to the grid.

So the solution would be to use the bind method like so:

var test = {
  prop: 10,
  addPropTo: function(array) {
    return array.map(function(elt) {
      return this.prop + elt;
    }.bind(this));
  }
};
console.log(test.addPropTo([5]));
//> [15]

Most standard higher-order functions take an optional second argument that can also be used to provide a this. Making our previous code a bit more simple

var test = {
  prop: 10,
  addPropTo: function(array) {
    return array.map(function(elt) {
      return this.prop + elt;
    }, this); // ← no bind
  }
};
console.log(test.addPropTo([5]));
//> [15]

Tomorrow we finish what we started here 😉

Day 17. Project 1 continued

Let’s get those critters moving, I mean let’s apply the turn method to the critters! To do so it will go over the forEach method we just defined look for objects with an act method. When an object is found turn calls that method to get an action object and then carries it out. For now, only move actions are understood.

Downside if we allow the critters to move as we come across them, they may move to a square that we have not looked at yet, allowing them to move again when we reach that square. To stop this from happening we need this an array of critters that have already had their turn and ignore them when we see them again:

World.prototype.turn = function() {
  var acted = [];
  this.grid.forEach(function(critter, vector) {
    if (critter.act && acted.indexOf(critter) == -1) {
      acted.push(critter);
      this.letAct(critter, vector);
    }
  }, this);
};

We use the second parameter to the grid’s forEach method to be able to access the correct this inside the inner function. The letAct method contains the actual logic that allows the critters to move.

World.prototype.letAct = function(critter, vector) {
  var action = critter.act(new View(this, vector));
  if (action && action.type == "move") {
    var dest = this.checkDestination(action, vector);
    if (dest && this.grid.get(dest) == null) {
      this.grid.set(vector, null);
      this.grid.set(dest, critter);
    }
  }
};

World.prototype.checkDestination = function(action, vector) {
  if (directions.hasOwnProperty(action.direction)) {
    var dest = vector.plus(directions[action.direction]);
    if (this.grid.isInside(dest))
      return dest;
  }
};

First, we ask the critter to act, passing it a view object that knows about the world and the critter’s current position in that world (we’ll define View in a moment). The act method returns an action of some kind.

If the action’s type is not “move”, it is ignored. If it is “move”, if it has a direction property that refers to a valid direction, and if the square in that direction is empty (null), we set the square where the critter used to be to hold null and store the critter in the destination square.

Note that letAct takes care to ignore nonsense input—it doesn’t assume that the action’s direction property is valid or that the type property makes sense. This kind of defensive programming makes sense in some situations. The main reason for doing it is to validate inputs coming from sources you do not control (such as user or file input), but it can also be useful to isolate subsystems from each other. In this case, the intention is that the critters themselves can be programmed sloppily— they don’t have to verify if their intended actions make sense. They can just request an action, and the world will figure out whether to allow it.

These two methods are not part of the external interface of a World object. They are an internal detail. Some languages provide ways to explicitly declare certain methods and properties private and signal an error when you try to use them from outside the object. JavaScript does not, so you will have to rely on some other form of communication to describe what is part of an object’s interface. Sometimes it can help to use a naming scheme to distinguish between external and internal properties, for example by prefixing all internal ones with an underscore character (_). This will make accidental uses of properties that are not part of an object’s interface easier to spot. The one missing part, the View type, looks like this:

function View(world, vector) {
  this.world = world;
  this.vector = vector;
}
View.prototype.look = function(dir) {
  var target = this.vector.plus(directions[dir]);
  if (this.world.grid.isInside(target))
    return charFromElement(this.world.grid.get(target));
  else
    return "#";
};
View.prototype.findAll = function(ch) {
  var found = [];
  for (var dir in directions)
    if (this.look(dir) == ch)
      found.push(dir);
  return found;
};
View.prototype.find = function(ch) {
  var found = this.findAll(ch);
  if (found.length == 0) return null;
  return randomElement(found);
};

The look method figures out the coordinates that we are trying to look at and, if they are inside the grid, finds the character corresponding to the element that sits there. For coordinates outside the grid, look simply pretends that there is a wall there so that if you define a world that isn’t walled in, the critters still won’t be tempted to try to walk off the edges.

It moves

The world object should actually be able to move now!

for (var i = 0; i < 5; i++) { world.turn(); console.log(world.toString()); } //> … five turns of moving critters

Simply printing out many copies of the map is a rather unpleasant way to observe a world, though. That’s why the sandbox from the book provides an animateWorld function that will run a world as an onscreen animation, moving three turns per second, until you hit the stop button.

We will figure out how this works later on in the book.

More Life-Forms

So one of the most exciting moments is when the critters bounce of each other, right?!

What about if a critter moves along walls?! Let’s do this!

function dirPlus(dir, n) {
  var index = directionNames.indexOf(dir);
  return directionNames[(index + n + 8) % 8];
}

function WallFollower() {
  this.dir = "s";
}

WallFollower.prototype.act = function(view) {
  var start = this.dir;
  if (view.look(dirPlus(this.dir, -3)) != " ")
    start = this.dir = dirPlus(this.dir, -2);
  while (view.look(this.dir) != " ") {
    this.dir = dirPlus(this.dir, 1);
    if (this.dir == start) break;
  }
  return {type: "move", direction: this.dir};
};

To do this we need to be able to compute with compass directions. To do so we need to define our own operation dirPlus to calculate relative directions (not to forget that our directions are modeled by strings). so dirPlus(“n”,1) means one 45º turn clockwise from north giving “ne”.

The act method only has to “scan” the critter’s surroundings, starting from its left side and going clockwise until it finds an empty square. It then moves in the direction of that empty square.

The if statement is to make sure that our critter does not run in circles if it is in an empty space.

And to make sure that the code does not run forever if the critter is walled out or surrounded by other critters, there is the test this.dir that starts after every pass through the loop.

A more lifelike simulation

Just to make things more interesting (complicated), let’s add some concepts like food and reproduction. Each living thing in the world gets an energy property which increases by eating and decreases by moving or doing some action. When the critter has enough energy it can reproduce and a baby critter will be born (they are critters, they can do almost anything)!
So as these critters are very hungry creatures we are going to have to add some plants (also we do not want our world to end that quickly), as you can guess plants do not move. They just grow and reproduce.
Ok so we need to use inheritance so that we can keep our old world with wall clinging critters and to do so we create a new constructor LifelikeWorld, whose prototype is based on the World prototype but which override the letAct method. The new one delegates the work of actually performing and action to various functions stored in the actionTypes object.

function LifelikeWorld(map, legend) {
  World.call(this, map, legend);
}
LifelikeWorld.prototype = Object.create(World.prototype);

var actionTypes = Object.create(null);

LifelikeWorld.prototype.letAct = function(critter, vector) {
  var action = critter.act(new View(this, vector));
  var handled = action &&
    action.type in actionTypes &&
    actionTypes[action.type].call(this, critter,
                                  vector, action);
  if (!handled) {
    critter.energy -= 0.2;
    if (critter.energy <= 0)
      this.grid.set(vector, null);
  }
};

If the action didn’t work for whatever reason, the default action is for the creature to simply wait. It loses one-fifth point of energy, and if its energy level drops to zero or below, the creature dies and is removed from the grid.

Action Handlers
The most simplest actiona a critter can do is “grow”, what plants do. When an action object like {type: “grow”} is returned, the following handler method will be called:

actionTypes.grow = function(critter) {
  critter.energy += 0.5;
  return true;
};

Growing always succeeds and adds half a point to the plant’s energy level.

Moving is more involved.

actionTypes.move = function(critter, vector, action) {
  var dest = this.checkDestination(action, vector);
  if (dest == null ||
      critter.energy <= 1 ||
      this.grid.get(dest) != null)
    return false;
  critter.energy -= 1;
  this.grid.set(vector, null);
  this.grid.set(dest, critter);
  return true;
};

Firstly, this the checkDestination method checks whether the action provides a valid destination. If not, move returns false to indicate no action was taken. Otherwise it will carry on like usual and move the critter and take away the required energy from the critter.

Now let’s get those critters eating!

actionTypes.eat = function(critter, vector, action) {
  var dest = this.checkDestination(action, vector);
  var atDest = dest != null && this.grid.get(dest);
  if (!atDest || atDest.energy == null)
    return false;
  critter.energy += atDest.energy;
  this.grid.set(dest, null);
  return true;
};

Critters are little monsters and will eat each other, this involves adding another destination square. This time, the destination must not be empty and must contain something with energy, like a critter (but not a wall—walls are not edible). If so, the energy from the eaten is transferred to the eater, and the victim is removed from the grid.

Our critters can move, eat and now let’s make them reproduce so that our project does not end too quickly

actionTypes.reproduce = function(critter, vector, action) {
  var baby = elementFromChar(this.legend,
                             critter.originChar);
  var dest = this.checkDestination(action, vector);
  if (dest == null ||
      critter.energy <= 2 * baby.energy ||
      this.grid.get(dest) != null)
    return false;
  critter.energy -= 2 * baby.energy;
  this.grid.set(dest, baby);
  return true;
};

For a newborn critter it will cost twice the amount of energy than an older critter. To do so we create a (hypothetical) baby using elementFromChar on the critter’s own origin character. Once we have a baby, we can find its energy level and test whether the parent has enough energy to successfully bring it into the world. We also require a valid (and empty) destination.

If it all works out the baby will be put onto the grid.

Populating the new world

Creating Plants plants = *

function Plant() {
  this.energy = 3 + Math.random() * 4;
}
Plant.prototype.act = function(view) {
  if (this.energy > 15) {
    var space = view.find(" ");
    if (space)
      return {type: "reproduce", direction: space};
  }
  if (this.energy < 20)
    return {type: "grow"};
};

Plants start with an energy level between 3 and 7, randomly assigned. When a plant reaches 15 energy points and there is empty space nearby, it reproduces into that empty space. If a plant can’t reproduce, it simply grows until it reaches energy level 20.

Plant eater Plant eater = 0

function PlantEater() {
  this.energy = 20;
}
PlantEater.prototype.act = function(view) {
  var space = view.find(" ");
  if (this.energy > 60 && space)
    return {type: "reproduce", direction: space};
  var plant = view.find("*");
  if (plant)
    return {type: "eat", direction: plant};
  if (space)
    return {type: "move", direction: space};
};

Bringing it to life

Here it is:

var valley = new LifelikeWorld(
  ["############################",
   "#####                 ######",
   "##   ***                **##",
   "#   *##**         **  O  *##",
   "#    ***     O    ##**    *#",
   "#       O         ##***    #",
   "#                 ##**     #",
   "#   O       #*             #",
   "#*          #**       O    #",
   "#***        ##**    O    **#",
   "##****     ###***       *###",
   "############################"],
  {"#": Wall,
   "O": PlantEater,
   "*": Plant}
);

Now run this

animateWorld(valley);

Wow what a trek! Do the chapters and tomorrow more fun!!

Day 18. Bugs and Error Handling

Bugs you say? Yes these are not just what you would find in our every day hike, these are also known as mistakes, problems or errors a programmer has made.

Programmer Mistakes
When a programmer makes a mistake it is a simple task to tackle (simple is probably not the best word here). But we go into the code, find the mistake and fix it! (Oh if it were that simple…).
These can differ, you might just find a typo or and actual function doing something else than the programmer wanted to do.
The bad thing about JavaScript is that it does not really help you to find the bug, some languages let you know that you are doing something wrong while typing the code, JavaScript is very flexible, we have seen the upside to that and now we are seeing it’s downside.
JavaScript will, however, let you know about some things, like if a functions is not syntactically valid, or if you call something that is not a function, it will let you know. Many times though, your nonsense code will just return a NaN… or undefined, and the program will continue and only after running several functions will JavaScript return you something that you did not want. You have been warned!

Strict Mode
Remember that really strict teacher you had in high-school that made you write by hand, make margins or EXACTLY 0,5mm and paragraphs no long than 5 sentences?? No? Luck you!
But we can tell JavaScript to be that kind of “teacher” by enabling strict mode to tell us off.

Let’s take a look

function canYouSpotTheProblem() {
  "use strict";
  for (counter = 0; counter < 10; counter++)
    console.log("Happy happy");
}

canYouSpotTheProblem();

Go on, open a new tab, open console (on mac that is cmd, alt + j) and write that piece of code in.

If you do had not activated strict mode then JavaScript would have quietly created a global variable var counter. Note that this use strict only works when there is not a global variable either.

Let’s see what else the strict mode can do!

function Person(name) { this.name = name; }
var ferdinand = Person("Ferdinand"); // oops
console.log(name);
//> Ferdinand
"use strict";
function Person(name) { this.name = name; }
//> Oops, forgot 'new'
var ferdinand = Person("Ferdinand");
//>TypeError: Cannot set property 'name' of undefined

So if you accidentally call a method or constructor incorrectly in strict mode, JavaScript will produce an error as soon as it tries to read something from this, rather than happily working with the global object, creating and reading global variables.

There are a few more things you can do in strict mode, check them out here

Testing

So as JavaScript does not do much for us, to find the bug we could do it manually going over everything again and again which could possibly drive us insane, depending on the amount of code we are talking about.
But we can automate this process by buildlet’s create a vector function to try this out

function Vector(x, y) {
  this.x = x;
  this.y = y;
}
Vector.prototype.plus = function(other) {
  return new Vector(this.x + other.x, this.y + other.y);
};
function testVector() {
var p1 = new Vector(10, 20);
var p2 = new Vector(-10, 5);
var p3 = p1.plus(p2);</a>

if (p1.x !== 10) return "fail: x property";
if (p1.y !== 20) return "fail: y property";
if (p2.x !== -10) return "fail: negative x property";
if (p3.x !== 0) return "fail: x from plus";
if (p3.y !== 25) return "fail: y from plus";
return "everything ok";
}
console.log(testVector());
//> everything ok

Debugging

As we know, once we have found the problem we need to fix it, this is called debugging.
It might be simple to find the error and fix it or it might contain syntax errors, or logical errors, that are difficult to diagnose.
Often, when JavaScript code contains errors, nothing will happen. There are no error messages, and you will get no indications where to search for errors.
In the next example the program tries to convert a whole number to a string in any base by picking out the last digit and then dividing the number to get rid of this digit.

But the output suggests there is a bug!!

function numberToString(n, base) {
  var result = "", sign = "";
  if (n < 0) { sign = "-"; n = -n; } do { result = String(n % base) + result; n /= base; } while (n > 0);
  return sign + result;
}
console.log(numberToString(13, 10));
//> 1.5e-3231.3e-3221.3e-3211.3e-3201.3e-3191.3e-3181.3…

Ok if you already see the problem you need to imagine that you do not! So instead of just randomly chaning code and THINK!
If you add some console.logs it makes it easier to figure out what’s going on.

n this case, we want n to take the values 13, 1, and then 0. Let’s write out its value at the start of the loop.

13
1.3
0.13
0.013
…
1.5e-323

Right. Dividing 13 by 10 does not produce a whole number. Instead of n /= base, what we actually want is n = Math.floor(n / base) so that the number is properly “shifted” to the right.

But there’s an even better way by using the debugger of your browser, say what? To do so you put the word debugger; into your code, open the console on your broswer console and you step into to it, like I have mentioned before!

Day 19. Errors, Exceptions, Catching and Assertions

Yesterday we checked out bugs and today we’re going to see some other possibilities. Sometimes programmers just cannot prevent what is going to happen. If your program communicates with the outside world in any way your most likely to encounter a problem.
When dealing with a “real” application we need to actively do something to tackle the problem.

Let’s see what we can do:

function promptNumber(question) {
  var result = Number(prompt(question, ""));
  if (isNaN(result)) return null;
  else return result;
}

console.log(promptNumber("How many trees do you see?"));

Go on, open a new tab, open console (on mac that is cmd, alt + j) and write that piece of code in.
Now any code that calls promptNumber must check whether an actual number was read and, failing that, must somehow recover—maybe by asking again or by filling in a default value.

Like always there is a downside to this: Imagine that the function can return any sort of value, it would be difficult to find a special value that can be distinguish from a valid result.

Exceptions

When a function cannot proceed normally we tend to have the urge to stop what we are doing and go back to the part we know how to handle the problem. This is called exception handling.
Exceptions allow the code that runs into a problem to simply throw an exception, which is a value.
The throw statement throws a user-defined exception. Execution of the current function will stop (the statements after throw will not be executed), and control will be passed to the first catch block in the call stack. If no catch block exists among caller functions, the program will terminate.

Let’s look at an example

function promptDirection(question) {
  var result = prompt(question, "");
  if (result.toLowerCase() == "left") return "L";
  if (result.toLowerCase() == "right") return "R";
  throw new Error("Invalid direction: " + result);
}

function look() {
  if (promptDirection("Which way?") == "L")
    return "a house";
  else
    return "two angry bears";
}

try {
  console.log("You see", look());
} catch (error) {
  console.log("Something went wrong: " + error);
}

You can specify an object when you throw an exception. You can then reference the object’s properties in the catch block.

Cleaning up after Exceptions

Take a look at this code:

var context = null;

function withContext(newContext, body) {
  var oldContext = context;
  context = newContext;
  var result = body();
  context = oldContext;
  return result;
}

What if body raises an exception? In that case, the call to withContext will be thrown off the stack by the exception, and context will never be set back to its old value.
Let’s try a try statement.

function withContext(newContext, body) {
  var oldContext = context;
  context = newContext;
  try {
    return body();
  } finally {
    context = oldContext;
  }
}

The try statement allows you to define a block of code to be tested for errors while it is being executed. Like we have seen, the catch statement allows you to define a block of code to be executed, if an error occurs in the try block.
The JavaScript statements try and catch come in pairs:

try {
  withContext(5, function() {
    if (context < 10)
      throw new Error("Not enough context!");
  });
} catch (e) {
  console.log("Ignoring: " + e);
}
//> Ignoring: Error: Not enough context!

console.log(context);
//> null

withContext cleaned up the context variable.

Selective Catching

Now let’s say that the exception makes it all the way to the bottom of the stack without being caught, it gets handled by the environment. And how this is handled depends on the environment.

In a browser: This would alow use to use console to find the errors and maybe fix them. If it is not a programmers error then it might just be ok to leave the error as it is. For problems that are exception to happen, exceptions are not a good response.
Bad usage of the language can also result in exceptions being made. They can be caught just like our own exceptions.
When using a catch body is entered, all we know is that something in our try body caused an exception, but we do not know what or which one.

JavaScript does not allow us to selectively catch exceptions, you either catch them or you do not. This has it’s disadvantage of leading us to think that we have caught our exception when we might not have.

Take a look at this:

for (;;) {
  try {
    var dir = promtDirection("Where?"); // ← typo!
    console.log("You chose ", dir);
    break;
  } catch (e) {
    console.log("Not a valid direction. Try again.");
  }
}

The ;; is a way to intentionally creat a loop that does not finish on it’s own. We break out of the loop only when a valid direction is given. But we misspelled promptDirection , which will result in an “undefined variable” error. Because the catch block completely ignores its exception value ( e ), assuming it knows what the problem is, it wrongly treats the variable error as indicating bad input.

The problem with the code is that the catch block assumes that the error will be related to user input. But it’s not, and since the real error (passed as e) is never displayed the developer will be misguided searching it. To be “eloquent” your code should use the e variable to display a more useful message.
So we need a specific kind of exception.

Let’s define a new error type and use instanceOf to identify it:

function InputError(message) {
  this.message = message;
  this.stack = (new Error()).stack;
}
InputError.prototype = Object.create(Error.prototype);
InputError.prototype.name = "InputError";

The prototype is made to derive from Error.prototype so that instanceof Error will also return true for InputError objects. It’s also given a name property since the standard error types (Error, SyntaxError, ReferenceError, and so on) also have such a property.
The assignment to the stack property tries to give this object a somewhat useful stack trace, on platforms that support it, by creating a regular error object and then using that object’s stack property as its own.

Now promptDirection can throw such an error.

function promptDirection(question) {
  var result = prompt(question, "");
  if (result.toLowerCase() == "left") return "L";
  if (result.toLowerCase() == "right") return "R";
  throw new InputError("Invalid direction: " + result);
}

and the loop can catch it more carefully

for (;;) {
  try {
    var dir = promptDirection("Where?");
    console.log("You chose ", dir);
    break;
  } catch (e) {
    if (e instanceof InputError)
      console.log("Not a valid direction. Try again.");
    else
      throw e;
  }
}

Assertions
Are a way to do a basic error check for programmer errors.

That’s all you need for most basic testing! The assert function accepts two parameters:

function AssertionFailed(message) {
  this.message = message;
}
AssertionFailed.prototype = Object.create(Error.prototype);

function assert(test, message) {
  if (!test)
    throw new AssertionFailed(message);
}

function lastElement(array) {
  assert(array.length > 0, "empty array in lastElement");
  return array[array.length - 1];
}

A simple assertion solution lets our application fail early and fail at the right point in runtime execution. Allowing us to handle it better.
Let’s do the exercises and tomorrow more theory!

Day 20. Regular Expressions

Regular expressions are a tool which describe patterns in string data. They are very awkward but very useful at the same time, we will be going deeper into this throughout the chapter.

You construct a regular expression in one of two ways:
Using a regular expression literal, which consists of a pattern enclosed between slashes, such as:

var re = /ab+c/;

Or you can call the constructor function of the RegExp object, as follows:

var re = new RegExp("ab+c");

When using the RegExp constructor, the pattern is written as a normal string, so the usual rules apply for backslashes.
A regular expression pattern is composed of simple characters, such as /abc/, or a combination of simple and special characters, such as /ab*c/ or /Chapter (\d+)\.\d*/. Simple patterns are constructed of characters for which you want to find a direct match. When the search for a match requires something more than a direct match, such as finding one or more b’s, or finding white space, the pattern includes special characters. Here you can find a list of all the special characters!

Testing for Matches
test is one of the many methods that regular expressions have. If you pass it to a string it will produce a Boolean (true or false).

Let’s look at an example

console.log(/abc/.test("abcde"));
//> true
console.log(/abc/.test("abxde"));
//> false

Testing for Matches

What we just did could have been tested with a regular indexOf. Regular expressions become useful when we are using more complex patterns.
Let’s say we want to match any number. Putting the numbers inside of square brackets allows us to match any number inside of those brackets. And using a dash between the numbers would mean, take a look for any number between this and this [2-10]

Like so:

Take a look at this code:

console.log(/[0123456789]/.test("in 1992"));
//> true
console.log(/[0-9]/.test("in 1992"));
//> true

There are a number of common character groups that have their own built-in shortcuts:

\d	// Any digit character
\w	// An alphanumeric character (“word character”)
\s	// Any whitespace character (space, tab, newline, and similar)
\D	// A character that is not a digit
\W	// A nonalphanumeric character
\S	// A nonwhitespace character
.	// Any character except for newline

To match a date and time format you could do something like:

var dateTime = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/;
console.log(dateTime.test("30-01-2003 15:20"));
//> true
console.log(dateTime.test("30-jan-2003 15:20"));
//> false

Although this code is hard to read so it is not the best solution. We will take a closer look further on in the book.

Now say that you want to match any character except one certain one (this is called inversion) you can write a caret ^

Take a look at this:

var notBinary = /[^01]/;
console.log(notBinary.test("1100100010100110"));
//> false
console.log(notBinary.test("1100100010200110"));
//> true

Repeating parts of a pattern
Now let’s say we want to match a sequence or more than one digit.
If you add a + in a regular expression, it shows that the element can be repeated more than once.
That’s all you need for most basic testing! The assert function accepts two parameters:

console.log(/'\d+'/.test("'123'"));
//> true
console.log(/'\d+'/.test("''"));
//> false
console.log(/'\d*'/.test("'123'"));
//> true
console.log(/'\d*'/.test("''"));
//> true

If you add a * in a regular expression, it shows that the element can be repeated more than once but also allows the pattern to match zero times.
If you add a ? in a regular expression, it makes part of the pattern optional. meaning it may occur zero or one time.

In the following example, the u character is allowed to occur, but the pattern also matches when it is missing.

var neighbor = /neighbou?r/;
console.log(neighbor.test("neighbour"));
//> true
console.log(neighbor.test("neighbor"));
//> true

If you add a {} in a regular expression, it means that a pattern should occur a certain amount of times.

var dateTime = /\d{1,2}-\d{1,2}-\d{4} \d{1,2}:\d{2}/;
console.log(dateTime.test("30-1-2003 8:45"));
//> true

If you add a comma{,} it means the range between.

Grouping subexpressions
To be able to apply more than one subexpression you can use parenthesis.

Like so

var owlSinging = /hoot+(toot+)+/i;
console.log(owlSinging.test("hoottoottoot"));
//> true

The first and second + characters apply only to the second o in hoot and toot, respectively. The third + applies to the whole group (toot+), matching one or more sequences like that.

What does that random ido at the end of that function. It just tells it that it is case insensitive search.

This is defined as searching with flags and here are some more

g	// Global search.
i	// Case-insensitive search.
m	// Multi-line search.
y	// Perform a "sticky" search that matches starting at the current position in the target string. See sticky

Matches and groups
Now that we have seen the test method, let’s take a look at the exec (execute) method.

That will return null if it did not find a match and it will return an object with information about the match otherwise.

var match = /\d+/.exec("one two 100");
console.log(match);
//> ["100"]
console.log(match.index);
//> 8

The index property on the exec method tells us where the the successful match beings in the string! (Remember that it starts at 0).

There is also a console.log("one two 100".match(/\d+/)); //> ["100"]

When the regular expression contains subexpressions grouped with parentheses, the text that matched those groups will also show up in the array. The whole match is always the first element. The next element is the part matched by the first group (the one whose opening parenthesis comes first in the expression), then the second group, and so on.

var quotedText = /'([^']*)'/;
console.log(quotedText.exec("she said 'hello'"));
//> ["'hello'", "hello"]

When the group does not find match, its position in the output will be undefined. Likewise, if there are many matches only the last one will end in the array.

console.log(/bad(ly)?/.exec("bad"));
//> ["bad", undefined]
console.log(/(\d)+/.exec("123"));
//> ["123", "3"]

Groups can be useful for extracting parts of a string. If we don’t just want to verify whether a string contains a date but also extract it and construct an object that represents it, we can wrap parentheses around the digit patterns and directly pick the date out of the result of exec.

The date type
JavaScript has a build in Date object, yes it represents dates.

console.log(new Date());

It gives us the current date, time and timezone.

You can also create an object for a specific time

console.log(new Date(1990, 0, 22));
//>Mon Jan 22 1990 00:00:00 GMT+0100 (CET)
console.log(new Date(1986, 6, 26));
//> Sat Jul 26 1986 00:00:00 GMT+0200 (CEST)

As you may have noticed JavaScript starts the months from 0.

Timestamps are stored as the number of milliseconds since the start of 1970, using negative numbers for times before 1970 (following a convention set by “Unix time”, which was invented around that time). The getTime method on a date object returns this number. It is big, as you can imagine.

console.log(new Date(2013, 11, 19).getTime());
//> 1387407600000
console.log(new Date(1387407600000));
//> Thu Dec 19 2013 00:00:00 GMT+0100 (CET)

Date objects provide methods like getFullYear, getMonth, getDate, getHours, getMinutes, and getSeconds to extract their components. There’s also getYear, which gives you a rather useless two-digit year value (such as 93 or 14).

Putting parentheses around the parts of the expression that we are interested in, we can now easily create a date object from a string.

function findDate(string) {
  var dateTime = /(\d{1,2})-(\d{1,2})-(\d{4})/;
  var match = dateTime.exec(string);
  return new Date(Number(match[3]),
                  Number(match[2]) - 1,
                  Number(match[1]));
}
console.log(findDate("30-1-2003"));
//> Thu Jan 30 2003 00:00:00 GMT+0100 (CET)

Word and String Boundaries
The downside of findDate is that would also extract nonsense dates from strings like 30-01-40000 -> 30-01-4000. To enforce the match then we should add ^ and $ markers. The caret matches the start of the input string, while the dollar sign matches the end. So, /^\d+$/ matches a string consisting entirely of one or more digits, /^!/ matches any string that starts with an exclamation mark, and /x^/ does not match any string (there cannot be an x before the start of the string).

If, on the other hand, we just want to make sure the date starts and ends on a word boundary, we can use the marker \b.

console.log(/cat/.test("concatenate"));
//> true
console.log(/\bcat\b/.test("concatenate"));
//> false

Choice patterns
The | aka pipe character, allows us to denote a choice between a pattern to its left and the pattern to its right.

Let’s take a closer look:

var animalCount = /\b\d+ (spider|fox|owl)s?\b/;
console.log(animalCount.test("15 spiders"));
//> true
console.log(animalCount.test("15 spiderfoxes"));
//> false

(Imagine if there really were spiderfoxes… … …)

Tomorrow more!

Day 21. Regular Expressions Continued

Backtracking
Backtracking is what regular expressions do naturally during the course of matching when a match fails. For example,

if I’m matching the expression

.+b

against the string

aaaaaabcd

then it will first match aaaaaabc on the .+ and compare b against the remaining d. This fails, so it backtracks a bit and matches aaaaaab for the .+ and then compares the final b against the c. This fails too, so it backtracks again and tries aaaaaa for the .+ and the matches the b against the b and succeeds.

The Replace Method
replace is one of the many methods that string values have.

It allows you to replace one string (or part of a string) with another.

console.log("papa".replace("p", "m"));
//> mapa

See how it only replaced the first “p” it found. We can adjust this to make it change all matches by using the g option. Global. Remember that we are still talking about regular expressions.

console.log("Borobudur".replace(/[ou]/, "a"));
//> Barobudur
console.log("Borobudur".replace(/[ou]/g, "a"));
//> Barabadar

Now the replace method comes in handy when we can refer back to matched groups in the replacement string.

Take a look at this

console.log(
  "Hopper, Grace\nMcCarthy, John\nRitchie, Dennis"
    .replace(/([\w ]+), ([\w ]+)/g, "$2 $1"));
// → Grace Hopper
//   John McCarthy
//   Dennis Ritchie

What we have done here is change the Lastname, Firstname format to Firstname Lastname. The [\w ] allows for spaces in the names which you can’t see because of the sample data.$1 is replaced by the text that matched against the first group, $2 by the second, and so on, up to $9. The whole match can be referred to with $&.

It is also possible to pass a function, rather than a string, as the second argument to replace.

cvar s = "the cia and fbi";
console.log(s.replace(/\b(fbi|cia)\b/g, function(str) {
  return str.toUpperCase();
}));
// → the CIA and FBI

Greed
The repetition operators (+, *, ?, and {}) are greedy, meaning they match as much as they can and backtrack from there.
If you put a question mark after them (+?, *?, ??, {}?), they become nongreedy and start by matching as little as possible.

The first example given in the book does not work because of this greed:

function stripComments(code) {
  return code.replace(/\/\/.*|\/\*[^]*\*\//g, "");
}
console.log(stripComments("1 + /* 2 */3"));
//> 1 + 3
console.log(stripComments("x = 10;// ten!"));
//> x = 10;
console.log(stripComments("1 /* a */+/* b */ 1"));
//> 1  1

Now let’s apply what we just learnt about adding question marks.

function stripComments(code) {
  return code.replace(/\/\/.*|\/\*[^]*?\*\//g, "");
}
console.log(stripComments("1 /* a */+/* b */ 1"));
//> 1 + 1

Dynamically creating RegExp objects

You can use the RegExp constructor to create regular expression dynamically.

var name = "harry";
var text = "Harry is a suspicious character.";
var regexp = new RegExp("\\b(" + name + ")\\b", "gi");
console.log(text.replace(regexp, "_$1_"));
// → _Harry_ is a suspicious character.

Adding backslashes before alphabetic characters is a bad idea because things like \b and \n have a special meaning. But escaping everything that’s not alphanumeric or whitespace is safe. To escape these you add an additional backslash.

var name = "dea+hl[]rd";
var text = "This dea+hl[]rd guy is super annoying.";
var escaped = name.replace(/[^\w\s]/g, "\\$&");
var regexp = new RegExp("\\b(" + escaped + ")\\b", "gi");
console.log(text.replace(regexp, "_$1_"));
// → This _dea+hl[]rd_ guy is super annoying.

The search Method
indexOf cannot be called with a regular expression. Instead we use the search method.

It returns -1 when it does not find what it is asked to look for.

console.log("  hike".search(/\S/));
// → 2
console.log("    ".search(/\S/));
// → -1

The lastIndex property
exec method does not provide a convenient way to start searching from a certain point in the string. But there is another way!
source is a property for regular expression objects, it contains the string that expression was created from.
lastIndex controls where the next match will start.

Those circumstances are that the regular expression must have the global (g) option enabled, and the match must happen through the exec method.

var pattern = /y/g;
pattern.lastIndex = 3;
var match = pattern.exec("xyzzy");
console.log(match.index);
//> 4
console.log(pattern.lastIndex);
//> 5

If there was a match then the call to exec automatically updates the lastIndex property to point after the match. If there was not a match the lastIndex is set back to zero.
When using a global regular expression value for multiple exec calls, these automatic updates to the lastIndex property can cause problems. Your regular expression might be accidentally starting at an index that was left over from a previous call.
Another interesting thing about the global option is that it changes the way the match method on strings work. Match will find all matches of the pattern in the string and return an array containing the matched strings.

Take a look:

var digit = /\d/g;
console.log(digit.exec("here it is: 1"));
//> ["1"]
console.log(digit.exec("and now: 1"));
//> null

looping over matches

A common pattern is to scan through all occurrences of a pattern in a string, in a way that gives us access to the match object in the loop body, by using lastIndex and exec.

var input = "A string with 3 numbers in it... 42 and 88.";
var number = /\b(\d+)\b/g;
var match;
while (match = number.exec(input))
  console.log("Found", match[1], "at", match.index);
// → Found 3 at 14
//   Found 42 at 33
//   Found 88 at 40

Passing an Ini File

To finish up we will look at a problem that calls for regular expressions to get a better understanding. Here is the configuration file:

searchengine=http://www.google.com/search?q=$1
spitefulness=9.7

; comments are preceded by a semicolon...
; each section concerns an individual enemy
[larry]
fullname=Larry Doe
type=kindergarten bully
website=http://www.geocities.com/CapeCanaveral/11451

[gargamel]
fullname=Gargamel
type=evil sorcerer
outputdir=/home/marijn/enemies/gargamel

Parsing program in JavaScript

function parseINI(string) {
  // Start with an object to hold the top-level fields
  var currentSection = {name: null, fields: []};
  var categories = [currentSection];

  string.split(/\r?\n/).forEach(function(line) {
    var match;
    if (/^\s*(;.*)?$/.test(line)) {
      return;
    } else if (match = line.match(/^\[(.*)\]$/)) {
      currentSection = {name: match[1], fields: []};
      categories.push(currentSection);
    } else if (match = line.match(/^(\w+)=(.*)$/)) {
      currentSection.fields.push({name: match[1],
                                  value: match[2]});
    } else {
      throw new Error("Line '" + line + "' is invalid.");
    }
  });

  return categories;
}

International Characters
Things like é or β, which most definitely are word characters, will not match \w (and will match uppercase \W, the nonword category).
By a strange historical accident, \s (whitespace) does not have this problem and matches all characters that the Unicode standard considers whitespace

Tomorrow more!

Day 22. Modules

Modules are to a programs code what chapters are to books.
They allow us to gather bulks of code to make the whole program more understandable.
Why Modules help
When an author writes a book it is easier for him or her to structure the book with chapters, well this is very similar. There are a lot of benefits to using modules:

Namespacing

As we touched several times, variables on the top-level of a scope are global. We have also mentioned that this can cause interference between global and local scopes and creating chaos within our code. As we’ll see later in this post, modules allow us to avoid namespace pollution by creating a private space for our variables.

Reuse

Modules make it easier for us to reuse our own code. Often we reuse code we have used in previous programs but then realise that it might need a change and to change all of that is a waste of time.
So if we put pieces of functionality that stand on their own into separate files and modules makes them easier to track, update, and share because all the various pieces of code that want to use the module load it from the same actual file.

Decoupling

By definition, a module is self-contained. Meaning that it isolates pieces of code from each other. This is a way to update one chapter in our book without making any changes to our other chapters.

Using functions as namespaces

Functions are the only thing in JavaScript that allow us to create a new scope. So if we want our module to have it’s own scope we will have to base it on functions.

Take a look at this:

var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
             "Thursday", "Friday", "Saturday"];
function dayName(number) {
  return names[number];
}

console.log(dayName(1));
// → Monday

This example would mean that our variable name is in the global scope, meaning that if we used the variable name anywhere else (which can be easily done), then we might have some sort of interference.

To solve this we can do this:

var dayName = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return function(number) {
    return names[number];
  };
}();

console.log(dayName(3));
// → Wednesday

And to isolate the code from the outside world entirely

we can do this

(function() {
  function square(x) { return x * x; }
  var hundred = 100;

  console.log(square(hundred));
})();
// → 10000

If an expression starts with the keyword function, it is a function expression. However, if a statement starts with function, it is a function declaration, which requires a name and, not being an expression, cannot be called by writing parentheses after it.

Objects as interfaces
Now let’s say we want to add another function to our day-of-the-week module.

We would have to add it inside our existing function like so:

var weekDay = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return {
    name: function(number) { return names[number]; },
    number: function(name) { return names.indexOf(name); }
  };
}();

console.log(weekDay.name(weekDay.number("Sunday")));
// → Sunday

For bigger modules, gathering all the exported values into an object at the end of the function becomes awkward as there is so much data. What we can do is declare an object (named exports)

and add properties to that. Here’s an example

f(function(exports) {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];

  exports.name = function(number) {
    return names[number];
  };
  exports.number = function(name) {
    return names.indexOf(name);
  };
})(this.weekDay = {});

console.log(weekDay.name(weekDay.number("Saturday")));
// → Saturday

Detaching from the global scope
Sometimes even when we create modules with their own namespace they can interfere with one another. However, we can create a system that allows one module to directly ask for the interface object of another module, without going through the global scope.
A require function will load the modules file and return the appropiate interface. To do so we need two things:
1. A readFile which returns the content of a given file as a string.
2. We need to be able to actually execute this string as JavaScript code.

Detaching from the global scope
Sometimes even when we create modules with their own namespace they can interfere with one another. However, we can create a system that allows one module to directly ask for the interface object of another module, without going through the global scope.
A require function will load the modules file and return the appropiate interface. To do so we need two things:
1. A readFile which returns the content of a given file as a string.
2. We need to be able to actually execute this string as JavaScript code.

Evaluating data as code

There are several ways to take data and run it as part of a program.

eval will execute a string of code in the current scope. Normally, not a good idea becuase it might break some of the properties that scopes normally have.

Example

function evalAndReturnX(code) {
  eval(code);
  return x;
}

console.log(evalAndReturnX("var x = 2"));
//> 2

Best way is to use the function constructor. This one takes two arguments:
1. A string containing a comma-separated list of argument names
2. A string containing the function’s body.

Day 23. More Modules

Require
require

Example

function require(name) {
  var code = new Function("exports", readFile(name));
  var exports = {};
  code(exports);
  return exports;
}

console.log(require("weekDay").name(1));
// → Monday

As the new Funtion wraps the module in a function there is no need to write a wrapping namespace function in the module file itself. And since we make exports an argument to the module function, the module does not have to declare it.

So we can make our code more legible by writing it like so:

var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
             "Thursday", "Friday", "Saturday"];

exports.name = function(number) {
  return names[number];
};
exports.number = function(name) {
  return names.indexOf(name);
};

When using this pattern, a module typically starts with a few variable declarations that load the modules it depends on.

var weekDay = require("weekDay");
var today = require("today");

console.log(weekDay.name(today.dayNumber()));

The downside to this is that it can be called again and again, also is other modules have the same dependency then it will also be called.
Another problem we face is that it is not possible for a module to export a value other than the export object.

The traditional way to solve this is to create another module and apply the export property on that module.

function require(name) {
  if (name in require.cache)
    return require.cache[name];

  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);

  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);

Slow-loading modules
Due to the fact that it is slower for for the browser to fetch a file and read it than your hard disk. So if for every require you call the browser would have to fetch something, it would take it a very long time for the browser to load.

To solve this you could use a program like Browserify or you could wrap up your module in a function so that the module loader can first load its dependencies in the background and then call the function, initializing the module, when the dependencies have been loaded. This is what a AMD (Asynchronous Module Definition) module does!

define(["weekDay", "today"], function(weekDay, today) {
  console.log(weekDay.name(today.dayNumber()));
});

The modules that are loaded this way must themselves contain a call to define.

define([], function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return {
    name: function(number) { return names[number]; },
    number: function(name) { return names.indexOf(name); }
  };
});

To be able to show a minimal implementation of define, we will pretend we have a backgroundReadFile function that takes a filename and a function and calls the function with the content of the file as soon as it has finished loading it.

The modules that are loaded this way must themselves contain a call to define.

var defineCache = Object.create(null);
var currentMod = null;

function getModule(name) {
  if (name in defineCache)
    return defineCache[name];

  var module = {exports: null,
                loaded: false,
                onLoad: []};
  defineCache[name] = module;
  backgroundReadFile(name, function(code) {
    currentMod = module;
    new Function("", code)();
  });
  return module;
}

The define function itself uses getModule to fetch or create the module objects for the current module’s dependencies.
Its task is to schedule the moduleFunction (the function that contains the module’s actual code) to be run whenever those dependencies are loaded.

function define(depNames, moduleFunction) {
  var myMod = currentMod;
  var deps = depNames.map(getModule);

  deps.forEach(function(mod) {
    if (!mod.loaded)
      mod.onLoad.push(whenDepsLoaded);
  });

  function whenDepsLoaded() {
    if (!deps.every(function(m) { return m.loaded; }))
      return;

    var args = deps.map(function(m) { return m.exports; });
    var exports = moduleFunction.apply(null, args);
    if (myMod) {
      myMod.exports = exports;
      myMod.loaded = true;
      myMod.onLoad.forEach(function(f) { f(); });
    }
  }
  whenDepsLoaded();
}

Interface design
I could not have put this better: The best way to learn the value of good interface design is to use lots of interfaces—some good, some bad. Experience will teach you what works and what doesn’t. Never assume that a painful interface is “just the way it is”. Fix it, or wrap it in a new interface that works better for you.

Time to do the excercises!

Day 24. Project 2: A Programming Language

After reading the introduction to this chapter (11) I am very intrigued! Even though I am a bit ill with a cold I have caught on this Hike I am really excited about this chapter and cannot wait to start with all of you! So let’s learn how to build a programming language!

Parsing
The first thing that comes to thought when thinking about a progrmaming language is it’s syntax. A parse is a program that reads a piece of text and produces a data structure the reflects the structure of the program contained in that text.
So our program language will be called Egg and it will have a simple and uniform syntax, also everything within Egg will be an expression. An expression can be a variable, a number, a string, or an application. Applications can be used for calling functions and for constructors.
To keep this programming language simple strings are simply a sequence of characters that are not double quotes, wrapped in double quotes. Numbers are sequences of digits and variables can consist of any character that is not whitespace and does not have a special meaning in the syntax.

Applications are written the same would they are written in JavaScript:

do(define(x, 10),
   if(>(x, 5),
      print("large"),
      print("small")))

For the language to be uniform we will make operators as normal variables, applied just like other functions.
Since our syntax has no concept block we need a do construct to represent doing multiple things in sequence. The data structure will consist of expression objects, each of these objects will have a type property to say what type of expression it is and other properities to describe its content.
value properties represent literal strings or numbers.
word properties represent identifiers.
apply properties represent applications. These have two properties:
1. operator property which refers to the expression being applied.
2. args property which refers to an array of argument expressions.

The >(x, 5) part of the previous program would be represented like this:

{
  type: "apply",
  operator: {type: "word", name: ">"},
  args: [
    {type: "word", name: "x"},
    {type: "value", value: 5}
  ]
}

This type of data structure is called a syntax tree Which can look like this:

syntax_tree

We write a parser function that is recursive in a way that reflects the recursive nature of the language.

function parseExpression(program) {
  program = skipSpace(program);
  var match, expr;
  if (match = /^"([^"]*)"/.exec(program))
    expr = {type: "value", value: match[1]};
  else if (match = /^\d+\b/.exec(program))
    expr = {type: "value", value: Number(match[0])};
  else if (match = /^[^\s(),"]+/.exec(program))
    expr = {type: "word", name: match[0]};
  else
    throw new SyntaxError("Unexpected syntax: " + program);

  return parseApply(expr, program.slice(match[0].length));
}

function skipSpace(string) {
  var first = string.search(/\S/);
  if (first == -1) return "";
  return string.slice(first);
}

The downside to this is that it can be called again and again, also is other modules have the same dependency then it will also be called.
Another problem we face is that it is not possible for a module to export a value other than the export object.

The traditional way to solve this is to create another module and apply the export property on that module.

function require(name) {
  if (name in require.cache)
    return require.cache[name];

  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);

  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);

Because Egg allows any amount of whitespace between its elements, we have to repeatedly cut the whitespace off the start of the program string. This is what the skipSpace function helps with.

SyntaxError is a standard error object type, which is raised when an attempt is made to run an invalid JavaScript program.

parseApply checks whether the expression is an application. If so, it parses a parenthesized list of arguments.

function parseApply(expr, program) {
  program = skipSpace(program);
  if (program[0] != "(")
    return {expr: expr, rest: program};

  program = skipSpace(program.slice(1));
  expr = {type: "apply", operator: expr, args: []};
  while (program[0] != ")") {
    var arg = parseExpression(program);
    expr.args.push(arg.expr);
    program = skipSpace(arg.rest);
    if (program[0] == ",")
      program = skipSpace(program.slice(1));
    else if (program[0] != ")")
      throw new SyntaxError("Expected ',' or ')'");
  }
  return parseApply(expr, program.slice(1));
}

If the next character in the program is not an opening parenthesis, this is not an application, and parseApply simply returns the expression it was given.

We wrap it in a parse function that verifies that it has reached the end of the input string after parsing the expression (an Egg program is a single expression), and that gives us the program’s data structure.

function parse(program) {
  var result = parseExpression(program);
  if (skipSpace(result.rest).length > 0)
    throw new SyntaxError("Unexpected text after program");
  return result.expr;
}

console.log(parse("+(a, 10)"));
// → {type: "apply",
//    operator: {type: "word", name: "+"},
//    args: [{type: "word", name: "a"},
//           {type: "value", value: 10}]}

The Evaluator

function evaluate(expr, env) {
  switch(expr.type) {
    case "value":
      return expr.value;

    case "word":
      if (expr.name in env)
        return env[expr.name];
      else
        throw new ReferenceError("Undefined variable: " +
                                 expr.name);
    case "apply":
      if (expr.operator.type == "word" &&
          expr.operator.name in specialForms)
        return specialForms[expr.operator.name](expr.args,
                                                env);
      var op = evaluate(expr.operator, env);
      if (typeof op != "function")
        throw new TypeError("Applying a non-function.");
      return op.apply(null, expr.args.map(function(arg) {
        return evaluate(arg, env);
      }));
  }
}

var specialForms = Object.create(null);

The evaluator has code for each of the expression types. A literal value expression simply produces its value. But for a variable it needs to check its environment and then get the variables value.

This is really all that is needed to interpret Egg. It is that simple. But without defining a few special forms and adding some useful values to the environment, you can’t do anything with this language yet. And tomorrow we will check this out!

Day 25. Project 2.2: A Programming Language

Special Forms

Yesterday we left it at special forms. Let’s take a look at how to use the specialForms object to define the special syntax.

specialForms["if"] = function(args, env) {
  if (args.length != 3)
    throw new SyntaxError("Bad number of args to if");

  if (evaluate(args[0], env) !== false)
    return evaluate(args[1], env);
  else
    return evaluate(args[2], env);
};

The reason we need to represent if as a special form, is that all arguments to functions are evaluated before the function is called, whereas if should evaluate only either its second or its third argument, depending on the value of the first.

The same goes for the while constructor:

specialForms["while"] = function(args, env) {
  if (args.length != 2)
    throw new SyntaxError("Bad number of args to while");

  while (evaluate(args[0], env) !== false)
    evaluate(args[1], env);

  // Since undefined does not exist in Egg, we return false,
  // for lack of a meaningful result.
  return false;
};

We also have do

specialForms["do"] = function(args, env) {
  var value = false;
  args.forEach(function(arg) {
    value = evaluate(arg, env);
  });
  return value;
};

The environment

We need to define an environment as our global scope.

For starters we need to create boolean values to be able to use the if construct.

We need define to be able to create variables and give them new values.

var topEnv = Object.create(null);

topEnv["true"] = true;
topEnv["false"] = false;

Check if it works

var prog = parse("if(true, false, true)");
console.log(evaluate(prog, topEnv));
//> false

Now let’s add some basic arithmetic. I’ll explain what is going on here after the code:

["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) {
  topEnv[op] = new Function("a, b", "return a " + op + " b;");
});

We are using new Function to synthesize a bunch of operator functions in a loop, rather than defining them all individually.

A way to output values is also necessary so let’s use console.log to do so

topEnv["print"] = function(value) {
  console.log(value);
  return value;
};

Now that we have to essential tools to start our program we need a way to run them.

function run() {
  var env = Object.create(topEnv);
  var program = Array.prototype.slice
    .call(arguments, 0).join("\n");
  return evaluate(parse(program), env);
}

This allows us to create a fresh environment and parses and evalutes the strings we give it as a single program.

The use of Array.prototype.slice.call is a trick to turn an array-like object, such as arguments, into a real array so that we can call join on it.

Functions
We need functions for our programming language, no doubt about it.

We’re going to make this happen by using a fun construct.

which treats its last argument as the function’s body and treats all the arguments before that as the names of the function’s arguments.

specialForms["fun"] = function(args, env) {
  if (!args.length)
    throw new SyntaxError("Functions need a body");
  function name(expr) {
    if (expr.type != "word")
      throw new SyntaxError("Arg names must be words");
    return expr.name;
  }
  var argNames = args.slice(0, args.length - 1).map(name);
  var body = args[args.length - 1];

  return function() {
    if (arguments.length != argNames.length)
      throw new TypeError("Wrong number of arguments");
    var localEnv = Object.create(env);
    for (var i = 0; i < arguments.length; i++)
      localEnv[argNames[i]] = arguments[i];
    return evaluate(body, localEnv);
  };
};

Functions in Egg have their own local environment. Take a look:

run("do(define(plusOne, fun(a, +(a, 1))),",
    "   print(plusOne(10)))");
// → 11

run("do(define(pow, fun(base, exp,",
    "     if(==(exp, 0),",
    "        1,",
    "        *(base, pow(base, -(exp, 1)))))),",
    "   print(pow(2, 10)))");
// → 1024

Compilation
Compilation is the process of adding another step between the parsing and the running of a program, which transforms the program into something that can be evaluated more efficiently by doing as much work as possible in advance. Normally, this involves converting the program to machine code. We will not be seeing this right now so let's do the exercises!

Day 26. PART2!!: JavaScript and The Browser

If there wasn't a browser there would not be JavaScript.
Networks and the Internet

Computer networks have been around since the 1950s!! If you put cables between two or more computers and allow them to send data back and forth through these cables, you can do all kinds of wonderful things. Imagine what we can do by connecting all the computers around the world 😉 ie. The Internet

For computers to communicate with each other they need to understand each other, they both need to know what the bits represent.
A network protocol describe the "type" of communication over a network. There are protocols for sending email, for fetching email, for sharing files, or even for controlling computers that happen to be infected by malicious software.

Most protocols are built on top of other protocols.

Using a network connection, including connecting to the Internet, computers connect to each other to transmit data between them and communicate with each other using the TCP/IP (Transmission Control Protocol / Internet Protocol).

Marijn gives us a really good explanation here:
A TCP connection works as follows: one computer must be waiting, or listening, for other computers to start talking to it. To be able to listen for different kinds of communication at the same time on a single machine, each listener has a number (called a port) associated with it. Most protocols specify which port should be used by default. For example, when we want to send an email using the SMTP protocol, the machine through which we send it is expected to be listening on port 25.
Another computer can then establish a connection by connecting to the target machine using the correct port number. If the target machine can be reached and is listening on that port, the connection is successfully created. The listening computer is called the server, and the connecting computer is called the client.

Think of TCP/IP as a book of rules, a step-by-step guide that each computer uses to know how to talk to another computer. This book of rules dictates what each computer must do to transmit data, when to transmit data, how to transmit that data. It also states how to receive data in the same manner. If the rules are not followed, the computer will not be able to connect to another computer, nor send and receive data between other computers.

The Web
The World Wide Web (not the whole internet) is a set of protocols and formats that allows us to visit different web pages in a browser.
Ever wondered what http stands for?
Hypertext Transfer Protocol! See that, it has a protocol. To be able to add content to the web you just need to conect a machine to the internet, make it listen to port 80 using this protocol.
URL: Uniform Resource Locator and each document on the web is named by this.

So:
http:// -> protocol
anacidre.com -> server
/javascript-hike -> path

Each machine connected to the Internet gets a unique IP address, which looks something like 37.187.37.82. These can be used as the server part of a URL. But as names are easier to remember than a bunch of numbers we tend to register a name and point it to the machine.

HTML
Hypertext Markup Language, is the document format used for web pages. Recently I was a mentor at the First Rails Girls in Galicia. I did a HTML and CSS crash course for the people who had no idea what HTML and CSS was. Here are my slides which might help you with HTML if you do not know what it already is.

HTML and JavaScript
As you have seen in the slides or already know HTML uses tags. And the most important tag for us at the moment is , even if it refers to a script file and doesn’t contain any code. If you forget this, the rest of the page will be interpreted as part of the script.

Remember what attributes are? No? Take a look at my slides. Yes? Good. Because some of them can contain a JavaScript program.

For example: Button

<button onclick="alert('Boom!');">DO NOT PRESS</button>

In the Sandbox
As we know it can be dangerous to download programs, whether it's virus or malware we are afraid of there is a risk!

So browsers do not allow us to do certain things with JavaScript to reduce that risk.

A sandbox is a way to isolate this code. The idea being that the program is harmlessly playing in a sandbox. But you should imagine this particular kind of sandbox as having a cage of thick steel bars over it, which makes it somewhat different from your typical playground sandbox. But this makes it difficult to allow programs to be useful.

Compatibility and the browser wars
Since the start of the web, web developers have had to deal with all sorts of browsers, first of all they only had one to deal with (Mosaic) and then there were two or three.. And there were lots of bugs. Nowadays however, we have quite a few different browsers (my favourite: Chrome) and most of them have very few bugs which allow web developers to do their job.

But still, writing websites for all browsers is still a challenge (trust me!) and it seems that it might just take a while until everyone starts using Chrome 😉

Day 27. The Document Object Model

When we open a web page, the browser gets the HTML and parses it. The browser builds up a model of the document's structure and then draws this structure on the screen.

Document Structure

So this piece of code:

<!doctype html>
<html>
  <head>
    <title>My home page</title>
  </head>
  <body>
    <h1>My home page</h1>
    <p>HI! I am Ana Cidre and this is my home page.</p>
    <p>I am also learning JavaScript! Read it
      <a href="http://anacidre.com/javascript-hike">here</a>.</p>
  </body>
</html>

Would be structured like this: (without the colours, I just did that to make it look good 😉 )

html-boxes

For each box, there is an object, which we can interact with to find out things such as what HTML tag it represents and which boxes and text it contains. This representation is called the Document Object Model (DOM).

The global variable document allows us to access these objects.
documentElement is a property that refers to the object representing the html tag. I also provides the properties head and body.

Trees

Each node can refer to other nodes, "children", which in turn may have their own children. We can see the data structure above as a tree as it has no cycles and has a well defined root. In the case of the DOM, document.documentElement serves as the root.

In programming we see a lot of trees, just like if we were doing an everyday hike ;). A typical tree has different kinds of nodes. Application nodes always have children, whereas variables and values are leaves, or nodes without children.

Same goes for DOM. Nodes which represent HTML determine the structure of the document. The can have child nodes (ie. document.body) and some of these children can be leaves(ie text documents or comments).

Each DOM node object has a nodeType property. Which allows us to identify the node by its number.
Value 1 would be the regular elements like document.ELEMENT_NODE
Value 3 would be the text nodes
Value 8 would be the comments nodes.

So this is how our document tree would be:
html-tree
The leaves are text nodes, and the arrows indicate parent-child relationships between nodes.

The Standard

Using cryptic numeric codes to respresent nodes does not feel like JavaScript. Well that's because DOM was not designed for JavaScript. It actually tries to define a language-neutral interface that can be used in other systems as well—not just HTML but also XML.

There are many cons and some pros to having a cross-language consistency interface, but I am not going to go into that right now. If it really interests you Marijn writes a bit about it in Chapter 13.

Moving through the tree
DOM nodes contain a wealth of links to other nearby nodes. Check them out:

html-links

Although the diagram shows only one link of each type, every node has a parentNode property that points to the node that is containing it. Likewise, every element node (node type 1) has a childNodes property that points to an array-like object holding its children.

In theory you can move around this tree using just child and parent links, however, JavaScript give you additional convenience links.
firstChild property points you to the first child
lastChild property points you to the last child
If the value is null that node has no children.
previousSibling and nextSibling ppoint to adjacent nodes, which are nodes with the same parent that appear immediately before or after the node itself.

When dealing with nested data like the previous example, recursive functions come in handy. The following recursive function scans a document for text nodes containing a given string and returns true when it has found one:

function talksAbout(node, string) {
  if (node.nodeType == document.ELEMENT_NODE) {
    for (var i = 0; i < node.childNodes.length; i++) {
      if (talksAbout(node.childNodes[i], string))
        return true;
    }
    return false;
  } else if (node.nodeType == document.TEXT_NODE) {
    return node.nodeValue.indexOf(string) > -1;
  }
}

console.log(talksAbout(document.body, "learning"));
// → true

nodeValue property of a text node refers to the string of text that it represents.

Finding elements

Finding specific elements in a DOM can get tricky. It would not be a good idea to “Get the third child of the sixth child of the document body” because counting the children can be tricky! In our last example there are 7 children, crazy right? But DOM counts white spaces as children too. So 3 children elements plus 4 white spaces equal 7 children.

So to find an element it would be better to “Get the first link in the document”:

var link = document.body.getElementsByTagName("a")[0];
console.log(link.href);

getElementsByTagName is a method that allows us to collect all elements with the given tag name. That are descendants (direct or indirect children) of the given node and returns them as an array-like object.

Now to find a specific single node we can use an id attribute to be able to find it:

<p>My ostrich Gertrude:</p>
<p><img id="gertrude" src="img/ostrich.png"></p>

<script>
  var ostrich = document.getElementById("gertrude");
  console.log(ostrich.src);
</script>

getElementsByClassName is a method that is very similar to getElementsByTagName but retrieves all elements that have the given string in their class attribute.

Changing the document
We can change almost everything about the DOM document:
removeChild removes the given child node from the document.
appendChild which adds it to the end of the list as of children.
insertBefore inserts the node given as the first argument before the node given as the second argument.

<p>One</p>
<p>Two</p>
<p>Three</p>

<script>
  var paragraphs = document.body.getElementsByTagName("p");
  document.body.insertBefore(paragraphs[2], paragraphs[0]);
</script>

A node in the document can only exist in one place, so in this case, paragraph three will be moved to the top and will no longer exist after paragraph two.
replaceChild method allows us to replace one node with another one.

Creating Nodes

Say we wanted to change all the cat images in a document with hat images and by doing that we also want to change their alt attributes:

<p>The <img src="img/cat.png" alt="Cat"> in the
  <img src="img/hat.png" alt="Hat">.</p>

<p><button onclick="replaceImages()">Replace</button></p>

<script>
  function replaceImages() {
    var images = document.body.getElementsByTagName("img");
    for (var i = images.length - 1; i >= 0; i--) {
      var image = images[i];
      if (image.alt) {
        var text = document.createTextNode(image.alt);
        image.parentNode.replaceChild(text, image);
      }
    }
  }
</script>

This involves not only removing the images but adding a new text node(type 3) to replace them. For this, we use the document.createTextNode method.
The loop that goes over the images starts at the end of the list of nodes. This is necessary because the node list returned by a method like getElementsByTagName (or a property like childNodes) is live. That is, it is updated as the document changes. If we started from the front, removing the first image would cause the list to lose its first element so that the second time the loop repeats, where i is 1, it would stop because the length of the collection is now also 1.

If you do not want a live node you can convert the collection to a real array by calling the array slice method on it:

var arrayish = {0: "one", 1: "two", length: 2};
var real = Array.prototype.slice.call(arrayish, 0);
real.forEach(function(elt) { console.log(elt); });
// > one
//   two

If we want to create a regular element node (type 1) we can use the document.createElement method.

<blockquote id="quote">
  No book can ever be finished. While working on it we learn
  just enough to find it immature the moment we turn away
  from it.
</blockquote>

<script>
  function elt(type) {
    var node = document.createElement(type);
    for (var i = 1; i < arguments.length; i++) {
      var child = arguments[i];
      if (typeof child == "string")
        child = document.createTextNode(child);
      node.appendChild(child);
    }
    return node;
  }

  document.getElementById("quote").appendChild(
    elt("footer", "—",
        elt("strong", "Karl Popper"),
        ", preface to the second editon of ",
        elt("em", "The Open Society and Its Enemies"),
        ", 1950"));
</script>

This code allows us to make all the other arguments children of the regular element node we just created.

Tomorrow we will continue with DOM and see attributes, layout and more!

Day 28. Attributes

Some element attributes (in HTML) can be accessed through a property of the same name on the elements DOM object.

HTML allows us to set any attribute on nodes. However, if we use our own attribute name we cannot access them through a property, we would have to use the getAttribute and setAttribute methods.
When we open a web page, the browser gets the HTML and parses it. The browser builds up a model of the document's structure and then draws this structure on the screen.

Take a look:

<p data-classified="secret">The launch code is 00000000.</p>
<p data-classified="unclassified">I have two feet.</p>

<script>
  var paras = document.body.getElementsByTagName("p");
  Array.prototype.forEach.call(paras, function(para) {
    if (para.getAttribute("data-classified") == "secret")
      para.parentNode.removeChild(para);
  });
</script>

Here we use data- to make sure that that attribute is not already being used.

In the next example we look for the pretags with the data-language attribute and highlight them:

function highlightCode(node, keywords) {
  var text = node.textContent;
  node.textContent = ""; // Clear the node

  var match, pos = 0;
  while (match = keywords.exec(text)) {
    var before = text.slice(pos, match.index);
    node.appendChild(document.createTextNode(before));
    var strong = document.createElement("strong");
    strong.appendChild(document.createTextNode(match[0]));
    node.appendChild(strong);
    pos = keywords.lastIndex;
  }
  var after = text.slice(pos);
  node.appendChild(document.createTextNode(after));
}

The function highlightCode takes a pre node and a regular expression (with the “global” option turned on) that matches the keywords of the programming language that the element contains.

We can highlight all programs on the page by looping over all the pre elements that have a data-language attribute and calling highlightCode on each one with the correct regular expression for the language.

var languages = {
  javascript: /\b(function|return|var)\b/g /* … etc */
};

function highlightAllCode() {
  var pres = document.body.getElementsByTagName("pre");
  for (var i = 0; i < pres.length; i++) {
    var pre = pres[i];
    var lang = pre.getAttribute("data-language");
    if (languages.hasOwnProperty(lang))
      highlightCode(pre, languages[lang]);
  }
}

The result in action:

<p>Here it is, the identity function:</p>
<pre data-language="javascript">
function id(x) { return x; }

To access the class attribute you need to use className or you can access it under its real name, "class", by using the getAttribute and setAttribute methods.

Layout

In the layout we saw at yesterday you might have noticed how the a tag was inside a block whereas the p tags had their own blocks, that is because the latter are block elements and tags like the a tag are inline elements.
Browsers are able to compute a layout, which gives each element a size and position based on its type and content. This layout is then used to actually draw the document.

With JavaScript we can find out the size and position of an element by using these methods:

offsetWidth // property that gives you the width the element takes up in pixels.
offsetHeight // property that gives you the height the element takes up in pixels.
clientWidth  // property that gives you the width of the space inside the element.
clientHeight // property that gives you the height of the space inside the element.
<p style="border: 3px solid red">
  I'm boxed in
</p>

<script>
  var para = document.body.getElementsByTagName("p")[0];
  console.log("clientHeight:", para.clientHeight);
  console.log("offsetHeight:", para.offsetHeight);
</script>

getBoundingClientRect method returns an object with top, bottom, left, and right properties, indicating the pixel positions of the sides of the element relative to the top left of the screen. If you want them relative to the whole document, you must add the current scroll position, found under the global pageXOffset and pageYOffset variables.
A program that repeatedly alternates between reading DOM layout information and changing the DOM forces a lot of layouts to happen and will consequently run really slowly.

Styling

We can style elements with HTML. To do this we can use the style attribute like this:

<p><a href=".">Normal link</a></p>
<p><a href="." style="color: green">Green link</a></p>

The style attribute can take many declarations, to do so they must be separated by semi-colons like this: "color: red; border: none"

JavaScript code can directly manipulate the style of an element through the node’s style property. This property holds an object that has properties for all possible style properties. The values of these properties are strings, which we can write to in order to change a particular aspect of the element’s style.

<p id="para" style="color: purple">
  Pretty text
</p>

<script>
  var para = document.getElementById("para");
  console.log(para.style.color);
  para.style.color = "magenta";
</script>

If the property name has a dash, like font-size, then you need to write it like this:
style.fontFamily

Cascading styles

The styling system for HTML is called CSS for Cascading Style Sheets. This is a better approach than styling in the HTML. The cascading in the name refers to the fact that multiple such rules are combined to produce the final style for an element.

I am pretty sure most of you who are reading this know what CSS is but just incase here is an example:

strong {
    font-style: italic;
    color: gray;
  }

Say in the style attribute we added font-style: normal, that would override the example for strong. Styles in a style attribute applied directly to the node have the highest precedence and always win.

In CSS we use classes and IDs that allow us to call the piece of code whatever we like. We just use the name we've given to the code in the class attribute or ID attribute and we're good to go:

HTML
<div id="header" class="subtle">
<p>Hello, I have an ID and a class</p>
</div>

CSS
.subtle {
  color: gray;
  font-size: 80%;
}
#header {
  background: blue;
  color: white;
}

Classes in CSS are defined by a "." and IDs "#".
The precedence rule favoring the most recently defined rule holds true only when the rules have the same specificity. A rule’s specificity is a measure of how precisely it describes matching elements, determined by the number and kind (tag, class, or ID) of element aspects it requires.

Query selectors

The querySelectorAll method, which is defined both on the document object and on element nodes, takes a selector string and returns an array-like object containing all the elements that it matches.

<p>And if you go chasing
  <span class="animal">rabbits</span></p>
<p>And you know you're going to fall</p>
<p>Tell 'em a <span class="character">hookah smoking
  <span class="animal">caterpillar</span></span></p>
<p>Has given you the call</p>

<script>
  function count(selector) {
    return document.querySelectorAll(selector).length;
  }
  console.log(count("p"));           // All <p> elements
  // → 4
  console.log(count(".animal"));     // Class animal
  // → 2
  console.log(count("p .animal"));   // Animal inside of <p>
  // → 2
  console.log(count("p > .animal")); // Direct child of <p>
  // → 1
</script>

The querySelectorAll is not live!

Positioning and animating

There is a style property in HTML that is called "position". This has several values but it's default Value is static.

Let's see what we can do with it:

static // Default value. Elements render in order, as they appear in the document flow
absolute // The element is positioned relative to its first positioned (not static) ancestor element
fixed // The element is positioned relative to the browser window
relative // The element is positioned relative to its normal position, so "left:20px" adds 20 pixels to the element's LEFT position
initial // Sets this property to its default value. Read about initial
inherit // Inherits this property from its parent element. Read about inherit

We can use this to create an animation. The following document displays a picture of a cat that floats around in an ellipse:

<p style="text-align: center">
  <img src="img/cat.png" style="position: relative">
</p>
<script>
  var cat = document.querySelector("img");
  var angle = 0, lastTime = null;
  function animate(time) {
    if (lastTime != null)
      angle += (time - lastTime) * 0.001;
    lastTime = time;
    cat.style.top = (Math.sin(angle) * 20) + "px";
    cat.style.left = (Math.cos(angle) * 200) + "px";
    requestAnimationFrame(animate);
  }
  requestAnimationFrame(animate);
</script>

The picture is centered on the page and given a position of relative. We will repeatedly update that picture’s top and left styles in order to move it.

The script uses requestAnimationFrame to schedule the animate function to run whenever the browser is ready to repaint the screen. The animate function itself again calls requestAnimationFrame to schedule the next update, it lets the browser know that we are done for now, and it can go ahead and do the things that browsers do, such as updating the screen and responding to user actions.

Moving in circles is done using the trigonometry functions Math.cos and Math.sin.
Math.cos and Math.sin are useful for finding points that lie on a circle around point (0,0) with a radius of one unit. Both functions interpret their argument as the position on this circle, with zero denoting the point on the far right of the circle, going clockwise until 2π (about 6.28) has taken us around the whole circle. Math.cos tells you the x-coordinate of the point that corresponds to the given position around the circle, while Math.sin yields the y-coordinate. Positions (or angles) greater than 2π or less than 0 are valid—the rotation repeats so that a+2π refers to the same angle as a.

cos-sin

Time to do some exercises!

Day 29. Handling Events

With some programs we use a different type of input, like a keyboard and a mouse, and when they are used we do not know in which order, how or when. Let's take a look at these.

Event handlers

The best way to "register" a key being clicked on the keyboard is to give our code a chance to react to events as they occur. Browsers allow us to do this, we need to register functions as handlers for specific events to do so.

Take a look:

<p>Click this document to activate the handler.</p>
<script>
  addEventListener("click", function() {
    console.log("You clicked!");
  });
</script>

The addEventListener function registers its second argument to be called whenever the event described by its first argument occurs.

Events and DOM nodes

In the previous example we are calling the addEventListener function to the whole window. We do this because the global scope of a browser is it's window. Every DOM element has its own span class="code">addEventListener method that allows you to listen on that element.

In the following example we are attaching the addEventListener function to a button. So when you click on that button and only on that button it will cause the handler to run.

<button>Click me</button>
<p>No handler here.</p>
<script>
  var button = document.querySelector("button");
  button.addEventListener("click", function() {
    console.log("Button clicked.");
  });
</script>

You can also use the onClick function, it works like the addEventListener function but you can only use it once per node.

To remove a handler we would use the removeEventListener function.

<button>Act-once button</button>
<script>
  var button = document.querySelector("button");
  function once() {
    console.log("Done.");
    button.removeEventListener("click", once);
  }
  button.addEventListener("click", once);
</script>

Event objects

The argument we pass the event handler is called an event object. This object gives us information about the event, such as whether the user clicked with the left or right button.

<button>Click me any way you want</button>
<script>
  var button = document.querySelector("button");
  button.addEventListener("mousedown", function(event) {
    if (event.which == 1)
      console.log("Left button");
    else if (event.which == 2)
      console.log("Middle button");
    else if (event.which == 3)
      console.log("Right button");
  });
</script>

Later on we will discuss the type of events.

Propagation

Events handlers that are registered on nodes with children will also receive the same events. So if we put an event handler on a button in a paragraph, the whole paragraph takes the event handler. Unless we create two handlers, in which the button will get to go first. This is called propagation as the event is said to propagate outward.
Start with the child, then the parent and finally the root.

We can stop this by calling the stopPropagation method on the event object to prevent handlers that are higher up from receiving the event.

The following example registers "mousedown" handlers on both a button and the paragraph around it. When clicked with the right mouse button, the handler for the button calls stopPropagation, which will prevent the handler on the paragraph from running. When the button is clicked with another mouse button, both handlers will run.

<p>A paragraph with a <button>button</button>.</p>
<script>
  var para = document.querySelector("p");
  var button = document.querySelector("button");
  para.addEventListener("mousedown", function() {
    console.log("Handler for paragraph.");
  });
  button.addEventListener("mousedown", function(event) {
    console.log("Handler for button.");
    if (event.which == 3)
      event.stopPropagation();
  });
</script>

We can use a target property on most event objects to make sure you are not accidentally handling something that propagated up from a node.
We can also use the target property to be able to use an event handler on several of the same type objects.

Like Button

<button>A</button>
<button>B</button>
<button>C</button>
<script>
  document.body.addEventListener("click", function(event) {
    if (event.target.nodeName == "BUTTON")
      console.log("Clicked", event.target.textContent);
  });
</script>

Default actions

Many events have a default action. If you click a link, you will be taken to the link’s target. If you press the down arrow, the browser will scroll the page down...

Normally, the JavaScript event handlers will overwrite the default ones, if this does not happen then we can call the preventDefault method to stop the default action from happening.

This will allow us to do things to annoy the user 😉

check this out:

<a href="https://developer.mozilla.org/">MDN</a>
<script>
  var link = document.querySelector("a");
  link.addEventListener("click", function(event) {
    console.log("Nope.");
    event.preventDefault();
  });
</script>

But we should not do these things due to the fact that it can be really unpleasant when things do not do what they are supposed to.

Key events

When we press down a key on our keyboard the browaer fires a keydown event, and when we let go of the key a keydown event.Despite its name, "keydown" fires not only when the key is physically pushed down. When a key is pressed and held, the event fires again every time the key repeats.

the keyCode property of the event object is how we identify which key is being pressed or released. Unfortunately, it’s not always obvious how to translate the numeric key code to an actual key.

For letter and number keys, the associated key code will be the Unicode character code associated with the (uppercase) letter or number printed on the key. The charCodeAt method on strings gives us a way to find this code.

console.log("Violet".charCodeAt(0));
//> 86
console.log("1".charCodeAt(0));
//> 49

The best way to find the code you need is usually by experimenting. Register a key event handler that logs the key codes it gets and press the key you are interested in. Modifier keys such as Shift, Ctrl, Alt, and Meta (Command on Mac) generate key events just like normal keys.

Which allows us to do combinations of keys!

<p>Press Ctrl-Space to continue.</p>
<script>
  addEventListener("keydown", function(event) {
    if (event.keyCode == 32 && event.ctrlKey)
      console.log("Continuing!");
  });
</script>

If we want to register the text that is being typed we can use an event called keypress.We can use the String.fromCharCode function to turn this code into an actual single-character string.

Check it out!

<p>Focus this page and type something.</p>
<script>
  addEventListener("keypress", function(event) {
    console.log(String.fromCharCode(event.charCode));
  });
</script>

Mouse clicks

When we click our mouse (or trackpad)the browser fires a mousedown event, and when we let go, a mouseup event. Just like our keydown and keydown events. These will happen on the DOM nodes that are immediately below the mouse pointer when the event occurs.

After the mouseup event happens a click event takes place on the most specific node that had both the press and the release of the mouse.

To register a double click we have the dblclick event, which fires up after the second click.

Te retrieve information about the place where a mouse event happened you can look at its pageX and pageY properties, which contain the event’s coordinates (in pixels) relative to the top-left corner of the document.

This examples allows us to draw dots!

<style>
  body {
    height: 200px;
    background: beige;
  }
  .dot {
    height: 8px; width: 8px;
    border-radius: 4px; /* rounds corners */
    background: blue;
    position: absolute;
  }
</style>
<script>
  addEventListener("click", function(event) {
    var dot = document.createElement("div");
    dot.className = "dot";
    dot.style.left = (event.pageX - 4) + "px";
    dot.style.top = (event.pageY - 4) + "px";
    document.body.appendChild(dot);
  });
</script>

The clientX and clientY properties are similar to pageX and pageY but relative to the part of the document that is currently scrolled into view.

Mouse motion

When we MOVE our mouse (or our finger on the trackpad) the browser fires a mousemove event. We can use this to track the position of the mouse.
A common situation in which this is useful is when implementing some form of mouse-dragging functionality.

Let's look at an example:

<p>Drag the bar to change its width:</p>
<div style="background: orange; width: 60px; height: 20px">
</div>
<script>
  var lastX; // Tracks the last observed mouse X position
  var rect = document.querySelector("div");
  rect.addEventListener("mousedown", function(event) {
    if (event.which == 1) {
      lastX = event.pageX;
      addEventListener("mousemove", moved);
      event.preventDefault(); // Prevent selection
    }
  });

  function buttonPressed(event) {
    if (event.buttons == null)
      return event.which != 0;
    else
      return event.buttons != 0;
  }
  function moved(event) {
    if (!buttonPressed(event)) {
      removeEventListener("mousemove", moved);
    } else {
      var dist = event.pageX - lastX;
      var newWidth = Math.max(10, rect.offsetWidth + dist);
      rect.style.width = newWidth + "px";
      lastX = event.pageX;
    }
  }
</script>

Note that the mousemove is on the whole browser because if we drag the bar and we move our mouse outside of the bar we still want this to work.

All major browsers support either buttons or which, so the buttonPressed function in the example first tries buttons, and falls back to which when that isn’t available.

When we put our mouse over a node it fires up a mouseover and a mouseout. These are typically used for hover effects, to show or style something,.. But it is not that simple.

We have the propagate problem. So to deal with this we can use a relatedTarget property of the events object created for these events.

Say we want to change our hover effect only when the relatedTarget is outside of our target node.

<p>Hover over this <strong>paragraph</strong>.</p>
<script>
  var para = document.querySelector("p");
  function isInside(node, target) {
    for (; node != null; node = node.parentNode)
      if (node == target) return true;
  }
  para.addEventListener("mouseover", function(event) {
    if (!isInside(event.relatedTarget, para))
      para.style.color = "red";
  });
  para.addEventListener("mouseout", function(event) {
    if (!isInside(event.relatedTarget, para))
      para.style.color = "";
  });
</script>

The isInside function follows the given node’s parent links until it either reaches the top of the document (when node becomes null) or finds the parent we are looking for.

I honestly would not go through the trouble of doing this through JavaScript but rather through CSS as it has a :hover property which makes things easier. But we are learning JavaScript!

Tomorrow more!

Day 30. Scroll Events, Focus Events, Load Events,...

Scroll Events
Whenever we scroll a scroll event is fired. I love Marijn's explanation of why this can be useful:
This has various uses, such as knowing what the user is currently looking at (for disabling off-screen animations or sending spy reports to your evil headquarters) or showing some indication of progress (by highlighting part of a table of contents or showing a page number).

Let's draw a progress bar that can be filled by scrolling!

<style>
  .progress {
    border: 1px solid blue;
    width: 100px;
    position: fixed;
    top: 10px; right: 10px;
  }
  .progress > div {
    height: 12px;
    background: blue;
    width: 0%;
  }
  body {
    height: 2000px;
  }
</style>
<div class="progress"><div></div></div>
<p>Scroll me...</p>
<script>
  var bar = document.querySelector(".progress div");
  addEventListener("scroll", function() {
    var max = document.body.scrollHeight - innerHeight;
    var percent = (pageYOffset / max) * 100;
    bar.style.width = percent + "%";
  });
</script>

I might just used this last one on my JavaScript hike post 😉

Focus events

When an element gains focus, the browser fires a "focus" event on it. When it loses focus, a "blur" event fires. Luckily these two do not propagate.

Now we are going to apply some help text so that the users know what we want exactly

<p>Name: <input type="text" data-help="Your full name"></p>
<p>Age: <input type="text" data-help="Age in years"></p>
<p id="help"></p>

<script>
  var help = document.querySelector("#help");
  var fields = document.querySelectorAll("input");
  for (var i = 0; i < fields.length; i++) {
    fields[i].addEventListener("focus", function(event) {
      var text = event.target.getAttribute("data-help");
      help.textContent = text;
    });
    fields[i].addEventListener("blur", function(event) {
      help.textContent = "";
    });
  }
</script>

Load Event

When a page finished loading the "load" event is fired on the window and on the document body object. This is normally used for when we want things to happen on the broswer once the whole document is loaded. These events also do not propagate.

When a page is closed or navigated away from (for example by clicking on a link), a "beforeunload" event fires.The main use of this event is to prevent the user from accidentally losing work by closing a document.

Script execution timeline

There are various things that get a script tag to start running. It is important to note that no two scripts can run at the same moment. If a script is already running, event handlers and pieces of code scheduled in other ways have to wait for their turn. This is what causes freezing: if a script takes too long to run then the event handlers will not be able to function and it will freeze. However, some programming environments do allow multiple threads of execution to run at the same time. This can make a program faster, but also it makes it more difficult.

JavaScript makes things more simple by only doing one thing at a time. Now saw you really wanted something in the background that took forever to run and you obviously do not want it to freeze, there is a thing called web workers that is provided by the browser. A worker is an isolated JavaScript environment that runs alongside the main program for a document and can communicate with it only by sending and receiving messages.

This is what we would do

var squareWorker = new Worker("code/squareworker.js");
squareWorker.addEventListener("message", function(event) {
  console.log("The worker responded:", event.data);
});
squareWorker.postMessage(10);
squareWorker.postMessage(24);

Setting timers

Remember the requestAnimationFrame we saw? The setTimeout function is very similar. It schedules another function to be called later. But instead of calling the function at the next redraw, it waits for a given amount of milliseconds.

Let's turn a page from blue to yellow after two seconds:

<script>
  document.body.style.background = "blue";
  setTimeout(function() {
    document.body.style.background = "yellow";
  }, 2000);
</script>

Now say we do not like the effect so we want to cancel it:

var bombTimer = setTimeout(function() {
  console.log("BOOM!");
}, 500);

if (Math.random() < 0.5) { // 50% chance
  console.log("Defused.");
  clearTimeout(bombTimer);
}

A similar set of functions, setInterval and clearInterval are used to set timers that should repeat every X milliseconds.

var ticks = 0;
var clock = setInterval(function() {
  console.log("tick", ticks++);
  if (ticks == 10) {
    clearInterval(clock);
    console.log("stop.");
  }
}, 200);

Debouncing

Most of the events fire up quickly but we do need to be careful not to do anything too time-consuming otherwise the document will start to run slow.

If you do need to do something that takes time you can use a debounce the event. To do so you use setTimeOut

In the first example, we want to do something when the user has typed something, but we don’t want to do it immediately for every key event. When they are typing quickly, we just want to wait until a pause occurs.

<textarea>Type something here...</textarea>
<script>
  var textarea = document.querySelector("textarea");
  var timeout;
  textarea.addEventListener("keydown", function() {
    clearTimeout(timeout);
    timeout = setTimeout(function() {
      console.log("You stopped typing.");
    }, 500);
  });
</script>

Giving an undefined value to clearTimeOut or calling it on a timeout that has already fired has no effect so we can just call it on everything.

Now say we want to space reponses to at least a certain amount of time, but want to fire them during a series of events.

We could do this:

<script>
  function displayCoords(event) {
    document.body.textContent =
      "Mouse at " + event.pageX + ", " + event.pageY;
  }

  var scheduled = false, lastEvent;
  addEventListener("mousemove", function(event) {
    lastEvent = event;
    if (!scheduled) {
      scheduled = true;
      setTimeout(function() {
        scheduled = false;
        displayCoords(lastEvent);
      }, 250);
    }
  });
</script>

Time to do the exercises from Chapter 14

Day 31. Project 3: A Platform Game

With this project we will learn how to create a game. I used to be a big fan of computer games (what happened? I just do not have the time anymore 🙁 ) so lets get going!

The Game
We will be building a game like a bit like the one built by Thomas Palef:
build-a-game

The dark grey box is the player, who has to collect the yellow boxes and not touch the red boxes. A level is completed when all the coins are collected from that level.

The player can move around by using the left/right arrows and the up arrow to jump. While jumping you can change direction in midair. Each field on the grid is either empty, solid or lava (red). The positions of these elements are not constrained to the grid—their coordinates may be fractional, allowing smooth motion.

The technology

We will use the browser DOM to display the game, and we’ll read user input by handling key events. So it's a good recap of the previous posts.

To be able to create the coloured boxes we create DOM elements and use styling to give them a background color, size, and position. We can represent the background as a table as the squares on the grid do not change. The free moving elements can be built on top of that should be given the attribute position absolute.

The game consists of a fixed background, laid out like a grid, with the moving elements overlaid on that background.

Efficiency is important and although the DOM was not designed for high-performance graphics it is actually pretty decent.

Levels

Previously we used arrays of strings to describe a two-dimensional grid, we will do the same here so that we can design levels without having to build a level editor.

A simple level would look like this:

var simpleLevelPlan = [
  "                      ",
  "                      ",
  "  x              = x  ",
  "  x         o o    x  ",
  "  x @      xxxxx   x  ",
  "  xxxxx            x  ",
  "      x!!!!!!!!!!!!x  ",
  "      xxxxxxxxxxxxxx  ",
  "                      "
];
x // stand for walls
  // space characters for empty space
! // fixed lava tiles
@ // where the player stands
o // are the coins
= // stands for a block of lava that moves back and forth horizontally
| // will stand for vertically moving blobs of lava
v // will stand for dripping lava

Note that the grid for these positions will be set to contain empty space, and another data structure is used to track the position of such moving elements.

Remember: The game consists of multiple levels that the player must complete. A level is completed when all coins have been collected. If the player touches lava, the current level is restored to its starting position, and the player may try again.

Reading a level

The following constructor builds a level object:

function Level(plan) {
  this.width = plan[0].length;
  this.height = plan.length;
  this.grid = [];
  this.actors = [];

  for (var y = 0; y < this.height; y++) {
    var line = plan[y], gridLine = [];
    for (var x = 0; x < this.width; x++) {
      var ch = line[x], fieldType = null;
      var Actor = actorChars[ch];
      if (Actor)
        this.actors.push(new Actor(new Vector(x, y), ch));
      else if (ch == "x")
        fieldType = "wall";
      else if (ch == "!")
        fieldType = "lava";
      gridLine.push(fieldType);
    }
    this.grid.push(gridLine);
  }

  this.player = this.actors.filter(function(actor) {
    return actor.type == "player";
  })[0];
  this.status = this.finishDelay = null;
}

To keep things simple this code does not check for malformed input.
A level stores its width and height, along with two arrays:
1 for the grid
1 for the "actors", the dynamic elements

he grid is represented as an array of arrays, where each of the inner arrays represents a horizontal line and each square contains either null, for empty squares, or a string indicating the type of the square "wall" or "lava".

The actors array holds objects that track the current position and state of the dynamic elements in the level. Each of these is expected to have a pos property that gives its position (the coordinates of its top-left corner):
A size property that gives its size.
A type property that holds a string identifying the element ("lava", "coin", or "player").

Once we have built the grid we use a filter method to find the player actor object, which we store in a property of the level. The status property is to know whether the player has won or lost. When this happens, finishDelay is used to keep the level active for a short period of time so that a simple animation can be shown.

Level.prototype.isFinished = function() {
  return this.status != null && this.finishDelay < 0;
};

Actors

We will use the Vector type to store the position and size of an actor.

function Vector(x, y) {
  this.x = x; this.y = y;
}
Vector.prototype.plus = function(other) {
  return new Vector(this.x + other.x, this.y + other.y);
};
Vector.prototype.times = function(factor) {
  return new Vector(this.x * factor, this.y * factor);
};

The times method scales a vector by a given amount. It will be used to multiply a speed vector by a time interval to get the distance traveled during that time.

The actorChars object was used by the Level constructor to associate characters with constructor functions. The object looks like this:

var actorChars = {
  "@": Player,
  "o": Coin,
  "=": Lava, "|": Lava, "v": Lava
};

The Level constructor passes the actor’s source character as the second argument to the constructor, and the Lava constructor uses that to adjust its behaviour.

With the following constructor we build the player type. It has a speed property so that we can store its current speed which will help simulate momentum and gravity

function Player(pos) {
  this.pos = pos.plus(new Vector(0, -0.5));
  this.size = new Vector(0.8, 1.5);
  this.speed = new Vector(0, 0);
}
Player.prototype.type = "player";

A player is one and a half square high, so it's initial position should be two squares high so that its bottom aligns with the bottom of the square it appeared in.

To construct a dynamic Lava object we need to initialise the object differently depending on the character it is based on. Dynamic lava moves at a given speed and stops when it hits an obstacle. If it has a repeatPos property it will jump back to its start point to create the dripping effect. Otherwise, it will invert its speed and continue in the other direction to create a bouncing effect.

For now we will set up the properties, we will make it move later.

function Lava(pos, ch) {
  this.pos = pos;
  this.size = new Vector(1, 1);
  if (ch == "=") {
    this.speed = new Vector(2, 0);
  } else if (ch == "|") {
    this.speed = new Vector(0, 2);
  } else if (ch == "v") {
    this.speed = new Vector(0, 3);
    this.repeatPos = pos;
  }
}
Lava.prototype.type = "lava";

Let's give the Coins a bit of a wobble to make sure they stand out:

function Coin(pos) {
  this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1));
  this.size = new Vector(0.6, 0.6);
  this.wobble = Math.random() * Math.PI * 2;
}
Coin.prototype.type = "coin";

Math.sin gives us the y-coordinate of a point on a circle. That coordinate goes back and forth in a smooth wave form as we move along the circle, which makes the sine function useful for modeling a wavy motion.

To make sure that the coins do not move at simultaneously we add the Math.random

var simpleLevel = new Level(simpleLevelPlan);
console.log(simpleLevel.width, "by", simpleLevel.height);
//> 22 by 9

Encapsulation as a burden

Only one thing will be encapsulated in this chapter, and that is the drawing subsystem. The reason for this is that we will display the same game in a different way after we have built it this way. By putting the drawing behind an interface, we can simply load the same game program there and plug in a new display module.

Drawing

So lets get to it. To do the encapsulation of the drawing code we need to define a display object, which display a given level. The display type we define is called DOMDisplay because it uses simple DOM elements to show the level.

We will be using a stylesheet for the colours. The following helper function provides a short way to create an element and give it a class:

function elt(name, className) {
  var elt = document.createElement(name);
  if (className) elt.className = className;
  return elt;
}

A display is created by giving it a parent element to which it should append itself and a level object.

function DOMDisplay(parent, level) {
  this.wrap = parent.appendChild(elt("div", "game"));
  this.level = level;

  this.wrap.appendChild(this.drawBackground());
  this.actorLayer = null;
  this.drawFrame();
}

We used the fact that appendChild returns the appended element to create the wrapper element and store it in the wrap property in a single statement.

As the level's background never changes, it is drawn once. The actors are drawn everytime the the display is updated. The actorLayer property will be used by drawFrame to track the element that holds the actors so that they can be easily removed and replaced.

A size or distance that is 1 is relative to our grid so it would be 1 grid unit. We define the scale size at 20 because if it were just 1 pixel it would be awfully small.

var scale = 20;

DOMDisplay.prototype.drawBackground = function() {
  var table = elt("table", "background");
  table.style.width = this.level.width * scale + "px";
  this.level.grid.forEach(function(row) {
    var rowElt = table.appendChild(elt("tr"));
    rowElt.style.height = scale + "px";
    row.forEach(function(type) {
      rowElt.appendChild(elt("td", type));
    });
  });
  return table;
};

The background is drawn as a table element. This nicely corresponds to the structure of the grid property in the level—each row of the grid is turned into a table row (tr element). The strings in the grid are used as class names for the table cell (td) elements.

Some CSS will help us make the table look like the background we want:

.background    { background: rgb(52, 166, 251);
                 table-layout: fixed;
                 border-spacing: 0;              }
.background td { padding: 0;                     }
.lava          { background: rgb(255, 100, 100); }
.wall          { background: white;              }

To make sure we overwrite the default behaviour we need to overrule them.

Lets look at what we did there:

.background // we changed the background colour using rbg (red, green, blue)
.background td // removing any padding
.lava //making the lava red
.wall //making the wall white 

We draw each actor by creating a DOM element for it and setting that element’s position and size based on the actor’s properties. Then we need to multiply the values so that they go from game units to pixels.

DOMDisplay.prototype.drawActors = function() {
  var wrap = elt("div");
  this.level.actors.forEach(function(actor) {
    var rect = wrap.appendChild(elt("div",
                                    "actor " + actor.type));
    rect.style.width = actor.size.x * scale + "px";
    rect.style.height = actor.size.y * scale + "px";
    rect.style.left = actor.pos.x * scale + "px";
    rect.style.top = actor.pos.y * scale + "px";
  });
  return wrap;
};

Let's define our actor, coin and player with CSS

.actor  { position: absolute;            }
.coin   { background: rgb(241, 229, 89); }
.player { background: rgb(64, 64, 64);   }

When it updates the display, the drawFrame method first removes the old actor graphics, if any, and then redraws them in their new positions.

DOMDisplay.prototype.drawFrame = function() {
  if (this.actorLayer)
    this.wrap.removeChild(this.actorLayer);
  this.actorLayer = this.wrap.appendChild(this.drawActors());
  this.wrap.className = "game " + (this.level.status || "");
  this.scrollPlayerIntoView();
};

We can style the player actor slightly differently when the game is won or lost by adding a CSS rule.

.lost .player {
  background: rgb(160, 64, 64);
}
.won .player {
  box-shadow: -4px -7px 8px white, 4px -7px 8px white;
}

So if the player touches the lava, it turns red. When the last coin has been collected, we use two blurred white box shadows, one to the top left and one to the top right, to create a white halo effect.

We needed to make sure that levels fit into the viewport. That is why we called the method scrollPlayerIntoView.

Next we give the games wrapping DOM a maximum size and make sure that anything sticking outside of the box is not visible. We also give it a relative position.

.game {
  overflow: hidden;
  max-width: 600px;
  max-height: 450px;
  position: relative;
}

In the scrollPlayerIntoView method we find the player’s position and update the wrapping element’s scroll position. We can change the scroll position in case the player is too close to the edge, we do this by using scrollLeft and scrollTop

DOMDisplay.prototype.scrollPlayerIntoView = function() {
  var width = this.wrap.clientWidth;
  var height = this.wrap.clientHeight;
  var margin = width / 3;

  // The viewport
  var left = this.wrap.scrollLeft, right = left + width;
  var top = this.wrap.scrollTop, bottom = top + height;

  var player = this.level.player;
  var center = player.pos.plus(player.size.times(0.5))
                 .times(scale);

  if (center.x < left + margin)
    this.wrap.scrollLeft = center.x - margin;
  else if (center.x > right - margin)
    this.wrap.scrollLeft = center.x + margin - width;
  if (center.y < top + margin)
    this.wrap.scrollTop = center.y - margin;
  else if (center.y > bottom - margin)
    this.wrap.scrollTop = center.y + margin - height;
};

Look at our player and how it's center is found, see how the computations with objects are wrriten in a readable way via the vector method. To find the actor’s center, we add its position (its top-left corner) and half its size, then we need to make it pixels by multiplying the resulting vector by our display size.

Then we make sure our player does not leave the box view and it is ok to write nonsense scroll coordinates because the DOM will consider a -10 to be 0.

Lastly, we need a way to clear a displayed level, to be used when the game moves to the next level or resets a level.

DOMDisplay.prototype.clear = function() {
  this.wrap.parentNode.removeChild(this.wrap);
};

Now we can display our tiny level

<link rel="stylesheet" href="css/game.css">

<script>
  var simpleLevel = new Level(simpleLevelPlan);
  var display = new DOMDisplay(document.body, simpleLevel);
</script>

Day 31. Project 3: A Platform Game Part 2

Motion and Collision

Now we can add motion. To do so we split time into small steps and, for each step, move the actors by a distance corresponding to their speed (distance moved per second) multiplied by the size of the time step (in seconds). This part is pretty straightforward.

Now we get to the difficult part. Which is dealing with the interactions between the elements. Which is when the player hits a wall or lava it should not simply walk through it. So for walls the motion has to be stopped and for coins, collected.

We need to test whether the motion would take it inside of a nonempty part of the background. If it does, we simply cancel the motion altogether.

To do so and keep it simple we need to make small steps so that it will not look like the player is stopping way before it hits the object.

This method tells us whether a rectangle (specified by a position and a size) overlaps with any nonempty space on the background grid:

Level.prototype.obstacleAt = function(pos, size) {
  var xStart = Math.floor(pos.x);
  var xEnd = Math.ceil(pos.x + size.x);
  var yStart = Math.floor(pos.y);
  var yEnd = Math.ceil(pos.y + size.y);

  if (xStart < 0 || xEnd > this.width || yStart < 0)
    return "wall";
  if (yEnd > this.height)
    return "lava";
  for (var y = yStart; y < yEnd; y++) {
    for (var x = xStart; x < xEnd; x++) {
      var fieldType = this.grid[y][x];
      if (fieldType) return fieldType;
    }
  }
};

This method computes the set of grid squares that the body overlaps with by using Math.floor and Math.ceil on the body’s coordinates.

To ensure that the player dies when falling out of the world we will return wall for the top and sides and lava for the bottom. When the body is fully inside the grid, we loop over the block of grid squares found by rounding the coordinates and return the content of the first nonempty square we find.

Collisions between the actor and the objects are returned after the player moves.

This method scans the array of actors, looking for an actor that overlaps the one given as an argument:

Level.prototype.actorAt = function(actor) {
  for (var i = 0; i < this.actors.length; i++) {
    var other = this.actors[i];
    if (other != actor &&
        actor.pos.x + actor.size.x > other.pos.x &&
        actor.pos.x < other.pos.x + other.size.x &&
        actor.pos.y + actor.size.y > other.pos.y &&
        actor.pos.y < other.pos.y + other.size.y)
      return other;
  }
};

Actors and Actions

The animate method on the Level type gives all actors in the level a chance to move. Its step argument is the time step in seconds. The keys object contains information about the arrow keys the player has pressed.

var maxStep = 0.05;

Level.prototype.animate = function(step, keys) {
  if (this.status != null)
    this.finishDelay -= step;

  while (step > 0) {
    var thisStep = Math.min(step, maxStep);
    this.actors.forEach(function(actor) {
      actor.act(thisStep, this, keys);
    }, this);
    step -= thisStep;
  }
};

When the level's status property returns anything other than null, in other words when the player has lost or won, we should countdown the finishDelay property in order to indicate when we should stop showing the level.

The While loops allows us to cut the process into small steps to achieve what we said earlier, so that no step any larger than maxStep is taken.

An act method takes as arguments the time step, the level object, and the keys object.

Take a look at this one:

Lava.prototype.act = function(step, level) {
  var newPos = this.pos.plus(this.speed.times(step));
  if (!level.obstacleAt(newPos, this.size))
    this.pos = newPos;
  else if (this.repeatPos)
    this.pos = this.repeatPos;
  else
    this.speed = this.speed.times(-1);
};

It computes a new position by adding the product of the time step and its current speed to its old position.

So if nothing is blocking it then it will move to its new position. If there is something in the way it depends on what type of lava it is. If it's the dripping type it will move back up and start dripping again.

Guess what the act method does on coins, that's right it makes them wobble. We do not need to worry about collisions with coins because they will be defined on the players method.

var wobbleSpeed = 8, wobbleDist = 0.07;

Coin.prototype.act = function(step) {
  this.wobble += step * wobbleSpeed;
  var wobblePos = Math.sin(this.wobble) * wobbleDist;
  this.pos = this.basePos.plus(new Vector(0, wobblePos));
};

The wobble property is updated to track time and then used as an argument to Math.sin to create a wave, which is used to compute a new position.

Now the player

var playerXSpeed = 7;

Player.prototype.moveX = function(step, level, keys) {
  this.speed.x = 0;
  if (keys.left) this.speed.x -= playerXSpeed;
  if (keys.right) this.speed.x += playerXSpeed;

  var motion = new Vector(this.speed.x * step, 0);
  var newPos = this.pos.plus(motion);
  var obstacle = level.obstacleAt(newPos, this.size);
  if (obstacle)
    level.playerTouched(obstacle);
  else
    this.pos = newPos;
};

We need to handle the player per axis because if it hits the floor it should not stop it from moving horizontally. The horizontal motion is computed based on the state of the left and right arrow keys. The playerTouched method is called when the player hits or touches something like lava or coins.

Vertical motion works in a similar way but has to simulate jumping and gravity.

var gravity = 30;
var jumpSpeed = 17;

Player.prototype.moveY = function(step, level, keys) {
  this.speed.y += step * gravity;
  var motion = new Vector(0, this.speed.y * step);
  var newPos = this.pos.plus(motion);
  var obstacle = level.obstacleAt(newPos, this.size);
  if (obstacle) {
    level.playerTouched(obstacle);
    if (keys.up && this.speed.y > 0)
      this.speed.y = -jumpSpeed;
    else
      this.speed.y = 0;
  } else {
    this.pos = newPos;
  }
};

The combination we see here is achieve by Marijns test and errors. That's why we are using it. If we were to build it from scratch we would have to do this part of testing ourselves.

Next, we check for obstacles again. If we hit an obstacle, there are two possible outcomes. When the up arrow is pressed and we are moving down (meaning the thing we hit is below us), the speed is set to a relatively large, negative value. This causes the player to jump. If that is not the case, we simply bumped into something, and the speed is reset to zero.

The actual act method looks like this:

Player.prototype.act = function(step, level, keys) {
  this.moveX(step, level, keys);
  this.moveY(step, level, keys);

  var otherActor = level.actorAt(this);
  if (otherActor)
    level.playerTouched(otherActor.type, otherActor);

  // Losing animation
  if (level.status == "lost") {
    this.pos.y += step;
    this.size.y -= step;
  }
};

Once the player has moved and touches something it will call the playerTouched method again. Now it passes the actor as the second argument because if it touches a coin it first needs to know which coin.

Now lets make the actor shrink when it dies:

Level.prototype.playerTouched = function(type, actor) {
  if (type == "lava" && this.status == null) {
    this.status = "lost";
    this.finishDelay = 1;
  } else if (type == "coin") {
    this.actors = this.actors.filter(function(other) {
      return other != actor;
    });
    if (!this.actors.some(function(actor) {
      return actor.type == "coin";
    })) {
      this.status = "won";
      this.finishDelay = 1;
    }
  }
};

When lava is touched, the game’s status is set to "lost". When a coin is touched, that coin is removed from the array of actors, and if it was the last one, the game’s status is set to "won".

Tracking keys

While we are playing we want the keys to take effect while they are being pressed. So lets set up a key handler that stores the current state of the arrow keys. We also need to prevent them from scrolling the page by deactivating the default.

Note how the same handler function is used for both event types.

var arrowCodes = {37: "left", 38: "up", 39: "right"};

function trackKeys(codes) {
  var pressed = Object.create(null);
  function handler(event) {
    if (codes.hasOwnProperty(event.keyCode)) {
      var down = event.type == "keydown";
      pressed[codes[event.keyCode]] = down;
      event.preventDefault();
    }
  }
  addEventListener("keydown", handler);
  addEventListener("keyup", handler);
  return pressed;
}

Running the Game
Let’s define a helper function that wraps everything in an interface and allows us to simply call runAnimation, giving it a function that expects a time difference as an argument and draws a single frame.

When the frame function returns the value false, the animation stops.

function runAnimation(frameFunc) {
  var lastTime = null;
  function frame(time) {
    var stop = false;
    if (lastTime != null) {
      var timeStep = Math.min(time - lastTime, 100) / 1000;
      stop = frameFunc(timeStep) === false;
    }
    lastTime = time;
    if (!stop)
      requestAnimationFrame(frame);
  }
  requestAnimationFrame(frame);
}

The runLevel function takes a Level object, a constructor for a display, and, optionally, a function. It displays the level (in document.body) and lets the user play through it. When the level is finished (lost or won), runLevel clears the display, stops the animation, and, if an andThen function was given, calls that function with the level’s status.

var arrows = trackKeys(arrowCodes);

function runLevel(level, Display, andThen) {
  var display = new Display(document.body, level);
  runAnimation(function(step) {
    level.animate(step, arrows);
    display.drawFrame(step);
    if (level.isFinished()) {
      display.clear();
      if (andThen)
        andThen(level.status);
      return false;
    }
  });
}

A game is a sequence of levels. Whenever the player dies, the current level is restarted. When a level is completed, we move on to the next level:

function runGame(plans, Display) {
  function startLevel(n) {
    runLevel(new Level(plans[n]), Display, function(status) {
      if (status == "lost")
        startLevel(n);
      else if (n < plans.length - 1)
        startLevel(n + 1);
      else
        console.log("You win!");
    });
  }
  startLevel(0);
}

This is to schedule actions. Wrapping these actions in functions gives us a way to store them as a value so that they can be called at the right moment.

And that's that for today. You may start the exercises to Chapter 15!

Day 33. Drawing on Canvas

As I have a a background in Fine Art, the word canvas sounds very familiar, but something tells me that we are not going to be looking at the same canvas 😉

There are several ways display graphics on a browser. Now say we wanted to draw a line between arbitrary points with HTML, that would become extremely awkward. To solve this we could use a SVG (Scalable Vector Graphics) instead of HTML or we could use canvas.

SVG

Let's take a quick look at how a SVG works.

This is a simple HTML snippet with a SVG image:

<p>Normal HTML here.</p>
<svg xmlns="http://www.w3.org/2000/svg">
  <circle r="50" cx="50" cy="50" fill="red"/>
  <rect x="120" y="5" width="90" height="90"
        stroke="blue" fill="none"/>
</svg>

The xmlns attribute changes an element (and its children) to a different XML namespace. This namespace which is identified by the URL, specifies what language we are using. The circle and rect exist with SVG but not with HTML. They are used to draw shapes. These tags create DOM elements, just like HTML tags.

Take a look:

var circle = document.querySelector("circle");
circle.setAttribute("fill", "cyan");

The canvas element

Canvas graphics can be drawn onto a canvas element. To determine it's size we give it a width and height in pixels.
A new canvas is transparent and empty, waiting to be drawn onto. The canvas tag is intended to support different styles of drawing.

To be able to start drawing we need to create a context, which is an object whose methods is provide a drawing interface. There are currently two main drawing styles: "2d" and "webgl" (3d).

We will stick to 2d for now 🙂

To create the context we call the method getContext on the canvas element:

<p>Before canvas.</p>
<canvas width="120" height="60"></canvas>
<p>After canvas.</p>
<script>
  var canvas = document.querySelector("canvas");
  var context = canvas.getContext("2d");
  context.fillStyle = "red";
  context.fillRect(10, 10, 100, 50);
</script>

After creating the context we draw a red rectangle 100 pixels wide and 50 pixels high, with its top-left corner at coordinates (10,10). Meaning that is 10 pixels from the top left corner.

Filling and stroking

Filling: means to color the object (fill the object with colour).
Stroking: A line is drawn along it's edge.
fillRect will fill a rectangle and strokeRect will draw the outline.

To define the thickness of the outline we will need to add properties to it.

fillStyle allows us to change the way the shape is filled. It can be set to a string that determines a colour. The same goes for strokeStyle. The lineWidth property allows us to determine the width of the outline.

Here's an example:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.strokeStyle = "blue";
  cx.strokeRect(5, 5, 50, 50);
  cx.lineWidth = 5;
  cx.strokeRect(135, 5, 50, 50);
</script>

This code draws two blue squares using a thicker line for the second one. The default values for height is 150px and width 300px.

Paths

A path is a sequence of lines, to describe a path it is done entirely through side effects. Paths are not values that can be stored and passed around. Instead, if you want to do something with a path, you make a sequence of method calls to describe its shape.

Take a look:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  for (var y = 10; y < 100; y += 10) {
    cx.moveTo(10, y);
    cx.lineTo(90, y);
  }
  cx.stroke();
</script>

This example creates a path with a number of horizontal line segments and then strokes it using the stroke method. Each segment created with lineTo starts at the path’s current position. That position is usually the end of the last segment, unless moveTo was called. In that case, the next segment would start at the position passed to moveTo.

When we use the fill method on a path each shape is filled individually. It can contain several shapes but need to be closed (it ends where it starts). If it is not closed it will close it for you by joining a line.

Look at the next example, we are drawing a triangle but with only two sides, the third is implied.

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  cx.moveTo(50, 10);
  cx.lineTo(10, 70);
  cx.lineTo(90, 70);
  cx.fill();
</script>

To close it ourselves we would use the closePath method.

Curves

A path can also have curved lines, these are a bit harder to draw.

The quadraticCurveTo method draws a curve to a given point. To determine the curvature of a line we need to give the method a control point and a destination point.

Let's try to make this more clear:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  cx.moveTo(10, 90);
  // control=(60,10) goal=(90,90)
  cx.quadraticCurveTo(60, 10, 90, 90);
  cx.lineTo(60, 10);
  cx.closePath();
  cx.stroke();
</script>

So we draw a quadratic curve from left to right and it's control point is (60,10) and then draw two line segments going through that control point and back to the start of the line.

It should look like this.

To add another control point we can use the bezierCurveTo method.

Take a look

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  cx.moveTo(10, 90);
  // control1=(10,10) control2=(90,10) goal=(50,90)
  cx.bezierCurveTo(10, 10, 90, 10, 50, 90);
  cx.lineTo(90, 10);
  cx.lineTo(10, 10);
  cx.closePath();
  cx.stroke();
</script>

Such curves can be hard to work with—it’s not always clear how to find the control points that provide the shape you are looking for. Sometimes you can compute them, and sometimes you’ll just have to find a suitable value by trial and error.

Arcs: fragments of a circle are easier to deal with. The arcTo method takes minimum 5 arguments. The first four are similar to those of the quadraticCurveTo method. The first pair provides a sort of control point, and the second pair gives the line’s destination. The fifth argument provides the radius of the arc.

Let's take a look:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  cx.moveTo(10, 10);
  // control=(90,10) goal=(90,90) radius=20
  cx.arcTo(90, 10, 90, 90, 20);
  cx.moveTo(10, 10);
  // control=(90,10) goal=(90,90) radius=80
  cx.arcTo(90, 10, 90, 90, 80);
  cx.stroke();
</script>

Look at what happens here
See how the arcTo method won’t draw the line from the end of the rounded part to the goal position, we need to call the lineTo method with the same goal coordinates to add that part of the line.

To draw a circle, you could use four calls to arcTo (each turning 90 degrees). But the arc method provides a simpler way. It takes a pair of coordinates for the arc’s center, a radius, and then a start and end angle.

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.beginPath();
  // center=(50,50) radius=40 angle=0 to 7
  cx.arc(50, 50, 40, 0, 7);
  // center=(150,50) radius=40 angle=0 to ½π
  cx.arc(150, 50, 40, 0, 0.5 * Math.PI);
  cx.stroke();
</script>

Which results in this.

Drawing a pie chart

Say we need to draw a pie chart of these boring survery results... ...

var results = [
  {name: "Satisfied", count: 1043, color: "lightblue"},
  {name: "Neutral", count: 563, color: "lightgreen"},
  {name: "Unsatisfied", count: 510, color: "pink"},
  {name: "No comment", count: 175, color: "silver"}
];

To draw a pie chart, we draw a number of pie slices, each made up of an arc and a pair of lines to the center of that arc.

We can compute the angle taken up by each arc by dividing a full circle (2π) by the total number of responses and then multiplying that number (the angle per response) by the number of people who picked a given choice.

<canvas width="200" height="200"></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  var total = results.reduce(function(sum, choice) {
    return sum + choice.count;
  }, 0);
  // Start at the top
  var currentAngle = -0.5 * Math.PI;
  results.forEach(function(result) {
    var sliceAngle = (result.count / total) * 2 * Math.PI;
    cx.beginPath();
    // center=100,100, radius=100
    // from current angle, clockwise by slice's angle
    cx.arc(100, 100, 100,
           currentAngle, currentAngle + sliceAngle);
    currentAngle += sliceAngle;
    cx.lineTo(100, 100);
    cx.fillStyle = result.color;
    cx.fill();
  });
</script>

Result
Let's add some text...

Text

Just like fillrect we have fillText and strokeText. strokeText is for outlining letters and fillText for colouring the text. It will fill the given text with the current fillColor.

var arrows = trackKeys(arrowCodes);

function runLevel(level, Display, andThen) {
  var display = new Display(document.body, level);
  runAnimation(function(step) {
    level.animate(step, arrows);
    display.drawFrame(step);
    if (level.isFinished()) {
      display.clear();
      if (andThen)
        andThen(level.status);
      return false;
    }
  });
}

We can specify the size, style, and font of the text with the font property. This example just gives a font size and family name. You can add italic or bold to the start of the string to select a style. We can change the horizontal position by setting the textAlign property to "end" or "center" and the vertical position by setting textBaseline to "top", "middle", or "bottom".

Tomorrow we will see about images and transformations in canvas!

Day 34. Drawing on Canvas, images and more

Images

In computer graphics we have bitmap graphics and vector graphics. Vector graphics are what we have seen up until now. Bitmap graphics work with pixel data (coloured dots).

We can draw pixel image data on a canvas by using the drawImage method. This data can come from an img element or another canvas, but it does not have to be visible on the actual document.

The next example created a detached img element and loads an image file into it. However, it cannot start drawing the image immediately because the browser may not have fetched it. So for this not to happen we need to register a load handler.

Then do the drawing once it has loaded

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  var img = document.createElement("img");
  img.src = "img/hat.png";
  img.addEventListener("load", function() {
    for (var x = 10; x < 200; x += 30)
      cx.drawImage(img, x, 10);
  });
</script>

To give the image a different size to its original one, you can use the width and height arguments.
When we give drawImage nine arguments, it will only draw a piece of the image. The second through fifth arguments indicate the rectangle (x, y, width, and height) in the source image that should be copied, and the sixth to ninth arguments give the rectangle (on the canvas) into which it should be copied.

This can be used to pack multiple sprites (image elements) into a single image file and then draw only the part you need. For example, we have this picture containing a game character in multiple poses:

player_big

By alternating which pose we draw, we can show an animation that looks like a walking character.

Lets take a look:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  var img = document.createElement("img");
  img.src = "img/player.png";
  var spriteW = 24, spriteH = 30;
  img.addEventListener("load", function() {
    var cycle = 0;
    setInterval(function() {
      cx.clearRect(0, 0, spriteW, spriteH);
      cx.drawImage(img,
                   // source rectangle
                   cycle * spriteW, 0, spriteW, spriteH,
                   // destination rectangle
                   0,               0, spriteW, spriteH);
      cycle = (cycle + 1) % 8;
    }, 120);
  });
</script>

clearRect makes a rectangle transparent and the cycle variable tracks our position in the animation.

Transformation

Now say we wanted to make the little man walk the other way, we can do this by instructing the canvas to do so.
We can use scale. scale will make everything about the image to be stretched or squeezed together and if we do it by a negative amount it will flip the picture.

This method has two parameters, horizontal and vertical.

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  cx.scale(3, .5);
  cx.beginPath();
  cx.arc(50, 50, 40, 0, 7);
  cx.lineWidth = 3;
  cx.stroke();
</script>

When a horizontal scaling of -1 is applied, a shape drawn at x position 100 will end up at what used to be position -100. So to turn a picture around, we can’t simply add cx.scale(-1, 1) before the call to drawImage since that would move our picture outside of the canvas, where it won’t be visible.
You could adjust them to -50 instead of 0. Another solution would be to adjust the axis around which the scaling happens.

You can rotate shapes with the rotate method and move them with the translate method. But be aware that these are done relatively. So they happen relative to the previous transformation. This is known as "stack"

So if we translate by 10 horizontal pixels twice, everything will be drawn 20 pixels to the right.

To achieve what we wanted to, flipping the image, we can do the following:

<canvas></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  var img = document.createElement("img");
  img.src = "img/player.png";
  var spriteW = 24, spriteH = 30;
  img.addEventListener("load", function() {
    flipHorizontally(cx, 100 + spriteW / 2);
    cx.drawImage(img, 0, 0, spriteW, spriteH,
                 100, 0, spriteW, spriteH);
  });
</script>

We move the y-axis to where we want our mirror to be, apply the mirroring, and finally move the y-axis back to its proper place in the mirrored universe.

Storing and clearing transformations

If we were to draw something after doing a transformation then that transformation would be applied to that drawing. To stop this we would save the current transformation and we can always restore it when necessary.

The save and restore method will aloow us to do this on the 2d canvas.
save the current state is pushed onto the stack
restore the state on top of the stack is taken off and used as the context’s current transformation.

Let's take a closer look:

<canvas width="600" height="300"></canvas>
<script>
  var cx = document.querySelector("canvas").getContext("2d");
  function branch(length, angle, scale) {
    cx.fillRect(0, 0, 1, length);
    if (length < 8) return;
    cx.save();
    cx.translate(0, length);
    cx.rotate(-angle);
    branch(length * scale, angle, scale);
    cx.rotate(2 * angle);
    branch(length * scale, angle, scale);
    cx.restore();
  }
  cx.translate(300, 0);
  branch(60, 0.5, 0.8);
</script>

If the calls to save and restore were not there, the second recursive call to branch would end up with the position and rotation created by the first call.

Back to the game

Now that we have learnt about canvas we can make our game from Project 3 even better.

We will define an object type CanvasDisplay and the methods drawFrame and clear. Which tracks its own viewport, which tells us what part of the level we are currently looking at

function CanvasDisplay(parent, level) {
  this.canvas = document.createElement("canvas");
  this.canvas.width = Math.min(600, level.width * scale);
  this.canvas.height = Math.min(450, level.height * scale);
  parent.appendChild(this.canvas);
  this.cx = this.canvas.getContext("2d");

  this.level = level;
  this.animationTime = 0;
  this.flipPlayer = false;

  this.viewport = {
    left: 0,
    top: 0,
    width: this.canvas.width / scale,
    height: this.canvas.height / scale
  };

  this.drawFrame(0);
}

CanvasDisplay.prototype.clear = function() {
  this.canvas.parentNode.removeChild(this.canvas);
};

The drawFrame function uses the counter to track time so that it can switch between animation frames based on the current time. We will make it update the viewport for the current player position, fills the whole canvas with a background color, and draws the background and actors onto that.

CanvasDisplay.prototype.drawFrame = function(step) {
  this.animationTime += step;

  this.updateViewport();
  this.clearDisplay();
  this.drawBackground();
  this.drawActors();
};

To update the canvas display we need to clear it and redraw the scene. The updateViewport method is to check whether the player is too close to the edge of the screen and moves the viewport when this is the case.

CanvasDisplay.prototype.updateViewport = function() {
  var view = this.viewport, margin = view.width / 3;
  var player = this.level.player;
  var center = player.pos.plus(player.size.times(0.5));

  if (center.x < view.left + margin)
    view.left = Math.max(center.x - margin, 0);
  else if (center.x > view.left + view.width - margin)
    view.left = Math.min(center.x + margin - view.width,
                         this.level.width - view.width);
  if (center.y < view.top + margin)
    view.top = Math.max(center.y - margin, 0);
  else if (center.y > view.top + view.height - margin)
    view.top = Math.min(center.y + margin - view.height,
                        this.level.height - view.height);
};

The calls to Math.max and Math.min ensure that the viewport does not end up showing space outside of the level. When we clear the display we will use a bright colour if the player has won and a darker one if he/she has lost.

CanvasDisplay.prototype.clearDisplay = function() {
  if (this.level.status == "won")
    this.cx.fillStyle = "rgb(68, 191, 255)";
  else if (this.level.status == "lost")
    this.cx.fillStyle = "rgb(44, 136, 214)";
  else
    this.cx.fillStyle = "rgb(52, 166, 251)";
  this.cx.fillRect(0, 0,
                   this.canvas.width, this.canvas.height);
};

To draw the background, we run through the tiles that are visible in the current viewport

var otherSprites = document.createElement("img");
otherSprites.src = "img/sprites.png";

CanvasDisplay.prototype.drawBackground = function() {
  var view = this.viewport;
  var xStart = Math.floor(view.left);
  var xEnd = Math.ceil(view.left + view.width);
  var yStart = Math.floor(view.top);
  var yEnd = Math.ceil(view.top + view.height);

  for (var y = yStart; y < yEnd; y++) {
    for (var x = xStart; x < xEnd; x++) {
      var tile = this.level.grid[y][x];
      if (tile == null) continue;
      var screenX = (x - view.left) * scale;
      var screenY = (y - view.top) * scale;
      var tileX = tile == "lava" ? scale : 0;
      this.cx.drawImage(otherSprites,
                        tileX,         0, scale, scale,
                        screenX, screenY, scale, scale);
    }
  }
};

Tiles that are not empty (null) are drawn with drawImage. The otherSprites image contains the pictures used for elements other than the player. The walking character shown earlier will be used to represent the player. The code that draws it needs to pick the right sprite and direction based on the player’s current motion. The animationTime is measured in seconds.

var playerSprites = document.createElement("img");
playerSprites.src = "img/player.png";
var playerXOverlap = 4;

CanvasDisplay.prototype.drawPlayer = function(x, y, width,
                                              height) {
  var sprite = 8, player = this.level.player;
  width += playerXOverlap * 2;
  x -= playerXOverlap;
  if (player.speed.x != 0)
    this.flipPlayer = player.speed.x < 0;

  if (player.speed.y != 0)
    sprite = 9;
  else if (player.speed.x != 0)
    sprite = Math.floor(this.animationTime * 12) % 8;

  this.cx.save();
  if (this.flipPlayer)
    flipHorizontally(this.cx, x + width / 2);

  this.cx.drawImage(playerSprites,
                    sprite * width, 0, width, height,
                    x,              y, width, height);

  this.cx.restore();
};

The drawPlayer method is called by drawActors, which is responsible for drawing all the actors in the game.

CanvasDisplay.prototype.drawActors = function() {
  this.level.actors.forEach(function(actor) {
    var width = actor.size.x * scale;
    var height = actor.size.y * scale;
    var x = (actor.pos.x - this.viewport.left) * scale;
    var y = (actor.pos.y - this.viewport.top) * scale;
    if (actor.type == "player") {
      this.drawPlayer(x, y, width, height);
    } else {
      var tileX = (actor.type == "coin" ? 2 : 1) * scale;
      this.cx.drawImage(otherSprites,
                        tileX, 0, width, height,
                        x,     y, width, height);
    }
  }, this);
};

You may now run it

<body>
  <script>
    runGame(GAME_LEVELS, CanvasDisplay);
  </script>
</body>

Here is the game written out for you 🙂

Now the exercises of Chapter 16!!

Day 35. HTTP

We are going to take a look at how HTTP, JavaScript and the browser works more in detail.

The Protocol

If you go on http://www.rebelytics.com/hreflang-canonical/ it will first look up the address of the server associated with www.rebelytics.com and tries to open a TCP (transmission control protocol) connection to it on port 80 (this is the default port for HTTP).

If all works well the browser sends something along the lines of this:

GET /17_http.html HTTP/1.1
Host: eloquentjavascript.net
User-Agent: Your browser's name

And then the server will respond:

HTTP/1.1 200 OK
Content-Length: 65585
Content-Type: text/html
Last-Modified: Wed, 09 Apr 2014 10:48:09 GMT

<!doctype html>
... the rest of the document

The information sent by the client is a request and it start like this

GET /17_http.html HTTP/1.1

GET is a method which means that we want to get the specific resource.
Other methods are:
DELETE to delete a resource
PUT to replace a resource
POST to send information to a resource

But obviously the browser is not obliged to do every single request otherwise we could delete random websites.

The part after the method, so in this case GET is the path of the resource the request applies to. Normally it's a file on the server but it is not required to be. It can be anything that can be transferred as if it is a file.

After the path we can see HTTP/1.1, this is the version that the HTTP protocol is using.

As we saw in the servers response above it says HTTP/1.1 200 OK, the 200 is a status code and then in human language it's telling us that it is OK.

status codes
Those that start with a 2 indicate that the request succeeded.
Codes that start with a 3 indicate that the request is redirected to another URL.
Codes that start with a 4 indicate that the request went wrong (404 ring a bell?).
Codes that start with a 5 indicate that an error happened on a server and it's not the requests fault.

After the requests response there can be an unlimited amount of headers. They are formed as "name:value".

Like this:

Content-Length: 65585
Content-Type: text/html
Last-Modified: Wed, 09 Apr 2014 10:48:09 GMT

These specific headers tell us this size and type of the document and when it was last modified. The documents size is measured in bytes so this one is 65,585 bytes.

Normally a server or a client decides which headers are necessary but sometimes a header might be required. For example, the host header. Say we're on a hosting and there is multiple sites on there, the needs to be a way to allow the server to find the right client.

After the headers, both requests and responses may include a blank line followed by a body, which contains the data being sent.

Browsers and HTTP

So we saw that when we put a URL into the browser, it will make a request. When that HTML page references other files such as images and JavaScript, those are also fetched.

So that browsers can perform quickly they can fetch resources simultaneously and not have to fetch one after another.

Forms on a HTML page allow the user to fill in information and send it to the server. Here is an example of a form

<form method="GET" action="example/message.html">
  <p>Name: <input type="text" name="name"></p>
  <p>Message:<br><textarea name="message"></textarea></p>
  <p><button type="submit">Send</button></p>
</form>

This form has two fileds, a small one asking for the name and a big one letting the user leave a message. It also has a send button, which, if pressed the information in those fields will be encoded into a query string.

If that form's element is GET (like the one in our example) that query string is tacked onto the action URL, and the browser makes a GET request to that URL.

GET /example/message.html?name=Jean&message=Yes%3F HTTP/1.1

A query string starts with a question mark "?". Then we see the names and values from the form. An ampersand character (&) is used to separate the name/value pairs.

%3F is a way of escaping. Most formats need a way to escape and this particular one is called URL encoding. 3F is 68 in numeric values which is the question mark character.

JavaScript provides the encodeURIComponent and decodeURIComponent functions to encode and decode this format.

console.log(encodeURIComponent("Hello & goodbye"));
// → Hello%20%26%20goodbye
console.log(decodeURIComponent("Hello%20%26%20goodbye"));
// → Hello & goodbye

Going back to the form we should not use the GET method as that method should be used for requests that do not have side effects. Instead we should use the POST method and put the query string in body of the request.

Like this

POST /example/message.html HTTP/1.1
Content-length: 24
Content-type: application/x-www-form-urlencoded

name=Jean&message=Yes%3F

XMLHttpRequest

The interface through which browser JavaScript can make HTTP requests is called XMLHttpRequest. It was designed by Microsoft, for its Internet Explorer browser, in the late 1990s. The interface allows you to parse response documents as XML.

When this first started it allowed people to do things that would have been very difficult to do before, like make suggestions while people were typing into a field. The script would send the text to the server over HTTP as the user typed. The server, which had some database of possible inputs, would match the database entries against the partial input and send back possible completions to show the user.

Nowadays, the XMLHttpRequest is a standard interface.

Sending a request

To make a simple request, we create a request object with the XMLHttpRequest constructor and call its open and send methods.
open method configures the request
send after opening a method we send it, which is the body

var req = new XMLHttpRequest();
req.open("GET", "example/data.txt", false);
req.send(null);
console.log(req.responseText);
//> This is the content of data.txt

For GET requests, we can pass null. If the third argument to open was false, send will return only after the response to our request was received.

We get the status code through the status property and for human language through the statusText property.

var req = new XMLHttpRequest();
req.open("GET", "example/data.txt", false);
req.send(null);
console.log(req.status, req.statusText);
//> 200 OK
console.log(req.getResponseHeader("content-type"));
//> text/plain

Header names are case-insensitive. The browser, as we saw previously, will automatically add some headers but we can add more through the setRequestHeader method.

Asynchronous Requests

In the examples we saw, the request has finished when the call to send returns. This is convenient because it means properties such as responseText are available immediately. Bad thing is that our program is suspending during the duration of this time and we cannot do anything while this is happening.

To avoid this we can use "true" as our third argument to open, this means it is asynchronous. This means that when we call send, the only thing that happens right away is that the request is scheduled to be sent. This means the our program is no longer suspended and the browser and server will continue in the background.
But as long as the request is running, we won’t be able to access the response. We need a mechanism that will notify us when the data is available.

For this, we need the "load" event on the request object.

var req = new XMLHttpRequest();
req.open("GET", "example/data.txt", true);
req.addEventListener("load", function() {
  console.log("Done:", req.status);
});
req.send(null);

Fetching XML Data

When the resource that is received by a XMLHttpRequest object is an XML document, the object’s responseXML property will hold a parsed representation of this document. This is very similar to how a DOM works, except it does not have the style property. It is called a document object, the object that is held by the responseXML. The documentElement property is the outer tag of the XML document.

So, in the following code the fruits tag would be the documentElement.

<fruits>
  <fruit name="banana" color="yellow"/>
  <fruit name="lemon" color="yellow"/>
  <fruit name="cherry" color="red"/>
</fruits>

We can retrieve such a file like this:

var req = new XMLHttpRequest();
req.open("GET", "example/fruit.xml", false);
req.send(null);
console.log(req.responseXML.querySelectorAll("fruit").length);
//> 3

We can use XML to exachange data with the server, however this can be difficult to read, a better option would be using JSON data.

var req = new XMLHttpRequest();
req.open("GET", "example/fruit.json", false);
req.send(null);
console.log(JSON.parse(req.responseText));
//> {banana: "yellow", lemon: "yellow", cherry: "red"}

HTTP sandboxing

As we have talked about, due to security reasons browsers disallow scripts to make HTTP requests to other domains. Ths can sometimes be annoying as it might be a legitimate website that is requesting it.

To workaround this one we can include a header like this in the response:

Access-Control-Allow-Origin: *

Abstracting requests

We can use a hypothetical function to take a filename and a function and call that function with the contents of the file when it has finished fetching it.

function backgroundReadFile(url, callback) {
  var req = new XMLHttpRequest();
  req.open("GET", url, true);
  req.addEventListener("load", function() {
    if (req.status < 400)
      callback(req.responseText);
  });
  req.send(null);
}

This makes it easier for us to use GET requests. If you are writing a program that has to make HTTP requests, it is a good idea to use a helper function so that you don’t end up repeating the ugly XMLHttpRequest pattern all through your code.

Normallywe use the word callback for the functions argument in cases like these. A callback function is given to other code to provide that code with a way to “call us back” later.

The request we just saw does only GET requests, but we can do POST requests or one that does all sorts of requests. Note that many JavaScript libraries also provide wrappers for XMLHttpRequest.

Take a look at the code, it does not do anything when it receives an error. This could hurt our websites traffic, due to the fact that if we have a loading screen, get an error and that loading screen continues, the user will get annoyed as it does not know that there is an error.

We should also think about getting notified if there is an error. Error handling in asynchronous code is even trickier than error handling in synchronous code. Because we often need to defer part of our work, putting it in a callback function, the scope of a try block becomes meaningless.

try {
  backgroundReadFile("example/data.txt", function(text) {
    if (text != "expected")
      throw new Error("That was unexpected");
  });
} catch (e) {
  console.log("Hello from the catch block");
}

To handle failing requests, we have to allow an additional function to be passed to our wrapper and call that when a request goes wrong. Alternatively, we can use the convention that if the request fails, an additional argument describing the problem is passed to the regular callback function. Here’s an example:

function getURL(url, callback) {
  var req = new XMLHttpRequest();
  req.open("GET", url, true);
  req.addEventListener("load", function() {
    if (req.status < 400)
      callback(req.responseText);
    else
      callback(null, new Error("Request failed: " +
                               req.statusText));
  });
  req.addEventListener("error", function() {
    callback(null, new Error("Network error"));
  });
  req.send(null);
}

As you may have noticed we have added a handler for the error event which will be signaled when the request fails entirely.

We also call the callback function with an error argument when the request completes with a status code that indicates an error:

getURL("data/nonsense.txt", function(content, error) {
  if (error != null)
    console.log("Failed to fetch nonsense.txt: " + error);
  else
    console.log("nonsense.txt: " + content);
});

This will not help when it comes to exceptions though.

Promises

For big and complicated projects, writing synchronous code in plain callback style is hard to do correctly. We can easily miss giving an error to something or other.

There have been many attempts to make this better with extra abstractions, and one that works the best is "Promises". A Promise represents a value which may be available now, or in the future, or never. They wrap an asynchronous action in an object, which can be passed around and told to do certain things when the action finishes or fails.

If you want a more in-depth knowledge of promises you can go here. Note that this interface is set to become part of the next version of the JavaScript language but can already be used as a library.

To create a promise object, we call the Promise constructor, giving it a function that initializes the asynchronous action. The constructor calls that function, passing it two arguments, which are also functions.

The first function argument should be called when the action finishes successfully and the second when it does not (or when it fails).

Here is an example:

function get(url) {
  return new Promise(function(succeed, fail) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.addEventListener("load", function() {
      if (req.status < 400)
        succeed(req.responseText);
      else
        fail(new Error("Request failed: " + req.statusText));
    });
    req.addEventListener("error", function() {
      fail(new Error("Network error"));
    });
    req.send(null);
  });
}

That promise acts as a handle to the request’s outcome. It has a then method that you can call with two functions: one to handle success and one to handle failure.

get("example/data.txt").then(function(text) {
  console.log("data.txt: " + text);
}, function(error) {
  console.log("Failed to fetch data.txt: " + error);
});

You can also use then to transform the result of a promise

function getJSON(url) {
  return get(url).then(JSON.parse);
}

As an example that shows the use of promises, we will build a program that fetches a number of JSON files from the server and, while it is doing that, shows the word loading. The JSON files contain information about people, with links to files that represent other people in properties such as father, mother, or spouse.

We want to get the name of the mother of the spouse of example/bert.json. And if something goes wrong, we want to remove the loading text and show an error message instead. Here is how that might be done with promises:

<script>
  function showMessage(msg) {
    var elt = document.createElement("div");
    elt.textContent = msg;
    return document.body.appendChild(elt);
  }

  var loading = showMessage("Loading...");
  getJSON("example/bert.json").then(function(bert) {
    return getJSON(bert.spouse);
  }).then(function(spouse) {
    return getJSON(spouse.mother);
  }).then(function(mother) {
    showMessage("The name is " + mother.name);
  }).catch(function(error) {
    showMessage(String(error));
  }).then(function() {
    document.body.removeChild(loading);
  });
</script>

You can think of the promise interface as implementing its own language for asynchronous control flow.

Appreciating HTTP

When thinking in terms of remote procedure calls, HTTP is just a vehicle for communication, and you will most likely write an abstraction layer that hides it entirely.

Check this out:
Another approach is to build your communication around the concept of resources and HTTP methods. Instead of a remote procedure called addUser, you use a PUT request to /users/larry. Instead of encoding that user’s properties in function arguments, you define a document format or use an existing format that represents a user. The body of the PUT request to create a new resource is then simply such a document. A resource is fetched by making a GET request to the resource’s URL (for example, /user/larry), which returns the document representing the resource.

Security and HTTPS

The secure HTTP protocol, whose URLs start with https://, wraps HTTP traffic in a way that makes it harder to read and tamper with. First, the client verifies that the server is who it claims to be by requiring that server to prove that it has a cryptographic certificate issued by a certificate authority that the browser recognizes. Next, all data going over the connection is encrypted in a way that should prevent eavesdropping and tampering.

Thus, when it works right, HTTPS prevents both the someone impersonating the website you were trying to talk to and the someone snooping on your communication.

Time to do the exercises!

Day 36. Forms and Form fields

We have already briefly had a look at forms, let's take a closer look.

Fields

Ah the fields on a good hike are beautiful and green, but those are not the type of fields we are going to be looking at today. We will be looking at the ones that belong to a form. We define each field with a form tag an we can style it with HTML elements. We can create checkboxes, radio buttons, drop-down menus... The main way to select these is through the input tags attribute.

Here are a couple of them:


text	 // A single-line text field
password // Same as text but hides the text that is typed
checkbox // An on/off switch
radio	// (Part of) a multiple-choice field
file	// Allows the user to choose a file from their computer

Form fields do not necessarily have to appear in a form tag. You can put them anywhere in a page. But those fields cannot be submitted. But when responding to input with JavaScript, we often do not want to submit our fields normally anyway.

<p><input type="text" value="abc"> (text)</p>
<p><input type="password" value="abc"> (password)</p>
<p><input type="checkbox" checked> (checkbox)</p>
<p><input type="radio" value="A" name="choice">
   <input type="radio" value="B" name="choice" checked>
   <input type="radio" value="C" name="choice"> (radio)</p>
<p><input type="file"> (file)</p>

If you want several lines of text you can use the textarea tag Like this:

<textarea>
one
two
three
</textarea>

The select tag gives a dropdown of options that we give it:

<select>
  <option>Pancakes</option>
  <option>Pudding</option>
  <option>Ice cream</option>
</select>

Focus

Unlike most elements in an HTML document, form fields can get keyboard focus. When clicked or activated in some other way, they become the currently active element, the main recipient of keyboard input.
So we saw that when we put a URL into the browser, it will make a request. When that HTML page references other files such as images and JavaScript, those are also fetched.

So we can only write text in there once it is focused. We can control this focus with JavaScript by using the focus and blur methods
focus moves focus onto the selected DOM element.
blur removes the focus.

The value in document.activeElement corresponds to the currently focused element.

<input type="text">
<script>
  document.querySelector("input").focus();
  console.log(document.activeElement.tagName);
  //> INPUT
  document.querySelector("input").blur();
  console.log(document.activeElement.tagName);
  //> BODY
</script>

HTML also provides the autofocus attribute, which produces the same effect but lets the browser know what we are trying to achieve.

<input type="text" autofocus>

Normally we can use the tab key to move through a webpage, we can edit that attribute too.

<input type="text" tabindex=1> <a href=".">(help)</a>
<button onclick="console.log('ok')" tabindex=2>OK</button>

This example allows us to focus jump from the text input to the OK button.
Note that by default most types of HTML elements cannot be focused, but that can be changed by adding a tabindex attribute to any element.

Disabled fields

We can use the disable attribute to disable any form field.

<button>I'm all right</button>
<button disabled>I'm out</button>

Disabled fields cannot be focused or changed, and unlike active fields, they usually look gray and faded.

The form as a whole

When a field is contained in a form element, its DOM element will have a property form linking back to the form’s DOM element. The form element, in turn, has a property called elements that contains an array-like collection of the fields inside it.

The name attribute is how we identify the value once submitted. I can also be used as a property name.

<form action="example/submit.html">
  Name: <input type="text" name="name"><br>
  Password: <input type="password" name="password"><br>
  <button type="submit">Log in</button>
</form>
<script>
  var form = document.querySelector("form");
  console.log(form.elements[1].type);
  // → password
  console.log(form.elements.password.type);
  // → password
  console.log(form.elements.name.form == form);
  // → true
</script>

Text fields

Fields that have the input attribute password or text or the textarea tag look the same (interface). The DOM elements have a value property that holds a string, if we change this string it will change the fields content.

The selectionStart and selectionEnd properties tells us where the cursor is of the selected text returning number values.

Now imagine you are writing a text about Mary Poppins and Supercalifragilisticexpialidocious comes up several times, that's a hard one to write. The following code wires up a textarea tag with an event handler that, when you press F2, inserts the string “Supercalifragilisticexpialidocious” for you.

<textarea></textarea>
<script>
  var textarea = document.querySelector("textarea");
  textarea.addEventListener("keydown", function(event) {
    // The key code for F2 happens to be 113
    if (event.keyCode == 113) {
      replaceSelection(textarea, "Supercalifragilisticexpialidocious");
      event.preventDefault();
    }
  });
  function replaceSelection(field, word) {
    var from = field.selectionStart, to = field.selectionEnd;
    field.value = field.value.slice(0, from) + word +
                  field.value.slice(to);
    // Put the cursor after the word
    field.selectionStart = field.selectionEnd =
      from + word.length;
  }
</script>

The replaceSelection function replaces the currently selected part of a text field’s content with the given word and then moves the cursor after that word so that the user can continue typing.

The following example shows a text field and a counter showing the current length of the text entered:

<input type="text"> length: <span id="length">0</span>
<script>
  var text = document.querySelector("input");
  var output = document.querySelector("#length");
  text.addEventListener("input", function() {
    output.textContent = text.value.length;
  });
</script>

Checkboxes and radio buttons

A checkbox field is a simple binary toggle. Its value can be extracted or changed through its checked property, which holds a Boolean value.

<input type="checkbox" id="purple">
<label for="purple">Make this page purple</label>
<script>
  var checkbox = document.querySelector("#purple");
  checkbox.addEventListener("change", function() {
    document.body.style.background =
      checkbox.checked ? "mediumpurple" : "";
  });
</script>

The label tag is to associate text with an input field, it's for attribute should refer to the ID of the field. Clicking the label will activate the field, which focuses it and toggles its value when it is a checkbox or radio button.

Radio buttons work very much the same but you can only select one. Resulting in a same name attribute.

Color:
<input type="radio" name="color" value="mediumpurple"> Purple
<input type="radio" name="color" value="lightgreen"> Green
<input type="radio" name="color" value="lightblue"> Blue
<script>
  var buttons = document.getElementsByName("color");
  function setColor(event) {
    document.body.style.background = event.target.value;
  }
  for (var i = 0; i < buttons.length; i++)
    buttons[i].addEventListener("change", setColor);
</script>

The document.getElementsByName method gives us all elements with a given name attribute.

Select fields

Select fields, in a way, are similar to radio buttons as they allow the user to select one option of many. The appearance of a select tag is defined by the browser.

If we give the select tag a "multiple" attribute then we allow the user to select more than one option.

<select multiple>
  <option>Pancakes</option>
  <option>Pudding</option>
  <option>Ice cream</option>
</select>

A non-multiple select with be shown as a dropdown menu, this will appear differently depending on the browser.

If we apply the size attribute to the select tag we can say how many options we want visible at the same time. If we put down 5 we will see 5 options.

Every option tag has a value. The option tags for a select field can be accessed as an array-like object through the field’s options property. Each option has a property called selected, which indicates whether that option is currently selected. The property can also be written to select or deselect an option.

<select multiple>
  <option value="1">0001</option>
  <option value="2">0010</option>
  <option value="4">0100</option>
  <option value="8">1000</option>
</select> = <span id="output">0</span>
<script>
  var select = document.querySelector("select");
  var output = document.querySelector("#output");
  select.addEventListener("change", function() {
    var number = 0;
    for (var i = 0; i < select.options.length; i++) {
      var option = select.options[i];
      if (option.selected)
        number += Number(option.value);
    }
    output.textContent = number;
  });
</script>

File fields

File fields original purpose was to upload files from the browser machine through a form. Nowadays, they also provide a way to read such files from JavaScript programs. Files can only be read through a browser through uploading one.

The FileReader constructor as being similar to XMLHttpRequest but for files. Reading a file is done by creating a FileReader object, registering a "load" event handler for it, and calling its readAsText method, giving it the file we want to read. Once loading finishes, the reader’s result property contains the file’s content.

<input type="file" multiple>
<script>
  var input = document.querySelector("input");
  input.addEventListener("change", function() {
    Array.prototype.forEach.call(input.files, function(file) {
      var reader = new FileReader();
      reader.addEventListener("load", function() {
        console.log("File", file.name, "starts with",
                    reader.result.slice(0, 20));
      });
      reader.readAsText(file);
    });
  });
</script>

FileReaders also fire an "error" event when reading the file fails for any reason.

function readFile(file) {
  return new Promise(function(succeed, fail) {
    var reader = new FileReader();
    reader.addEventListener("load", function() {
      succeed(reader.result);
    });
    reader.addEventListener("error", function() {
      fail(reader.error);
    });
    reader.readAsText(file);
  });
}

Storing data client-side

Simple HTML pages with a bit of JavaScript can be a great medium for “mini applications”—small helper programs that automate everyday things. By connecting a few form fields with event handlers, you can do anything from converting between degrees Celsius and Fahrenheit to computing passwords from a master password and a website name.

When such an application needs to remember something between sessions, you cannot use JavaScript variables since those are thrown away every time a page is closed. But we could keep the data in the browser.

You can store string data in a way that survives page reloads by putting it in the localStorage object. This object allows you to file string values under names (also strings), as in this example:

localStorage.setItem("username", "Ana");
console.log(localStorage.getItem("username"));
//> ana
localStorage.removeItem("username");

localStorage sticks around until you remove it with removeItem. Data stored in localStorage by a given website can, in principle, only be read (and overwritten) by scripts on that same site. Browsers also enforce a limit of the size.

The following code implements a simple note-taking application. It keeps the user’s notes as an object, associating note titles with content strings. This object is encoded as JSON and stored in localStorage. The user can select a note from a select field and change that note’s text in a textarea. A note can be added by clicking a button.

Notes: <select id="list"></select>
<button onclick="addNote()">new</button><br>
<textarea id="currentnote" style="width: 100%; height: 10em">
</textarea>

<script>
  var list = document.querySelector("#list");
  function addToList(name) {
    var option = document.createElement("option");
    option.textContent = name;
    list.appendChild(option);
  }

  // Initialize the list from localStorage
  var notes = JSON.parse(localStorage.getItem("notes")) ||
              {"shopping list": ""};
  for (var name in notes)
    if (notes.hasOwnProperty(name))
      addToList(name);

  function saveToStorage() {
    localStorage.setItem("notes", JSON.stringify(notes));
  }

  var current = document.querySelector("#currentnote");
  current.value = notes[list.value];

  list.addEventListener("change", function() {
    current.value = notes[list.value];
  });
  current.addEventListener("change", function() {
    notes[list.value] = current.value;
    saveToStorage();
  });

  function addNote() {
    var name = prompt("Note name", "");
    if (!name) return;
    if (!notes.hasOwnProperty(name)) {
      notes[name] = "";
      addToList(name);
      saveToStorage();
    }
    list.value = name;
    current.value = notes[name];
  }
</script>

This is the solution 😉

Time to do the exercises!

Day 37. Project 4: A paint program

From what we have learnt we are ready to build a web application. We will be building a paint program that looks like this:
paint

Implementation

What we can see above is a big canvas and then some form fields underneath. The user draws on the picture by selecting a tool from a select field and then clicking or dragging across the canvas. There are tools for drawing lines, erasing parts of the picture, adding text, and more.

Will we be using mousedown and mousemove to allow the user to paint on the canvas. We will also let the user upload an image by either uploading one from his or her machine or through a URL.

The save link allows the user to be followed, shared or saved.

Building the DOM

As our programs interface is built of a lot of DOM elements we are going to need a helper function.

This will create an element with the given name and attributes and appends all further arguments it gets as child nodes, automatically converting strings to text nodes.

function elt(name, attributes) {
  var node = document.createElement(name);
  if (attributes) {
    for (var attr in attributes)
      if (attributes.hasOwnProperty(attr))
        node.setAttribute(attr, attributes[attr]);
  }
  for (var i = 2; i < arguments.length; i++) {
    var child = arguments[i];
    if (typeof child == "string")
      child = document.createTextNode(child);
    node.appendChild(child);
  }
  return node;
}

This way we can create elements easily.

The foundation

The most important part of our program is to be able to paint, thus, the createPaint function is the core. As our program will be built piece by piece we define an object called controls.

It will hold functions to initialise the various controls below the image

var controls = Object.create(null);

function createPaint(parent) {
  var canvas = elt("canvas", {width: 500, height: 300});
  var cx = canvas.getContext("2d");
  var toolbar = elt("div", {class: "toolbar"});
  for (var name in controls)
    toolbar.appendChild(controls[name](cx));

  var panel = elt("div", {class: "picturepanel"}, canvas);
  parent.appendChild(elt("div", null, panel, toolbar));
}

Each control has access to the canvas drawing context and to the canvas element.
The fillStyle property is the color.
The lineWidth is the brush size.

We use div elements so that later we can style those elements with css.

Tool selection

In our tool selection we first add a select so that the user can "select" which tool he or she wants to use.

As with controls, we will use an object to collect various tools so that we do not have to hard-code them and can add to them later.

var tools = Object.create(null);

controls.tool = function(cx) {
  var select = elt("select");
  for (var name in tools)
    select.appendChild(elt("option", null, name));

  cx.canvas.addEventListener("mousedown", function(event) {
    if (event.which == 1) {
      tools[select.value](event, cx);
      event.preventDefault();
    }
  });

  return elt("span", null, "Tool: ", select);
};

The tool field is populated with

The most basic tool is the line tool and for that to work we need to be able to find the canvas-relative coordinates that a given mouse event corresponds to. Remember that it is relative to the top left hand corner.

function relativePos(event, element) {
  var rect = element.getBoundingClientRect();
  return {x: Math.floor(event.clientX - rect.left),
          y: Math.floor(event.clientY - rect.top)};
}

Several tools need to listen to mousemove events as long as the mouse button is held down.

function trackDrag(onMove, onEnd) {
  function end(event) {
    removeEventListener("mousemove", onMove);
    removeEventListener("mouseup", end);
    if (onEnd)
      onEnd(event);
  }
  addEventListener("mousemove", onMove);
  addEventListener("mouseup", end);
}

The line tool uses these two helpers to do the actual drawing.

tools.Line = function(event, cx, onEnd) {
  cx.lineCap = "round";

  var pos = relativePos(event, cx.canvas);
  trackDrag(function(event) {
    cx.beginPath();
    cx.moveTo(pos.x, pos.y);
    pos = relativePos(event, cx.canvas);
    cx.lineTo(pos.x, pos.y);
    cx.stroke();
  }, onEnd);
};

The function starts by setting the drawing context’s lineCap property to "round" because if you use the default flat line caps you will see gaps at corners with bigger line widths.

Then, for every "mousemove" event that occurs as long as the mouse button is down, a simple line segment is drawn between the mouse’s old and new position, using whatever strokeStyle and lineWidth happen to be currently set.
The third argument is left undefined so that we can easily build an erase tool.

tools.Erase = function(event, cx) {
  cx.globalCompositeOperation = "destination-out";
  tools.Line(event, cx, function() {
    cx.globalCompositeOperation = "source-over";
  });
};

The globalCompositeOperation property influences the way drawing operations on a canvas change the color of the pixels they touch. The erase tool sets globalCompositeOperation to "destination-out", which has the effect of erasing the pixels we touch, making them transparent again.

Colour and brush size

Now lets add some colours and brush sizes. One of the more modern input types is color. Not all browsers support it.

controls.color = function(cx) {
  var input = elt("input", {type: "color"});
  input.addEventListener("change", function() {
    cx.fillStyle = input.value;
    cx.strokeStyle = input.value;
  });
  return elt("span", null, "Color: ", input);
};

Whenever the value of the color field changes, the drawing context’s fillStyle and strokeStyle are updated to hold the new value.

The field for configuring the brush size works similarly.

controls.brushSize = function(cx) {
  var select = elt("select");
  var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100];
  sizes.forEach(function(size) {
    select.appendChild(elt("option", {value: size},
                           size + " pixels"));
  });
  select.addEventListener("change", function() {
    cx.lineWidth = select.value;
  });
  return elt("span", null, "Brush size: ", select);
};

Saving

Data URLs don’t point at a resource but rather contain the entire resource in them. This is a data URL containing a simple HTML document:

data:text/html,<h1 style="color:red">Hello!</h1>

Canvas elements have a convenient method, called toDataURL, which will return a data URL that contains the picture on the canvas as an image file. Instead of having the link save every time we make a change we will rig the link to update its href attribute whenever it is focused with the keyboard or the mouse is moved over it.

controls.save = function(cx) {
  var link = elt("a", {href: "/"}, "Save");
  function update() {
    try {
      link.href = cx.canvas.toDataURL();
    } catch (e) {
      if (e instanceof SecurityError)
        link.href = "javascript:alert(" +
          JSON.stringify("Can't save: " + e.toString()) + ")";
      else
        throw e;
    }
  }
  link.addEventListener("mouseover", update);
  link.addEventListener("focus", update);
  return link;
};

So the link just quietly sits there, pointing at the wrong thing, but when the user approaches it, it updates itself to point at the current picture.

To prevent information leaks, browsers will mark a canvas as tainted when an image that the script may not see is drawn onto it. This is why we need the try/catch statement in the update function for the save link.

Loading image files

Last but not least we need to allow the user to upload images.

To upload them form a URL we need a helper function

function loadImageURL(cx, url) {
  var image = document.createElement("img");
  image.addEventListener("load", function() {
    var color = cx.fillStyle, size = cx.lineWidth;
    cx.canvas.width = image.width;
    cx.canvas.height = image.height;
    cx.drawImage(image, 0, 0);
    cx.fillStyle = color;
    cx.strokeStyle = color;
    cx.lineWidth = size;
  });
  image.src = url;
}

Last but not least we need to allow the user to upload images.

We need a helper function to load an image file from a URL and replace the contents of the canvas with it:

function loadImageURL(cx, url) {
  var image = document.createElement("img");
  image.addEventListener("load", function() {
    var color = cx.fillStyle, size = cx.lineWidth;
    cx.canvas.width = image.width;
    cx.canvas.height = image.height;
    cx.drawImage(image, 0, 0);
    cx.fillStyle = color;
    cx.strokeStyle = color;
    cx.lineWidth = size;
  });
  image.src = url;
}

We load the file that the user chose as a data URL and pass it to loadImageURL to put it into the canvas:

controls.openFile = function(cx) {
  var input = elt("input", {type: "file"});
  input.addEventListener("change", function() {
    if (input.files.length == 0) return;
    var reader = new FileReader();
    reader.addEventListener("load", function() {
      loadImageURL(cx, reader.result);
    });
    reader.readAsDataURL(input.files[0]);
  });
  return elt("div", null, "Open file: ", input);
};

Loading a file from a URL is even simpler. But with a text field, it is less clear when the user has finished writing the URL, so we can’t simply listen for "change" events. Instead, we will wrap the field in a form and respond when the form is submitted.

controls.openURL = function(cx) {
  var input = elt("input", {type: "text"});
  var form = elt("form", null,
                 "Open URL: ", input,
                 elt("button", {type: "submit"}, "load"));
  form.addEventListener("submit", function(event) {
    event.preventDefault();
    loadImageURL(cx, input.value);
  });
  return form;
};

Finishing Up

Let's add a few more tools.

A text tool:

tools.Text = function(event, cx) {
  var text = prompt("Text:", "");
  if (text) {
    var pos = relativePos(event, cx.canvas);
    cx.font = Math.max(7, cx.lineWidth) + "px sans-serif";
    cx.fillText(text, pos.x, pos.y);
  }
};

A spray paint tool (basically drawing random dots depending on whether the mouse is held down and whether it is held in the same place).

tools.Spray = function(event, cx) {
  var radius = cx.lineWidth / 2;
  var area = radius * radius * Math.PI;
  var dotsPerTick = Math.ceil(area / 30);

  var currentPos = relativePos(event, cx.canvas);
  var spray = setInterval(function() {
    for (var i = 0; i < dotsPerTick; i++) {
      var offset = randomPointInRadius(radius);
      cx.fillRect(currentPos.x + offset.x,
                  currentPos.y + offset.y, 1, 1);
    }
  }, 25);
  trackDrag(function(event) {
    currentPos = relativePos(event, cx.canvas);
  }, function() {
    clearInterval(spray);
  });
};

We also need to determine how many dots to draw every time

function randomPointInRadius(radius) {
  for (;;) {
    var x = Math.random() * 2 - 1;
    var y = Math.random() * 2 - 1;
    if (x * x + y * y <= 1)
      return {x: x * radius, y: y * radius};
  }
}

Now we run it:



Time to do the exercises!

Day 38 PART 3!!: Node.js

Up until now we have learnt the JavaScript language and how to use it on the browser. Now we are going to take a brief look on how to use it outside of the browser using a program "Node.js". With it, you can build anything from simple command-line tools to dynamic HTTP servers.

The code samples we will see are written for Node and won’t run in the browser. If you want to follow along and run the code in this chapter, start by going to nodejs.org and following the installation instructions for your operating system. Also refer to that website for further documentation about Node and its built-in modules.

Background

One of the most difficult problems we encounter with writing systems that communicate over the network is the input and output. The traditional way to handle input and output is to have a function, such as readFile, start reading a file and return only when the file has been fully read. This is called synchronous I/O (I/O stands for input/output).

Node was initially conceived for the purpose of making asynchronous I/O easy and convenient. JavaScript lends itself well to a system like Node. It is one of the few programming languages that does not have a built-in way to do I/O. Thus, there will not be any interference with Node.

Asynchronicity

We are talking about synchronous versus asynchronous I/O. Synchronous means that a program will fetch one resource after another from the Internet and then do some simple processing with the result. It means that it will wait until the first resource is done before starting the second. This is time consuming.

In a synchronous system we can start an additional thread of control to make it less time consuming. A second thread could start the second request, and then both threads wait for their results to come back, after which they resynchronize to combine their results.

The asynchronous model, starts an I/O action conceptually and causes a split in the timeline.

Which one to use depends on the type of program you are building.

The node command

When Node.js is installed on a system, it provides a program called node, which is used to run JavaScript files. Say you have a file hello.js, containing this code:

var message = "Hello world";
console.log(message);

You can run node from terminal (command line) like this to execute the program:

$ node hello.js
Hello world

The console.log method in Node is similiar to what happens in the browser. But in Node, the text will go to the process’ standard output stream, rather than to a browser’s JavaScript console. If you run node without giving it a file, it provides you with a prompt at which you can type JavaScript code and immediately see the result.

$ node
> 1 + 1
2
> [-1, -2, -3].map(Math.abs)
[1, 2, 3]
> process.exit(0)
$

The process variable, just like the console variable, is available globally in Node. It allow sus to inspect and manipulate the program. exit allows us to exit the program. process.argv will show us the command line arguments. All the standard JavaScript global variables, such as Array, Math, and JSON, are also present in Node’s environment. Browser-related functionality, such as document and alert, is absent. The global scope object is called global in Node (what would be window in the browser).

Modules

If you want to access other built-in functionality, you have to ask the module system for it.
When require is called, Node has to resolve the given string to an actual file to load.
A bit about Pathnames:
if the start with "/" "./" or "../" are resolved relative to the current module’s path.
"/" means the root of the file system.
"./" current directory
"../" on directory up
When a string that does not look like a relative or absolute path is given to require, it is assumed to refer to either a built-in module or a module installed in a node_modules directory.

Heres an example of what require can do

var garble = require("./garble");

// Index 2 holds the first actual command-line argument
var argument = process.argv[2];

console.log(garble(argument));

The file garble.js defines a library for garbling strings, which can be used both by the command-line tool defined earlier and by other scripts that need direct access to a garbling function.

module.exports = function(string) {
  return string.split("").map(function(ch) {
    return String.fromCharCode(ch.charCodeAt(0) + 5);
  }).join("");
};

We can now call our tool like this:

$ node main.js JavaScript
Of{fXhwnuy

Installing with NPM

NPM is an online repository of JavaScript modules, many of which are specifically written for Node. When you install Node on your computer, you also get a program called npm, which provides a convenient interface to this repository.

One module you will find on NPM is figlet, which can convert text into ASCII art—drawings made out of text characters. Which is really cool.

$ npm install figlet
npm GET https://registry.npmjs.org/figlet
npm 200 https://registry.npmjs.org/figlet
npm GET https://registry.npmjs.org/figlet/-/figlet-1.0.9.tgz
npm 200 https://registry.npmjs.org/figlet/-/figlet-1.0.9.tgz
figlet@1.0.9 node_modules/figlet
$ node
> var figlet = require("figlet");
> figlet.text("Hello world!", function(error, data) {
    if (error)
      console.error(error);
    else
      console.log(data);
  });
  _   _      _ _                            _     _ _
 | | | | ___| | | ___   __      _____  _ __| | __| | |
 | |_| |/ _ \ | |/ _ \  \ \ /\ / / _ \| '__| |/ _` | |
 |  _  |  __/ | | (_) |  \ V  V / (_) | |  | | (_| |_|
 |_| |_|\___|_|_|\___/    \_/\_/ \___/|_|  |_|\__,_(_)

Canvas elements have a convenient method, called toDataURL, which will return a data URL that contains the picture on the canvas as an image file. Instead of having the link save every time we make a change we will rig the link to update its href attribute whenever it is focused with the keyboard or the mouse is moved over it.

controls.save = function(cx) {
  var link = elt("a", {href: "/"}, "Save");
  function update() {
    try {
      link.href = cx.canvas.toDataURL();
    } catch (e) {
      if (e instanceof SecurityError)
        link.href = "javascript:alert(" +
          JSON.stringify("Can't save: " + e.toString()) + ")";
      else
        throw e;
    }
  }
  link.addEventListener("mouseover", update);
  link.addEventListener("focus", update);
  return link;
};

This module is installed by running npm install. npm install does so much: It reads package.json files, which contain JSON-encoded information about a program or library, such as which other libraries it depends on. Doing npm install in a directory that contains such a file will automatically install all dependencies, as well as their dependencies. The npm tool is also used to publish libraries to NPM’s online repository of packages so that other people can find, download, and use them.

Want to know more about npm? Click here

The file system module

The file-system (fs) is the most commonly used built-in module.

Here's an example: there is a function called readFile, which reads a file and then calls a callback with the file’s contents.

var fs = require("fs");
fs.readFile("file.txt", "utf8", function(error, text) {
  if (error)
    throw error;
  console.log("The file contained:", text);
});

The second argument to readFile indicates the character encoding used to decode the file into a string. Note that most modern systems use UTF-8 to encode text.

If you do not pass an encoding, Node will assume you are interested in the binary data and will give you a Buffer object instead of a string. This is an array-like object that contains numbers representing the bytes in the files.

var fs = require("fs");
fs.readFile("file.txt", function(error, buffer) {
  if (error)
    throw error;
  console.log("The file contained", buffer.length, "bytes.",
              "The first byte is:", buffer[0]);
});

A similar function, writeFile, is used to write a file to disk.

var fs = require("fs");
fs.writeFile("graffiti.txt", "Node was here", function(err) {
  if (err)
    console.log("Failed to write file:", err);
  else
    console.log("File written.");
});

Here, it was not necessary to specify the encoding since writeFile will assume that if it is given a string to write, rather than a Buffer object, it should write it out as text using its default character encoding, which is UTF-8.

Many of the functions in "fs" come in both synchronous and asynchronous variants. Synchronous functions require less ceremony to use and can be useful in simple scripts.

var fs = require("fs");
console.log(fs.readFileSync("file.txt", "utf8"));

The HTTP module

Another central module is called "http". It provides functionality for running HTTP servers and making HTTP requests.

If we want to start up a simple http module all we have to do is this:

var http = require("http");
var server = http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/html"});
  response.write("<h1>Hello!</h1><p>You asked for <code>" +
                 request.url + "</code></p>");
  response.end();
});
server.listen(8000);

You can point your web browser at http://localhost:8000/hello to make a request to your server. It will respond with a small HTML page.
To stop running a Node script like this, which doesn’t finish automatically because it is waiting for further events (in this case, network connections), press Ctrl-C.

To act as an HTTP client, we can use the request function in the "http" module.

var http = require("http");
var request = http.request({
  hostname: "eloquentjavascript.net",
  path: "/20_node.html",
  method: "GET",
  headers: {Accept: "text/html"}
}, function(response) {
  console.log("Server responded with status code",
              response.statusCode);
});
request.end();

To make requests to secure HTTP (HTTPS) URLs, Node provides a package called https, which contains its own request function, similar to http.request.

Tomorrow streams, a simple file server and error handling.

Day 39. Node.js: Streams, a simple file server and error handling

Streams

So far we have seen two writable streams, the request object and the response object. Writable streams are common in Node interfaces.
Writable strings consist of a write method, which is either passed a string or a Buffer object. To close the stream we use an end method, which can be given an argument to write out a piece of data before closing the stream. We can also give these a callback argument.

We can create a writable stream that points at a file by using the fs.createWriteStream function. Then we can use the write method to write the file one piece at a time.

Readable streams are a bit more complicated, we use event handlers to to read from a stream. To admit an event to an object we call on. We then give it an event name and then a function and it will register that function to be called whenever the given event occurs.

In a readable stream a:
data event is one that is fired when data comes in.
end event is one that is called when the stream is at an end.

The following code creates a server that reads request bodies and streams them back to the client as all-uppercase text:

var http = require("http");
http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  request.on("data", function(chunk) {
    response.write(chunk.toString().toUpperCase());
  });
  request.on("end", function() {
    response.end();
  });
}).listen(8000);

The following piece of code, if run while the uppercasing server is running, will send a request to that server and write out the response it gets:

var http = require("http");
var request = http.request({
  hostname: "localhost",
  port: 8000,
  method: "POST"
}, function(response) {
  response.on("data", function(chunk) {
    process.stdout.write(chunk.toString());
  });
});
request.end("Hello server");

The example writes to process.stdout (the process’ standard output, as a writable stream) instead of using console.log. We can’t use console.log because it adds an extra newline character after each piece of text that it writes, which isn’t appropriate here.

A simple file server

So, an HTTP server that allows remote access to a file system. When we treat files as HTTP resources, the HTTP methods GET, PUT, and DELETE can be used to read, write, and delete the files, respectively.

As we probably do not want to share our whole file system we will interpret these paths as starting in the server’s working directory, which is the directory in which it was started.

We’ll build the program piece by piece, using an object called methods to store the functions that handle the various HTTP methods.

var http = require("http"), fs = require("fs");

var methods = Object.create(null);

http.createServer(function(request, response) {
  function respond(code, body, type) {
    if (!type) type = "text/plain";
    response.writeHead(code, {"Content-Type": type});
    if (body && body.pipe)
      body.pipe(response);
    else
      response.end(body);
  }
  if (request.method in methods)
    methods[request.method](urlToPath(request.url),
                            respond, request);
  else
    respond(405, "Method " + request.method +
            " not allowed.");
}).listen(8000);

This starts a server that just returns 405 error responses. The respond function is passed to the functions that handle the various methods and acts as a callback to finish the request.

To get a path from the URL in the request, the urlToPath function uses Node’s built-in "url" module to parse the URL. It takes its pathname, which will be something like /file.txt, decodes that to get rid of the %20-style escape codes, and prefixes a single dot to produce a path relative to the current directory.

function urlToPath(url) {
  var path = require("url").parse(url).pathname;
  return "." + decodeURIComponent(path);
}

We will use the GET method to firstly return a list of file when reading a directory and secondly to return the file's content when reading a normal file.

As the content of the files varies it is tricky to determine the headers Content-Type.

We can use the mime package from NPM to get the correct type of file extension. To do so we should run the following command:

$ npm install mime
npm http GET https://registry.npmjs.org/mime
npm http 304 https://registry.npmjs.org/mime
mime@1.2.11 node_modules/mime

When a requested file does not exist, the correct HTTP error code to return is 404. We will use fs.stat, which looks up information on a file, to find out both whether the file exists and whether it is a directory.

methods.GET = function(path, respond) {
  fs.stat(path, function(error, stats) {
    if (error && error.code == "ENOENT")
      respond(404, "File not found");
    else if (error)
      respond(500, error.toString());
    else if (stats.isDirectory())
      fs.readdir(path, function(error, files) {
        if (error)
          respond(500, error.toString());
        else
          respond(200, files.join("\n"));
      });
    else
      respond(200, fs.createReadStream(path),
              require("mime").lookup(path));
  });
};

Canvas elements have a convenient method, called toDataURL, which will return a data URL that contains the picture on the canvas as an image file. Instead of having the link save every time we make a change we will rig the link to update its href attribute whenever it is focused with the keyboard or the mouse is moved over it.

controls.save = function(cx) {
  var link = elt("a", {href: "/"}, "Save");
  function update() {
    try {
      link.href = cx.canvas.toDataURL();
    } catch (e) {
      if (e instanceof SecurityError)
        link.href = "javascript:alert(" +
          JSON.stringify("Can't save: " + e.toString()) + ")";
      else
        throw e;
    }
  }
  link.addEventListener("mouseover", update);
  link.addEventListener("focus", update);
  return link;
};

Because it has to touch the disk and thus might take a while, fs.stat is asynchronous.

We will report any errors we do not expect as a 500, to indicate that the problem exists within the server.

The code to handle DELETE requests is:

methods.DELETE = function(path, respond) {
  fs.stat(path, function(error, stats) {
    if (error && error.code == "ENOENT")
      respond(204);
    else if (error)
      respond(500, error.toString());
    else if (stats.isDirectory())
      fs.rmdir(path, respondErrorOrNothing(respond));
    else
      fs.unlink(path, respondErrorOrNothing(respond));
  });
};

We return a 204 instead of a 500 because we are trying to deleting a file that did not exist in the first place.

The HTTP standard encourages people to make requests idempotent, which means that applying them multiple times does not produce a different result.

function respondErrorOrNothing(respond) {
  return function(error) {
    if (error)
      respond(500, error.toString());
    else
      respond(204);
  };
}

When an HTTP response does not contain any data, the status code 204 will be used to do so

methods.PUT = function(path, respond, request) {
  var outStream = fs.createWriteStream(path);
  outStream.on("error", function(error) {
    respond(500, error.toString());
  });
  outStream.on("finish", function() {
    respond(204);
  });
  request.pipe(outStream);
};

Here, we don’t need to check whether the file exists—if it does, we’ll just overwrite it.

The command-line tool curl, widely available on Unix-like systems, can be used to make HTTP requests. The following session briefly tests our server.

$ curl http://localhost:8000/file.txt
File not found
$ curl -X PUT -d hello http://localhost:8000/file.txt
$ curl http://localhost:8000/file.txt
hello
$ curl -X DELETE http://localhost:8000/file.txt
$ curl http://localhost:8000/file.txt
File not found

Error handling

In the code for the file server, there are six places where we are explicitly routing exceptions that we don’t know how to handle into error responses. Because exceptions aren’t automatically propagated to callbacks but rather passed to them as arguments, they have to be handled explicitly every time. This means that our server will crash whenever a problem is encountered in the server’s code itself, as opposed to asynchronous problems, which will be passed as arguments to the callbacks.

Remember promises? NPM has a "promise" module which contains a function called denodeify, which takes an asynchronous function like fs.readFile and converts it to a promise-returning function.

var Promise = require("promise");
var fs = require("fs");

var readFile = Promise.denodeify(fs.readFile);
readFile("file.txt", "utf8").then(function(content) {
  console.log("The file contained: " + content);
}, function(error) {
  console.log("Failed to read file: " + error);
});

Here are a few lines from the promise-based file server

methods.GET = function(path) {
  return inspectPath(path).then(function(stats) {
    if (!stats) // Does not exist
      return {code: 404, body: "File not found"};
    else if (stats.isDirectory())
      return fsp.readdir(path).then(function(files) {
        return {code: 200, body: files.join("\n")};
      });
    else
      return {code: 200,
              type: require("mime").lookup(path),
              body: fs.createReadStream(path)};
  });
};

function inspectPath(path) {
  return fsp.stat(path).then(null, function(error) {
    if (error.code == "ENOENT") return null;
    else throw error;
  });
}

Time to do the exercises!

Day 40. Project 5: Skill-sharing website

Can you believe this is our last chapter? It will be divided into two so it is not my last post but I am getting emotional... So many days of hiking... And it has almost come to an end. Ok enough of that. Let's get to making a skill-sharing website.

We will build a system that will let the participants propose and discuss talks among themselves, without a central organizer. We want a system that will let the participants propose and discuss talks among themselves, without a central organizer.

Design

There is a server part to this project, written for Node.js, and a client part, written for the browser. The server stores the system’s data and provides it to the client. It also serves the HTML and JavaScript files that implement the client-side system.

The server keeps a list of talks proposed for the next meeting, and the client shows this list. Each talk has a presenter name, a title, a summary, and a list of comments associated with it. The client allows users to propose new talks (adding them to the list), delete talks, and comment on existing talks. Whenever the user makes such a change, the client makes an HTTP request to tell the server about it.

skillsharing-1

The application will be set up to show a live view of the current proposed talks and their comments. Whenever someone, somewhere, submits a new talk or adds a comment, all people who have the page open in their browsers should immediately see the change. This poses a bit of a challenge since there is no way for a web server to open up a connection to a client, nor is there a good way to know which clients currently are looking at a given website.

A common solution to this problem is called long polling, which happens to be one of the motivations for Node’s design.

Long polling
To be able to immediately notify a client that something changed, we need a connection to that client.
There are a few techniques to allow this to happen, given the security conditions, we will be concentrating on long polling.

Long polling is where clients continuously ask the server for new information using regular HTTP requests, and the server simply stalls its answer when it has nothing new to report. As long as the client makes sure it constantly has a polling request open, it will receive information from the server immediately. To prevent connections from timing out we set a maximum time for each request.

Node, which makes it easy to manage many connections without creating a separate thread of control for each one, is a good fit for such this system.

HTTP Interface

Before we start coding eithe rthe server or the client side lets think about where they touch. The HTTP interface.

Our interface will be based on JSON and it is centered around the /talks path. Paths that do not start with /talks will be used for serving static files—the HTML and JavaScript code that implements the client-side system.

A GET request to /talks returns a JSON document like this:

{"serverTime": 1405438911833,
 "talks": [{"title": "Unituning",
            "presenter": "Carlos",
            "summary": "Modifying your cycle for extra style",
            "comment": []}]}

To make the long polling possible we are using the serverTime.
Creating a new talk is done by making a PUT request to a URL like /talks/Unituning, where the part after the second slash is the title of the talk. The PUT request’s body should contain a JSON object that has presenter and summary properties.

To make sure that there aren't any characters or spaces we cannot use in a URL we will use encodeURIComponent function

console.log("/talks/" + encodeURIComponent("How to Idle"));
//> /talks/How%20to%20Idle

A request to create a talk about idling might look something like this:

PUT /talks/How%20to%20Idle HTTP/1.1
Content-Type: application/json
Content-Length: 92

{"presenter": "Dana",
 "summary": "Standing still on a unicycle"}

Such URLs also support GET requests to retrieve the JSON representation of a talk and DELETE requests to delete a talk.

To add a comment to a talk we use the POST request to a URL.

POST /talks/Unituning/comments HTTP/1.1
Content-Type: application/json
Content-Length: 72

{"author": "Alice",
 "message": "Will you talk about raising a cycle?"}

changesSince is used to indicate that the client is interested in updates that happened since a given point in time. When there are such changes, they are immediately returned. When there aren’t, the response is delayed until something happens or until a given time period (we will use 90 seconds) has elapsed.

The serverTime property tells the client the precise time, from the server’s perspective, at which the data it receives was created.

GET /talks?changesSince=1405438911833 HTTP/1.1

(time passes)

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 95

{"serverTime": 1405438913401,
 "talks": [{"title": "Unituning",
            "deleted": true}]}

When a talk has been changed, has been newly created, or has a comment added, the full representation of the talk is included in the response to the client’s next polling request. When a talk is deleted, only its title and the property deleted are included. The client can then add talks with titles it has not seen before to its display, update talks that it was already showing, and remove those that were deleted.

This protocol does not have any access restrictions. To fix this we can put the system behind a reverse proxy, which is an HTTP server that accepts connections from outside the system and forwards them to HTTP servers that are running locally.

The server

Let's start with the server.

Routing

Our server will use http.createServer to start an HTTP server. In the function that handles a new request, we must distinguish between the various kinds of requests that we support. We will write one ourselves to illustrate the principle.

This is router.js, which we will later require from our server module:

var Router = module.exports = function() {
  this.routes = [];
};

Router.prototype.add = function(method, url, handler) {
  this.routes.push({method: method,
                    url: url,
                    handler: handler});
};

Router.prototype.resolve = function(request, response) {
  var path = require("url").parse(request.url).pathname;

  return this.routes.some(function(route) {
    var match = route.url.exec(path);
    if (!match || route.method != request.method)
      return false;

    var urlParts = match.slice(1).map(decodeURIComponent);
    route.handler.apply(null, [request, response]
                                .concat(urlParts));
    return true;
  });
};

Serving files

When a request matches none of the request types defined in our router, the server must interpret it as a request for a file in the public directory. We will use use a solid, well-tested static file server from NPM.

We will go for ecstatic, although this is not the only option. The ecstatic module exports a function that can be called with a configuration object to produce a request handler function. We use the root option to tell the server where it should look for files. The handler function accepts request and response parameters and can be passed directly to createServer to create a server that serves only files.

We want to first check for requests that we handle specially, though, so we wrap it in another function.

var http = require("http");
var Router = require("./router");
var ecstatic = require("ecstatic");

var fileServer = ecstatic({root: "./public"});
var router = new Router();

http.createServer(function(request, response) {
  if (!router.resolve(request, response))
    fileServer(request, response);
}).listen(8000);

The respond and respondJSON helper functions are used throughout the server code to send off responses with a single function call.

function respond(response, status, data, type) {
  response.writeHead(status, {
    "Content-Type": type || "text/plain"
  });
  response.end(data);
}

function respondJSON(response, status, data) {
  respond(response, status, JSON.stringify(data),
          "application/json");
}

Talks as resources

The server keeps the talks that have been proposed in an object called talks, whose property names are the talk titles.

var talks = Object.create(null);

router.add("GET", /^\/talks\/([^\/]+)$/,
           function(request, response, title) {
  if (title in talks)
    respondJSON(response, 200, talks[title]);
  else
    respond(response, 404, "No talk '" + title + "' found");
});

Deleting a talk is done by removing it from the talks object.

router.add("DELETE", /^\/talks\/([^\/]+)$/,
           function(request, response, title) {
  if (title in talks) {
    delete talks[title];
    registerChange(title);
  }
  respond(response, 204, null);
});

registerChange notifies waiting long-poll requests that there is a change.

To retrieve the content of JSON-encoded request bodies we need to read all content from a stream, parse it as JSON, and then call a callback

function readStreamAsJSON(stream, callback) {
  var data = "";
  stream.on("data", function(chunk) {
    data += chunk;
  });
  stream.on("end", function() {
    var result, error;
    try { result = JSON.parse(data); }
    catch (e) { error = e; }
    callback(error, result);
  });
  stream.on("error", function(error) {
    callback(error);
  });
}

The PUT handler needs to read JSON responses. It has to check whether the data it was given has presenter and summary properties.
If the data looks valid, the handler stores an object that represents the new talk in the talks object, possibly overwriting an existing talk with this title, and again calls registerChange.

If the data looks valid, the handler stores an object that represents the new talk in the talks object, possibly overwriting an existing talk with this title, and again calls registerChange.

router.add("PUT", /^\/talks\/([^\/]+)$/,
           function(request, response, title) {
  readStreamAsJSON(request, function(error, talk) {
    if (error) {
      respond(response, 400, error.toString());
    } else if (!talk ||
               typeof talk.presenter != "string" ||
               typeof talk.summary != "string") {
      respond(response, 400, "Bad talk data");
    } else {
      talks[title] = {title: title,
                      presenter: talk.presenter,
                      summary: talk.summary,
                      comments: []};
      registerChange(title);
      respond(response, 204, null);
    }
  });
});

Adding a comment to a talk works similarly.

router.add("POST", /^\/talks\/([^\/]+)\/comments$/,
           function(request, response, title) {
  readStreamAsJSON(request, function(error, comment) {
    if (error) {
      respond(response, 400, error.toString());
    } else if (!comment ||
               typeof comment.author != "string" ||
               typeof comment.message != "string") {
      respond(response, 400, "Bad comment data");
    } else if (title in talks) {
      talks[title].comments.push(comment);
      registerChange(title);
      respond(response, 204, null);
    } else {
      respond(response, 404, "No talk '" + title + "' found");
    }
  });
});

Tomorrow we will continue 🙂

Day 41. Project 5: Skill-sharing website Part 2

Today is my last post on this JavaScript hike. I'm sure there will be many more about JavaScript and also the exercises! It sure has been a long, tiring but very rewarding experience!

Long-polling support

Time for the part that handles long polling. When a GET request comes in for /talks, it can be either a simple request for all talks or a request for updates, with a changesSince parameter.

First we need a a small helper function that attaches the serverTime field to such responses.

function sendTalks(talks, response) {
  respondJSON(response, 200, {
    serverTime: Date.now(),
    talks: talks
  });
}

The handler itself needs to look at the query parameters in the request’s URL to see whether a changesSince parameter is given.

router.add("GET", /^\/talks$/, function(request, response) {
  var query = require("url").parse(request.url, true).query;
  if (query.changesSince == null) {
    var list = [];
    for (var title in talks)
      list.push(talks[title]);
    sendTalks(list, response);
  } else {
    var since = Number(query.changesSince);
    if (isNaN(since)) {
      respond(response, 400, "Invalid parameter");
    } else {
      var changed = getChangedTalks(since);
      if (changed.length > 0)
         sendTalks(changed, response);
      else
        waitForChanges(since, response);
    }
  }
});

When the changesSince parameter is missing, the handler simply builds up a list of all talks and returns that.

The getChangedTalks function, to be defined shortly, returns an array of changed talks since a given point in time. If it returns an empty array, the server does not yet have anything to send back to the client, so it stores the response object (using waitForChanges) to be responded to at a later time.

var waiting = [];

function waitForChanges(since, response) {
  var waiter = {since: since, response: response};
  waiting.push(waiter);
  setTimeout(function() {
    var found = waiting.indexOf(waiter);
    if (found > -1) {
      waiting.splice(found, 1);
      sendTalks([], response);
    }
  }, 90 * 1000);
}

To be able to find exactly those talks that have been changed since a given point in time, we need to keep track of the history of changes.

var changes = [];

function registerChange(title) {
  changes.push({title: title, time: Date.now()});
  waiting.forEach(function(waiter) {
    sendTalks(getChangedTalks(waiter.since), waiter.response);
  });
  waiting = [];
}

When building that array, getChangedTalks has to ensure that it doesn’t include the same talk twice:

function getChangedTalks(since) {
  var found = [];
  function alreadySeen(title) {
    return found.some(function(f) {return f.title == title;});
  }
  for (var i = changes.length - 1; i >= 0; i--) {
    var change = changes[i];
    if (change.time <= since)
      break;
    else if (alreadySeen(change.title))
      continue;
    else if (change.title in talks)
      found.push(talks[change.title]);
    else
      found.push({title: change.title, deleted: true});
  }
  return found;
}

Time to move onto the client.

The Client

The client-side part of the talk-managing website consists of three files: an HTML page, a style sheet, and a JavaScript file.

HTML
We will name our file index.html(as it is most conventionally used for web servers and easier for the sile server module we are using to detect it).

Thus, if we want a page to show up when a browser is pointed at our server, we should put it in public/index.html. This is how our index file starts:

<!doctype html>

<title>Skill Sharing</title>
<link rel="stylesheet" href="skillsharing.css">

<h1>Skill sharing</h1>

<p>Your name: <input type="text" id="name"></p>

<div id="talks"></div>

It defines the document title and includes a style sheet, which defines a few styles to, among other things, add a border around talks.

Next comes the form that is used to create a new talk.

<form id="newtalk">
  <h3>Submit a talk</h3>
  Title: <input type="text" style="width: 40em" name="title">
  <br>
  Summary: <input type="text" style="width: 40em" name="summary">
  <button type="submit">Send</button>
</form>

To create DOM structures for the talks, our program will define a simple templating system, which uses hidden DOM structures included in the document to instantiate new DOM structures, replacing the placeholders between double braces with the values of a specific talk.

<div id="template" style="display: none">
  <div class="talk">
    <h2>{{title}}</h2>
    <div>by <span class="name">{{presenter}}</span></div>
    <p>{{summary}}</p>
    <div class="comments"></div>
    <form>
      <input type="text" name="comment">
      <button type="submit">Add comment</button>
      <button type="button" class="del">Delete talk</button>
    </form>
  </div>
  <div class="comment">
    <span class="name">{{author}}</span>: {{message}}
  </div>
</div>

Finally, the HTML document includes the script file that contains the client-side code.

<script src="skillsharing_client.js"></script>

Starting up

The first thing the client has to do when the page is loaded is ask the server for the current set of talks. Since we are going to make a lot of HTTP requests, we will again define a small wrapper around XMLHttpRequest.

function request(options, callback) {
  var req = new XMLHttpRequest();
  req.open(options.method || "GET", options.pathname, true);
  req.addEventListener("load", function() {
    if (req.status < 400)
      callback(null, req.responseText);
    else
      callback(new Error("Request failed: " + req.statusText));
  });
  req.addEventListener("error", function() {
    callback(new Error("Network error"));
  });
  req.send(options.body || null);
}

The initial request displays the talks it receives on the screen and starts the long-polling process by calling waitForChanges.

var lastServerTime = 0;

request({pathname: "talks"}, function(error, response) {
  if (error) {
    reportError(error);
  } else {
    response = JSON.parse(response);
    displayTalks(response.talks);
    lastServerTime = response.serverTime;
    waitForChanges();
  }
});

The lastServerTime variable is used to track the time of the last update that was received from the server.

When the request fails we want our page to do something. So we define a simple function called reportError, which at least shows the user a dialog that tells them something went wrong.

function reportError(error) {
  if (error)
    alert(error.toString());
}

Displaying Talks

To be able to update the view of the talks when changes come in, the client must keep track of the talks that it is currently showing.

The function displayTalks is used both to build up the initial display and to update it when something changes. It will use the shownTalks object, which associates talk titles with DOM nodes, to remember the talks it currently has on the screen.

var talkDiv = document.querySelector("#talks");
var shownTalks = Object.create(null);

function displayTalks(talks) {
  talks.forEach(function(talk) {
    var shown = shownTalks[talk.title];
    if (talk.deleted) {
      if (shown) {
        talkDiv.removeChild(shown);
        delete shownTalks[talk.title];
      }
    } else {
      var node = drawTalk(talk);
      if (shown)
        talkDiv.replaceChild(node, shown);
      else
        talkDiv.appendChild(node);
      shownTalks[talk.title] = node;
    }
  });
}

Building up the DOM structure for talks is done using the templates that were included in the HTML document. First, we must define instantiateTemplate, which looks up and fills in a template.

function instantiateTemplate(name, values) {
  function instantiateText(text) {
    return text.replace(/\{\{(\w+)\}\}/g, function(_, name) {
      return values[name];
    });
  }
  function instantiate(node) {
    if (node.nodeType == document.ELEMENT_NODE) {
      var copy = node.cloneNode();
      for (var i = 0; i < node.childNodes.length; i++)
        copy.appendChild(instantiate(node.childNodes[i]));
      return copy;
    } else if (node.nodeType == document.TEXT_NODE) {
      return document.createTextNode(
               instantiateText(node.nodeValue));
    } else {
      return node;
    }
  }

  var template = document.querySelector("#template ." + name);
  return instantiate(template);
}

This is a crude approach to templating, but it is enough to implement drawTalk.

function drawTalk(talk) {
  var node = instantiateTemplate("talk", talk);
  var comments = node.querySelector(".comments");
  talk.comments.forEach(function(comment) {
    comments.appendChild(
      instantiateTemplate("comment", comment));
  });

  node.querySelector("button.del").addEventListener(
    "click", deleteTalk.bind(null, talk.title));

  var form = node.querySelector("form");
  form.addEventListener("submit", function(event) {
    event.preventDefault();
    addComment(talk.title, form.elements.comment.value);
    form.reset();
  });
  return node;
}

After instantiating the "talk" template, there are various things that need to be patched up. First, the comments have to be filled in by repeatedly instantiating the "comment" template and appending the results to the node with class "comments". Next, event handlers have to be attached to the button that deletes the task and the form that adds a new comment.

Updating the server

The event handlers registered by drawTalk call the function deleteTalk and addComment to perform the actual actions required to delete a talk or add a comment. These will need to build up URLs that refer to talks with a given title, for which we define the talkURL helper function.

function talkURL(title) {
  return "talks/" + encodeURIComponent(title);
}

The deleteTalk function fires off a DELETE request and reports the error when that fails.

function deleteTalk(title) {
  request({pathname: talkURL(title), method: "DELETE"},
          reportError);
}

Adding a comment requires building up a JSON representation of the comment and submitting that as part of a POST request.

function addComment(title, comment) {
  var comment = {author: nameField.value, message: comment};
  request({pathname: talkURL(title) + "/comments",
           body: JSON.stringify(comment),
           method: "POST"},
          reportError);
}

We also wire up that field to localStorage so that it does not have to be filled in again every time the page is reloaded.

var nameField = document.querySelector("#name");

nameField.value = localStorage.getItem("name") || "";

nameField.addEventListener("change", function() {
  localStorage.setItem("name", nameField.value);
});

The form at the bottom of the page, for proposing a new talk, gets a "submit" event handler.

var talkForm = document.querySelector("#newtalk");

talkForm.addEventListener("submit", function(event) {
  event.preventDefault();
  request({pathname: talkURL(talkForm.elements.title.value),
           method: "PUT",
           body: JSON.stringify({
             presenter: nameField.value,
             summary: talkForm.elements.summary.value
           })}, reportError);
  talkForm.reset();
});

Noticing changes

Given the mechanism that we implemented in our server and the way we defined displayTalks to handle updates of talks that are already on the page, the actual long polling is simple.

function waitForChanges() {
  request({pathname: "talks?changesSince=" + lastServerTime},
          function(error, response) {
    if (error) {
      setTimeout(waitForChanges, 2500);
      console.error(error.stack);
    } else {
      response = JSON.parse(response);
      displayTalks(response.talks);
      lastServerTime = response.serverTime;
      waitForChanges();
    }
  });
}

If you run the server and open two browser windows for localhost:8000/ next to each other, you can see that the actions you perform in one window are immediately visible in the other.

I hope you enjoyed this hike as much as I did 🙂