More JavaScript Programming plus Dates

Reading: JavaScript and JQuery pp 70-75, pp 144-146 on object literals, and pp 450-457 on dates and times.

Review: JS Values, Expressions, and Statements

What have we learned about JavaScript so far?

Here's a sample sequence of variable declarations:

var daysInYear = 365;                     // might sometimes be 366
var minutesInDay = 60 * 24;               // really a constant
var minutesInYear = daysInYear * minutesInDay; 

In the first declaration, the right-hand side is a simple number value, 365, which is assigned to the variable daysInYear. In the second declaration, the right-hand side is a more complex expression that evaluates to 1440, which is then assigned to minutesInDay. In the last declaration, the right-hand side is an expression involving the variables daysInYear and minutesInDay. Since daysInYear has the value 365 and minutesInDay has the value 1440 when this assignment occurs, the expression daysInYear * minutesInDay evaluates to 525600, which is then assigned to the variable minutesInYear.

daysInYear = 365;
365

daysInYear
minutesInDay = 60 * 24;
365

daysInYear
1440

minutesInDay
minutesInYear = daysInYear * minutesInDay;
365

daysInYear
1440

minutesInDay
525600

minutesInYear

Displaying the Date Dynamically

We can display the current date and time on a web page. For example, the following box is a div with id = date_today:

You loaded this page on at

If you reload this page, you'll notice that the date and time change appropriately.

Before we explain the JavaScript code that can do this, we need to understand how time is represented in JavaScript. We begin by creating a Date object:

var dateObj2 = new Date(); 

As we've seen before, the keyword var in var dateObj2 creates a new variable box named dateObj2 for storing a value. What we haven't seen before is the keyword new, which causes a JavaScript object to be created. In this case, the object represents the current date and time. JavaScript comes equipped with lots of pre-defined object types like Date. Stay tuned for a description of objects.

We can extract information from a Date object by invoking methods on it. The table below shows some of the important methods that Date objects understand. The elements of the Value column are dynamically computed by evaluating the JavaScript expressions in the Expression column, so reloading the page will update these appropriately.

Expression Value Notes
dateObj2.getFullYear() Full year
dateObj2.getYear() Avoid this! Varies from browser to browser
dateObj2.getMonth() 0=Jan, 1=Feb, ..., 11=Dec
dateObj2.getDate() 1 to 31
dateObj2.getDay() 0=Sun, 1=Mon, ..., 6=Sat
dateObj2.getHours() 0 to 23
dateObj2.getMinutes() 0 to 59
dateObj2.getSeconds() 0 to 59
dateObj2.getTime() Milliseconds since Jan 1, 1970 (the "epoch")

Objects

Dates are examples of objects. In JavaScript, an object is a kind of value that has two important characteristics:

Both properties and methods are selected from an object using dot notation. In the examples above, the variable now contains a date object. The expression to the left of the dot in dateObj2.getDate() is a variable, now, that contains a date object. To the right of the dot is the name of the thing we want to compute based on the object. In this case, we invoke the getDate() method, which returns the numerical day of the month in a date object. (You can tell we're calling a method rather than selecting a property by the presence of parentheses after the name.)

W3 Schools has a complete list of methods for Date objects.

Date Formatting

Now let's return to our date and time display. A date object contains a collection of information about the date and time, but for human-readability, we will need to format that data in some conventional way, using, for example, slashes and commas to separate the various numbers.

Here is the date, formatted as is done in the United States and a small handful of other countries. It is formatted into the following box which is a div with id = date_today2. This box has text in Spanish.

<div id="date_today2">Ha cargado esta página en <span class="date"></span>
  a las <span class="time"></span></div>
Ha cargado esta página en a las

Here is JavaScript code that does this (you can also view the page created by embedding this code in a complete HTML file for printing the date):

// create a Date object, representing this moment, and store it
var dateObj = new Date();

// format info about the day
var the_day = dateObj.getDate();
var the_month = dateObj.getMonth() + 1; // Add 1 because Jan is 0, etc.
var the_year = dateObj.getFullYear();
var current_date = the_month + "/" + the_day + "/" + the_year;

// format info about the time
var the_hour = dateObj.getHours();
var the_minute = dateObj.getMinutes();
var the_second = dateObj.getSeconds();
var current_time = the_hour + ":" + the_minute + ":" + the_second;

$('#date_today2 .date').text(current_date);
$('#date_today2 .time').text(current_time);

Let's examine the code. It is a sequence of JavaScript statements, which will be executed sequentially by the browser. The first statement creates a Date object representing the current date and time, and stores it in a variable named dateObj. Subsequent statements extract components of this Date object and piece them together. The final $().text() jQuery statements insert the two strings as the text in the two spans within the div with that id, thereby displaying the date and time on the page. The surrounding text is fixed.

As shown below, we could get by with only the single variable dateObj. Although the other variables are not strictly necessary, they can help to make the code more readable. Note that there's nothing special about naming the variable dateObj. We could have called it anything else, such as today or now or fred (but fred would not be a good name, since it wouldn't suggest the meaning or value of the data).

// create a Date object, representing this moment, and store it
var dateObj = new Date();

$('#date_today2 .date').text( (dateObj.getMonth() + 1) + "/"
                             + dateObj.getDate() + "/"
                             + dateObj.getFullYear());
$('#date_today2 .time').text( dateObj.getHours() + ":"
                              + dateObj.getMinutes() + ":"
                              + dateObj.getSeconds());

Practice the behavior of the code by using the execution box below. Change the code to display the date in the format that most of the world uses, namely, DD/MM/YYYY.

Remember:

Exercise on Date Formatting


Other Methods

We've used the example of dates to teach you about:

Lots of other objects and methods exist in JavaScript. One we already met, namely document.write(): the document is an object (a browser has more than one), and one method for operating on that object is to write some more text into it. We won't be using this method, but you know about it from your reading.

Here's another method, this time on numbers, the toFixed() method:


The toFixed() method returns a string representation of the number, with the number of decimal places given by the argument. It does not change the value of the variable, as the last step shows.

Re-assigning Variables

In all of our examples so far, we have created new variables to assign the next step of the calculation to.

Here's an example of poor use of re-assignment:


Ask yourself: what kind of value does val hold? It depends on where in the code you're looking; it changes from place to place. That's why we gave the variable such a vague and unhelpful name: we couldn't use anything more specific. In fact, the value even changes datatype from place to place (in the last assignment, it becomes a string). Since we know that the + operator treats strings differently from numbers, this sort of confusion can be a big problem.

The moral here is that it's not good enough for the JavaScript program to work. The underlying JavaScript code should be easy to read and understand as well!

Good Re-assignment

Let's turn to that now. It makes sense to re-assign to a variable when it holds the same information (the same meaning and same datatype), but that the old value needs to be updated. For example, suppose you are counting something, and the count has changed. In an online shopping application, you might be counting the number of items the user has in her cart. Suppose that the variable item_count stores the current number of items in the cart. When she adds another item to the cart, you want to increase that variable's value by one. Here's how:

  item_count = item_count + 1;

Notice that if that were a mathematical equality statement, it would be impossible: no number can equal one more than itself. But this is not equality, this is assignment, so it says to take the current value of item_count, add one to it, and store that value back into the variable.

Here's a specific example, where we count mouse clicks:

How fast can you click? Click like mad in the yellow area, and then move out of the area to stop the timing.

click here

You clicked times in milliseconds, which is clicks per second.

Here's an execution box that will add one more click to your click count and report the current values.


There are three things worth noticing from the code above:

  1. When we re-assign a variable, we omit the var out front. The var tells JavaScript that we are creating a new variable, and, of course, when we are re-assigning, we aren't creating a new variable.
  2. Remember that = should be read as "gets". So in the first line, we are not saying that click_count is equal to click_count plus one. That would be impossible! Instead, we are saying that the value assigned to click_count should be updated to the current value of click_count plus one.

Shortcuts for Incrementing a Variable

Increasing a variable by some amount is such a common operation in programming that most languages have a shortcut syntax, and JavaScript is no exception. For example, the following two statements mean the same thing:

  item_count = item_count + 1;
  item_count += 1;

In fact, increasing a variable by one is so common that there's an even shorter cut. All three of the following mean the same thing:

  item_count = item_count + 1;
  item_count += 1;
  item_count++;

All these do is save you some typing. You don't need to use them if you don't want to.

Swapping Values is Tricky!

Re-assignment also occurs when we are moving values around. For example, suppose we are keeping a high score list of the fastest clicking users. If someone moves up on the list (gets a new personal best), we may need to sort the list. One important step in sorting is swapping values.

Digging into real sorting algorithms is outside the scope of this course, but we do want to look at the issue of swapping values, because it brings up some important issues about how computation works.

Suppose that we declare two variables as follows:

var elmo = 21;
var grover = 18;

How can we swap the values in the two variables? That is, how can we change elmo to have grover's value of 18 and change grover to have elmo's value of 21?

The following solution attempt does not work. Why?

elmo   = grover;
grover = elmo; 
Use the execution box below (1) to verify that the above solution does not work and (2) to develop a solution that does work.

Note: Your code should work no matter what values are in the two variables. We are using 18 and 21 for concreteness only, but your code should work if they are 7 and 27 or 3 and 92 or ...

Exercise on Swapping Values


The important points are these:

Debugging JavaScript

Debugging JavaScript is generally much harder than debugging HTML. As we've seen, JavaScript has at least two built-in datatypes (numbers, strings), plus additional kinds of things such as the Date object, which have their own rules and constraints. In HTML on the other hand, a tag is either recognized or it's ignored. There's visual feedback when a tag is recognized, so you can usually figure out what to do, sometimes with a little trial and error. That's not to say that HTML is easy, only that it is easier.

Another thing that makes JavaScript harder to debug is that the browsers are written with regular web surfers in mind, not web page authors. Therefore, the browsers do their best to ignore and suppress JavaScript errors: they are actively trying to hide the errors from you! We already discussed this in a previous lecture; here is a link to the reference material on debugging JavaScript

To test your debugging, visit this page that has some JavaScript Errors.

Note that the errors we are discussing in this section are syntax errors. The syntax of a programming language is the set of rules about punctuation (where the commas and semi-colons go), the order of elements (variables on the left side of an assignment, expressions on the right), and so forth. These debuggers can help you find and fix those, but they cannot help you with logic errors, such as writing “age < 18” when you meant to write “age > 18”. These are hard to debug, too, because the code “works” in the sense of producing no errors, but it does the wrong thing. Your best strategy is to use alert() to check whether you are getting to the place in the code that you expect and whether variables have the values you expect.

Good luck!

Other Date Functions

The earlier date manipulation code was all numerical. That's partly because JavaScript is global, and they decided not to have a built-in function to map month zero to January when it could just as easily have been Janvier (French), Enero (Spanish) or Styczen (Polish).

Despite this, we decided to implement a simple function that maps month-numbers (ranging from 0 to 11) to English month-names. Try it out:


Exercise How would you print the name of the month 10 months from now?

Multiple Date Objects

Often with objects we will have more than one of them. The methods operate on them in similar ways, yielding similar values, but unique to that object. Here's an example that uses two date objects, so that we can measure the time-difference between them:

The Date() function makes things called objects. For, example, the following code creates two date objects, stored in different variables (start_time and end_time), so that we can determine how long it takes to compute the TOC:

  var start_time = new Date();
  computeTOC();   // build the table of contents
  var end_time = new Date();
  var elapsed = end_time.getTime() - start_time.getTime();
  console.log("building the TOC took "+elapsed+" milliseconds");

JavaScript Object Literals

It's now time to return to talking about JavaScript objects in general rather than just date objects.

In JavaScript, an object is a collection of data (properties and methods, as we say in our early definition of objects). This collection can be arbitrarily complex, including having other objects inside the containing object (much like a folder can contain other folders), but for now let's keep it simple:

A object is a collection of properties (also called keys) and values. We use the properties (keys) to look up the values. We'll use the terms properties and keys interchangeably

We'll ignore methods for now and focus on properties.

Let's be concrete. Imagine that we have an object to keep track of a user's info, including their name, year of graduation and whether they're going to the party. So, the three properties will be: (1) name, (2) gradYear, and (3) going.

We'll begin with a particular person, Alice, who is the class of 2013 and is going to the party. We'll store all that info in a single object and we'll store the object in a variable called person1. We can make a second object about another person, Betty.

Consider the following JavaScript code:

var person1 = {name: "Alice", gradYear: 2013, going: "yes"};
var person2 = {name: "Betty", gradYear: 2014, going: "no"};

Try copy/pasting that code into a JavaScript console. Look at the resulting objects:

>>> person1
>>> person2

Firebug even has a cool dir feature that breaks out all the properties into separate, clickable things. This is particularly useful for big, complicated objects, such as windows. Try it:

>>> dir(person1)
>>> dir(window)

Let's repeat those assignment statements, together with an abstraction:

  var person1 = {name: "Alice", gradYear: 2013, going: "yes"};
  var person2 = {name: "Betty", gradYear: 2014, going: "no"};
  var person2 = {prop1: value1, prop2: value2, prop3: value3};

The things on the right hand side are called object literals. The syntax of an object literal is an opening brace, a series of property/value pairs separated by commas, and a closing brace. Each property/value pair consists of a property (which follows the same rules as the names of variables), a colon, and a value. The value can be any JavaScript value, such as a number, string, or another object. Each of these object literals has three property/value pairs, but a JavaScript object can have any number of pairs, including none:

  var empty_person = {};

Using Object Literals

One use for the object literal syntax is to collect several related items so that you can refer to them as a collection instead of separate pieces of information. For example, the jQuery .css() method allows you to change a CSS property of the selected elements, but if you pass in an object literal of several changes, you can change them all at once. For, example, consider the following box:

This is CSS Box 1

This sets the width and height in two steps:


This sets the width and height in one step:


You can even animate the transitions:

This is CSS Box 2

This animates the box getting bigger.


And this animates the box getting smaller.


Notice how in the animations we packaged up our target measures into an object, stored that object in a variable with a nice, helpful name, and then referred to the variable in the animate() method.

Summary

Further Information

Beyond here is information that we think you might find interesting and useful, but which you will not be responsible for yet. It's for the intellectually curious student. We will be getting to many of these concepts a bit later in the course, so it would useful to pass your eyes over this once, just to start the learning process. Don't worry if some of it doesn't make sense yet.

JSON.stringify()

One of our go-to debugging tools is to use the alert function to report a value. Unfortunately, alert doesn't work so well with objects. Try it:


Fortunately, there's an easy solution. All modern browsers have a JSON object that has a method called stringify. The stringify method takes an JavaScript Object and converts it into a string. You can then hand that string to the alert function:


Object Operations

Given an object, there are a few things you might want to do (operations on it):

Here are some specific examples of those operations with the person1 object:


You'll notice that the way we add a new property/value pair is identical to the way we modify an existing property/value pair: just an assignment statement. That's because JavaScript creates the property if necessary, and then updates the value. In practice, removing a property/value pair is rarely done, so we really only need to remember two operations: getting and setting.

Here are two assignment statements that demonstrate both getting and setting. On the right hand side, we get a value out of one object and on the left hand side we set a value of an object.


The syntax for getting and setting look the same: a variable, a dot, and a property.

The markers on a Google Map are another example of objects. Those markers are objects with properties like lat and lng (latitude and longitude), along with other info. For example, something like:

  var marker1 = {lng: 42.296612,lat: -71.301956}; // Wellesley

Unknown or Odd Properties

The syntax we learned above to get and set a value in an object (variable.property) is simple and effective but fails in two cases: if the property is unknown and if the property contains odd characters, such as spaces or hyphens.

For example, suppose instead of calling the property gradYear, we wanted to call it grad year (with a space in it). The following doesn't work at all:

person1.grad year = 2014;

Usually, we can get around this very simply by limiting ourselves to property names that don't have spaces, hyphens, semi-colons and other oddities.

A slightly more difficult case comes where we don't know the property in advance. For example, we have an object that stores the dimensions of an image, with properties width and height. We want to retrieve the larger dimension, and we've stored the property in a variable called larger_dim. The following fails, because it tries to look up a property named larger_dim instead of one named height.


There is a solution to both problems: the syntax to get/set a value in an object can be a string in square brackets. Here's an example that works. Note that the expression in the square brackets is a literal string.


Here's the same syntax used to solve the second problem of an unknown property. Note that here, the expression in the square brackets is a variable (larger_dim) that contains a string.


In fact, if you want to, you can always use the square bracket notation, and ignore the dot notation. For example:


However, most programmers appreciate the brevity and reduced punctuation of the dot notation, so you will see it a lot.

Looping over an Object's Properties

Sometimes it's useful to be able to loop over all the properties of an object. JavaScript has a built-in syntax, a special kind of loop, for doing just that. For example, the following will alert all the properties in an object:


The following variation alerts all the values in an object. Note that using the square bracket notation is necessary here, because each time through the loop the variable prop has a different value.


The syntax for this loop is

    for ( P in OBJ ) {
        // loop body here
    }

We haven't studied loops, and we generally won't, so this topic is outside the scope of this class (though just barely). Nevertheless, the basic idea is that the code in the braces (called the body of the loop) is executed many times, once for each property in the object. The P is a new variable (like one created by the var keyword) and it is given a value (as if by an assignment statement) before each time through the body of the loop. Those values will the properites of the object. The OBJ is an existing variable that holds an existing object.

Here's one last example, which counts the number of properties in an object. Note the shortcut for incrementing the counter.


Solutions to Exercises