Skip to content

Latest commit

 

History

History
1820 lines (1233 loc) · 102 KB

ch2_advancedjs.asciidoc

File metadata and controls

1820 lines (1233 loc) · 102 KB

Advanced Introduction to JavaScript

This chapter is dedicated to the JavaScript programming language. Our challenging goal is "From Zero to Hero in 50 pages". While in the future chapters you’ll see how JavaScript frameworks can greatly minimize the amount of the JavaScript code that you need to write manually, you still need to understand the language itself.

This chapter starts with basics of the language, but then it quickly progresses to such advanced topics as prototypal inheritance, callbacks, and closures. If you prefer fat manuals covering each and every detail of programming languages, we can recommend you the book "JavaScript: The Definite Guide", Sixth Edition by David Flanagan.

Besides the JavaScript coverage this chapter includes a section on the tools (IDEs, debuggers, Web inspectors et al.) that will make your development process more productive.

Important
While you can skip some sections of this book as not relevant to your needs, we recommend you to read each section of this chapter in order. Most of the materials presented here expect you to understand the previous content of this chapter.

JavaScript: A Brief History

The JavaScript programming language was designed in 1995 by Brendan Eich, who was working for Netscape Communications Corporation at the time. His goal was to allow developers create more interactive Web pages. Initially the name of this language was Mocha, then LiveScript, and finally Netscape agreed with Sun Microsystems, creator of Java to rename it to JavaScript.

A year later, the language was given to an international standards body called ECMA, which formalized the language into ECMAScript standard so that other Web browser vendors could create their implementation of this standard. JavaScript is not the only language created based on the ECMAScript specification - ActionScript is a good example of another popular dialect of ECMAScript.

To learn more about the history of JavaScript from the source watch the Brendan Eich’s presentation "JavaScript at 17" at O’Reilly’s conference Fluent 2012.

Vast majority of today’s JavaScript code is being executed by the Web browsers, butthere are JavaScript engines that can execute JavaScript code independently. For example, Google’s V8 JavaScript engine implements ECMAScript 5 and is used not only in the Chrome browser, but can run in a standalone mode and can be embedded in any C++ application. Using the same programming language on the client and the server is the main selling point of node.js, which runs in V8. Oracle’s Java Development Kit (JDK) 8 will include the JavaScript engine Nashorn that not only can run on both the server and the client computers, but also allows to embed the fragments of JavaScript into Java programs.

In the 90th, JavaScript was considered a second class language used mainly for prettifying Web pages. In 2005 the techniques known as AJAX (see Chapter 4) made a significant impact to the way Web pages were built. With AJAX, the specific content inside the Web page could be updated without the need to make a full page refresh. For example, Google’s gmail that inserts just one line at the top of your input box whenever the new email arrives - it doesn’t re-retrieve the entire content of your Inbox from the server.

AJAX gave a second birth to JavaScript. But the vendors of Web browsers were not eager to implement the latest specifications of ECMAScript. Browsers’ incompatibility and lack of good development tools prevented JavaScript from becoming the language of choice for Web applications. Let’s not forget about the ubiquitous Flash Player – an excellent VM supported by all desktop Web browsers. Rich Internet Applications written in ActionScript were compiled into the byte code and executed by Flash Player on the user’s machine inside the Web browser.

If AJAX saved JavaScript, then rapid proliferation of tablets and smartphones made it really hot. Today’s mobile devices come equipped with modern Web browsers, and in the mobile world there is no need to make sure that your Web application will work in the 4-year old Internet Explorer 8. Adobe’s decision to stop supporting Flash Player in the mobile Web browsers is yet another reason to turn to JavaScript if your Web application has to be accessed from smartphones or tablets.

ECMASript, 5th Edition has been published in 2009 and is currently supported by all modern Web browsers. If you are interested in discovering if specific features of ECMAScript 5 are supported by a particular Web browser, check the latest version of the ECMAScript 5 compatibility table. At the time of this writing the snapshot of the Chrome Browser v. 22 looks as in ECMAScript 5 Compatibility Sample Chart below:

fig 02 01
Figure 1. ECMAScript 5 Compatibility Sample Chart

JavaScript became the lowest common denominator available on thousands of different devices. Yes, the JavaScript engines are not exactly the same on thousands devices that people use to login to Facebook, but they are pretty close, and using some of the JavaScript frameworks spare you from worrying about their incompatibilities.

JavaScript is an interpreted language that arrives to the Web browser as text. The JavaScript engine optimizes and compiles the code before the execution. If the JavaScript engine is a part of a Web page, the browser will load and execute the JavaScript code embedded or referenced between the HTML tags <script> and </script>. JavaScript was originally created for Web browsers, which were supposed to display whatever content has successfully arrived. What if an image has not arrived from the server? You’ll see a broken image icon. What if erroneous JavaScript code with syntax errors has arrived to the browser? Well, the engine will try to execute whatever has arrived. The end users may appreciate such browser’s forgiveness when at least some content is available, but the software developers should be ready to spend more time debugging (in multiple browsers) the errors that could have been caught by compilers in other programming languages.

Why Declaring JavaScript Variables

JavaScript is a weakly typed language hence the developers don’t have a luxury of strong compiler’s help that Java or C# developers enjoy. This is easily explainable. Imagine that if in Java or C# instead of declaring variables of specific data types everything would be of type Object, and you could assign to it any value – a string, a number, or a custom object Person. This would substantially complicate the ability of the compiler to weed out all possible errors. You don’t need to declare variables in JavaScript – just assign a value and the JavaScript engine will figure out the proper type during the execution of your code.For example, the variable named girlfriend will have a data type of String:

girlfriendName=“Mary”;

Since I haven’t used the keyword var in front of girlfriend, this variable will have the global scope. Variables declared with var inside functions are local. Consider the following function declaration:

function addPersonalInfo(){
   var address ="123 Main Street";      // local String variable
   age=25;                              // global Number variable
   var isMarried = true;                // local boolean variable
       isMarried = "don't remember";    // now it's of String type
}

The variables address and isMarried are visible only inside the function addPersonalInfo(). The variable age becomes global because of omission of the keyword var. In Chapter 3, you’ll see an example of how to limit the scope of the variables to avoid polluting the global name space.

The variable isMarried changes its type from Boolean to String during the execution of the above script, and JavaScript engine won’t complain assuming that the programmer knows what she’s doing. So be ready for the run-time surprises and allocate a lot more time for testing than with programs written in compiled languages.

Yet another moving part is the JavaScript engine where your code will run. Unless you are developing for strictly controlled enterprise environment you can’t assume that the end-user will have the same runtime as yours. You must test your code in multiple Web browsers.

Which IDE to Use

Selecting an Integrated Development Environment (IDE) that supports JavaScript is a matter of your personal preference. Since there is no compilation stage and most of your debugging will be done using the Web browser tools, picking a text editor that supports syntax highlighting is all that most developers need. For example, there is an excellent commercial text editor Sublime Text 2. Among many programming languages this editor understands the keywords of HTML, CSS, and JavaScript, and it offers not only syntax highlighting, context sensitive help, and auto-complete too.

If you are coming from the Java background, the chances are that you are familiar with free and open sourced Eclipse IDE. In this case install the Eclipse plugin VJET by eBay.

Oracle’s IDE NetBeans 7.3 and above support HTML5 and JavaScript development and includes JavaScript debugger that allows your code to connect to the Web browser, while debugging inside the IDE. If you prefer Microsoft technologies, they offer excellent JavaScript support in Visual Studio 2012.

In this book we’ll use an Eclipse-based Aptana Studio 3 IDE. Aptana Studio is available free of charge. Aptana Studio comes with embedded Web Server so you can test your JavaScript code without the need to start any additional software. In this chapter we’ll use Aptana Studio IDE to illustrate the features of JavaScript, and in the next chapter you’ll be working with a number of Aptana projects that will lead you through the development of the first version of our Save Sick Child Web application.

For the real world development we recommend using commercial IDE WebStorm from JetBrains. In addition to smart context sensitive help, auto-complete, and syntax highlighting it offers HTML5 templates, and the code coverage feature that identifies the code fragment that haven’t been tested. All of the editors and IDEs listed here are either available for free or are priced in the area of $60 USD. Try them all and pick the one that best fits your coding habits.

Getting Familiar with Aptana IDE

Download and install Aptana Studio 3 from http://aptana.com. Start Aptana and close the start page it displays by clicking on the little X on the tab. Then customize the color theme of this IDE by clicking the rainbow-colored circle on its toolbar. We usually select the theme called Eclipse. After the first start of Aptana you’ll see the message on the left side that reads ``There are no projects in your workspace. To get started, please create or import an existing one.''

If you want to start playing with the code samples that come with this book, click on the button Import Project, select the General | Archive file. Find the zip file you’d like to use, e.g. chapter2.zip, and press Finish. The project from the selected zip file will be imported into the Aptana’s workspace, which is nothing more than a folder on the disk where the source code will reside. When you work in Aptana IDE you see a set of views (panels). This set is called perspective. For Web projects Aptana uses Web perspective, which is indicated at the top right corner. Pressing the icon with a little pus sign at the top right allows to open another perspective with its own set of views.

Let’s get started with creating a project from scratch by pressing the button Create Project on the left. You could have also created a new Web Project using the File menu. On the next window you’ll need to select a wizard, and we’ll be always working with Web Projects throughout this book. The next window will offer you to select a project template - let’s stick to the simplest one - Default Project. Name it MyFirstProject.

To add an HTML file to this project select the menu File | New From Template | HTML | HTML5 Template. Aptana will offer you new_file.html the name of this file - no need to change it for now. Just press finish and you’ll see a window similar to the one shown on Aptana IDE with one HTML5 file.

fig 02 02
Figure 2. Aptana IDE with one HTML5 file

Right-click on the new_file.html and select the menu Run as JavaScript Web project. Don’t get upset that there is no JavaScript code there yet - we’ll add it pretty soon. Aptana starts its built-in Web server that by default runs on the port 8020 (it’s configurable in Aptana Preferences). The Web browser opens up and displays the page that looks like the one in Running MyFirstProject. Aptana has used its default template to generate HTML file. The template can be changed to your liking, and you can read about it in Aptana’s documentation at http://bitly.com/LRqRdU.

Tip
If you have your index.html open in Aptana’s editor, you can simply press the green triangle on the toolbar and run this file in the Web browser.
fig 02 03
Figure 3. Running MyFirstProject

To configure the Web Browser that Aptana should open by default, open its Preferences window and select the Web browser of your choice under the General section. Many examples in this chapter use the Firefox with installed add-on Firebug, so start with making Firefox your default browser.

Tip
you can find various HTML5 boilerplate projects on the Web that can be used as a starting point of your project. You don’t have to select the Aptana’s HTML5 boilerplate if it doesn’t fit your needs. For example, you can download a bare minimum boilerplate Shibui or more comprehensive HTML5 Boilerplate. Just download and unzip such a boilerplate project into your Aptana’s workspace and start adding your code, styles, and other resources.

Adding JavaScript to HTML

If your JavaScript is a part of HTML document, typically, you’ll be adding your <script> tags at the end of HTML file. The reason is simple - your JavaScript code may be manipulating with HTML elements, and you want them to exist by the time the script runs. The other way to ensure that the code is not running unless the Web page has loaded is by catching window’s load event, and you’ll see such example later in this chapter in the section on browser’s events. Some JavaScript frameworks may have their own approach to dealing with HTML content and in Chapter 7 you’ll see that the main HTML file of the Web application written with Ext JS framework has <script> tags followed by the empty <body> tags. But let’s keep things simple for now.

Add the following fragment at the very end (right above the closing </body> tag) of the new_file.html from Aptana IDE with one HTML5 file.

<script>
   alert("Hello from JavaScript");
</script>

Run the new_file.html in Aptana and you’ll see the following output in your Web browser:

fig 02 04
Figure 4. Running MyFirstProject with JavaScript at the bottom

Note that the Alert popup box is shown on top of the Web page that already rendered all of its HTML components. Now move the above code up to the end of the <head> section and re-run new_file.html. The picture is different now - the Alert box is shown before the HTML rendering is complete.

fig 02 05
Figure 5. Running MyFirstProject with JavaScript at the top

In this simple example this doesn’t cause any malfunctioning of the code, but if our JavaScript would need to manipulate with HTML elements, we’d run into issues of accessing non-existent components. Beside simple Alert box, JavaScript has Confirm and Prompt boxes, which allow asking OK/Cancel type of questions or request some input from the user.

Tip
In a real life you won’t be deploying your projects under Aptana’s internal Web server. When you code is tested you can FTP it to a remote server of your choice, e.g. Apache Web Server or IIS. Right-click on your Aptana project and select the menu option Publish. This will allow you to configure the FTP connection to your remote server and publish your working code there as you wish.

Debugging JavaScript in Web Browsers

The best way to learn any program is to run it step by step through a debugger. While some people appreciate using debuggers offered by Aptana, NetBeans, or Visual Studio, we prefer to debug using great tools offered by the major Web browsers:

  • Firefox: FireBug add-on

  • Chrome: Developer Tools

  • Internet Explorer: F12 Developer Tools

  • Safari: the menu Develop

  • Opera: Dragonfly

We’ll be doing most of the debugging in FireBug or Chrome Developer Tools. Both of them provide valuable information about your code and are easy to use. To get FireBug go to www.getfirebug.com and press the red button Install Firebug and follow the instructions. In Firefox, open the Firebug panel from the menu View.

fig 02 06
Figure 6. FireBug Console

Select the Console option on the Firebug toolbar and enter alert("Hello from JavaScript") after the >>> sign and you’ll see the Alert box. To enter multi-line JavaScript code press the little circle with a caret at the bottom right corner and FireBug will open a panel on the right, where you can enter and run your JavaScript code.

This was probably the last example where we used the Alert() popup box for debugging purposes. All JavaScript debuggers support the console.log() for printing debug information. Consider the following example that illustrate strict equality operator ===. Yes, it’s three equal signs in a row. This operator evaluates to true if the values are equal and the data types are the same.

var age=25;

var ageStr="25";

if (age==ageStr){
  console.log("The values of age and ageStr are equal");
}

if (age===ageStr){
 console.log("The values of age and ageStr are strictly equal");
} else{
 console.log ("The values of age and ageStr are not strictly equal");
}

Running this code in the FireBug console produces the following output:

fig 02 07
Figure 7. Using console.log() for the debug output
Tip
You can also use console.info(), console.debug(), and console.error() so the debuggers may highlight the output with different colors or mark with different icons.
Tip
For more information about debugging JavaScript refer to the code samples illustrated in Firebug’s Script panel and Firebug’s Script panel at a breakpoint.

JavaScript Functions. Gentle Introduction

Now comes the chicken or the egg dilemma. What should be explained first - functions or objects? Understanding of objects is needed for some of the function code samples and visa versa. We’ll start with simple function use cases, but will be switching to objects as needed.

Many of the readers can have experience with object-oriented languages like Java or C#, where classes can include methods implementing required functionality. Then these methods can be invoked with or without instantiation of the objects. If a JavaScript object includes functions they are called methods. But JavaScript functions don’t have to belong to an object. You can just declare a function and invoke it. Just like this:

//Function declaration
function calcTax (income, dependents){
   var tax;
   // Do stuff here
   return tax;
}

//Function invocation
calcTax(50000, 2);
var myTax = calcTax(50000,2);

Please note that the data types of the function parameters income and dependents are not specified. We can only guess that they are numbers based on their names. If a software developer won’t bother giving meaningful names to function parameters, the code becomes difficult to read. After the function calcTax() is invoked and complete, the variable myTax will have the value returned by the function. In the above code sample the JavaScript engine will not evaluate the function calcTax() until it’s actually invoked.

Another important thing to notice is that our function has a name calcTax. But this is not always the case - JavaScript allows functions to be anonymous. If you see the line of code where the keyword function is preceded by any other character this is not a function declaration, but a function expression. Consider the following variation of the tax calculation sample:

//Function expression
var doTax=function (income, dependents){
	//do stuff here
   return tax;
}

//Function invocation
var myTax=doTax(50000,2);

In the code above the function keyword is being used in the expression - we assign the anonymous function to the variable doTax. After this assignment just the text of the function is assigned to the variable doTax - the anonymous function is not being invoked just yet. It’s important to understand that even though the code of this anonymous function ends with return tax; actually, the tax calculation and return of its value is not happening until the doTax() is invoked. Only then the function is evaluated and the variable myTax will get whatever value this function returns.

Yet another example of a function expression is when it’s placed inside the grouping operator - parentheses as shown below:

(function calcTax (income, dependents){
   // Do stuff here
});

Another interesting concept of JavaScript is self-executing functions. Adding an extra pair of parentheses will cause the function expression located in the first set of parentheses to be executed right away.

(function calcTax (income, dependents){
   // Do stuff here
})();

The first set of parentheses hides its internal code from the outside world creating a scope or a closed ecosystem, where the function’s code will operate. Try to add a line invoking this function after the last line in the above code sample, e.g. calcTax(50000,2), and you’ll get an error - "calcTax is not defined". There is a way to expose some of the internal content of such a closure and you’ll see how to do it later in this chapter.

JavaScript Objects. Gentle Introduction

JavaScript objects are simply unordered collections of properties. You can assign new or delete existing properties from the objects during the runtime whenever you please. In classical object oriented languages there are classes and there are objects. For example, based on one Java a class you can create multiple instances of its objects.

Note
The ECMAScript 6 specification will include classes too, but since it’s a work in progress we won’t consider them as something useful in the today’s world. If you’d like to experiment with the upcoming features of JavaScript, download the Chrome Canary browser, go to chrome:flags and enable experimental JavaScript. Chrome Canary should be installed on the computer of any HTML5 developers - you can use today those features that will be officially released in Chrome Developers Tools in about three months.

In JavaScript you can create objects using one of the following methods:

  • Using object literals

  • Using new Object() notation

  • Using Object.create()

  • Using constructor functions and a new operator.

Note
In JavaScript everything is an Object. Think of Object as of a root of of the hierarchy of all objects used in your program. All your custom objects are descendants from Object.

Object Literals

The easiest way to create a JavaScript object is by using the object literal notation. The code sample below starts with a creation of an empty object. The second line creates an object with one property salary and assigns the value of 50000 to it. Finally, the instance of one more object pis created and the variable person points at it.

var t = {}             // create an instance of an empty object

var a = {salary: 50000}; // an instance with one property

// Store the data about Julia Roberts
var person = { lastName: ”Roberts”,
               firstName: ”Julia”,
                     age: 42
             };

This object has three properties: lastName, firstName, and age. Note that in object literal notation the values of these properties are specify using colon. You can access the properties of this person using the dot notation, e.g. person.LastName. But JavaScript allows yet another way of accessing the object properties by using square bracket syntax, for example person["lastName"]. In the next code sample you’ll see that using the square brackets is the only way to access the property.

 var person = {
       "last name": "Roberts",
       firstName: "Julia",
             age: 42};

var herName=person.lastName;          // (1)

console.error("Hello " + herName);    // (2)

herName=person["last name"];           // (3)

person.salutation="Mrs. ";

console.log("Hello "+ person.salutation + person["last name"]); // (4)
  1. The object person doesn’t have a property lastName, but no error is thrown

  2. This will print "Hello undefined"

  3. Using and alternative way of referring to an object property

  4. This will print "Hello Mrs. Roberts"

Tip
It’s a good idea to keep handy a style guide of any programming language, and we know two of such documents for JavaScript. Google has published their version of JavaScript Style Guide at http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml. A more detailed Airbnb JavaScript Style Guide is available as a github project at https://github.com/airbnb/javascript. And the github version of the JavaScript style guide is located at https://github.com/styleguide/javascript.

Objects can contain other objects. If a property of an object literal is also an object, you just need to specify the value of this property in an extra pair of curly braces. For example, you can represent the telephone of a person as an object having two properties: the type and the number. The following code snippet adds a nested object to store a work phone as a nested object inside the person’s object. Run this code in the FireBug’s console and it’ll print "Call Julia at work 212-555-1212".

var p = { lastName: "Roberts",
                firstName: "Julia",
                age: 42,
                phone:{
                      type: "work",
                      numb: "212-555-1212"
                 }
            };
console.log("Call " + p.firstName + " at " + p.phone.type + " " + p.phone.numb );

What if a person has more then one phone? We can change the name of the property phone to phones and instead store an array of objects. JavaScript arrays are surrounded by square brackets, and they are zero based. The following code snippet will print "Call Julia at home 718-211-8987".

var p = { lastName: "Roberts",
                firstName: "Julia",
                age: 42,
                phones:[{
                      type: "work",
                      numb: "212-555-1212"
                 },
                 {
                      type: "home",
                      numb: "799-211-8987"

                 }]
            };
console.log("Call " + p.firstName + " at " + p.phones[1].type + " " + p.phones[1].numb );
Methods in Object Literals

Functions defined inside objects are called methods. Defining methods in object literals is similar to defining properties - provide a method name followed by a colon and the function declaration. The code snippet below declares a method makeAppoyntment() to our object literal. Finally, the line p.makeAppointment(); invokes this new method, which will print the message on the console that Steven wants to see Julia and will call at so-and-so number.

var p = { lastName: "Roberts",
                firstName: "Julia",
                age: 42,
                phones:[{
                      type: "work",
                      numb: "212-555-1212"
                 },
                 {
                      type: "home",
                      numb: "718-211-8987"

                 }],
                makeAppointment: function(){
                    console.log("Steven wants to see  " + this.firstName +
                                 ". He'll call at " + this.phones[0].numb);
                }
            };

p.makeAppointment();
Note
Since we already started using arrays, it’s worth mentioning that arrays can store any objects. You don’t have to declare the size of the array upfront and can create new arrays as easy as var myArray=[] or var myArray=new Array(). You can even store function declarations as regular strings, but they will be evaluated on the array initialization. For example, during the greetArray initialization the user will see a prompt asking to enter her name, and, when it’s done, the greetArray will store two strings. The output of the code fragment below can look like "Hello, Mary".
var greetArray=[
    "Hello",
    prompt("Enter your name", ”Type your name here")
];

console.log(greetArray.join(","));

We’ve briefly covered object literals, and you to start using them. In Chapter 4 you’ll be learning about JSON - a popular data format used as replacement for XML in the JavaScript world. Then you’ll see how similar are the syntax of JSON and JavaScript object literals. Now we’ll spend a little bit of time delving into JavaScript functions, and then - back to objects again.

Constructor Functions

JavaScript functions are more then just some named pieces of code that implements certain behavior. They also can become objects themselves by a magic of the new operator. To make things even more intriguing, the function calls can have memories, which will be explained in the section about closures.

If a function is meant to be instantiated with the new operator it’s called a constructor function. If you are familiar with Java or C# you understand the concept of a class constructor that is being executed only once during the instantiation of a class. Now imagine that there is only a constructor without any class declaration that still can be instantiated with the new operator as in the following example.

function Person(lname, fname, age){
         this.lastName=lname;
         this.firstName=fname;
         this.age=age;
};

// Creating 2 instances of Person
var p1 = new Person(“Roberts”,“Julia”, 42);

var p2 = new Person(“Smith”, “Steven”, 34);

This code declares the function Person and after that, it creates two instances of the Person objects referred by the variables p1 and p2 accordingly. This is what the statement functions are objects means.

Note
According to common naming conventions the names of the constructor functions are capitalized.

Objects can have methods and properties, right? On the other hand, functions are objects. Hence functions can have methods and properties too. If you declare a function marryMe() inside the constructor function Person, marryMe() becomes a method of Person. This is exactly what we’ll do next. But this time we’ll create an HTML file that includes the <script> section referring to the JavaScript code sample located in a separate file.

If you want to try it hands-on, create a new file in your Aptana project by selecting the menu File | New | File and give it a name marryme.js. Agree with a suggested default JavaScript template, and key in the following content into this file:

function Person(lname, fname, age){
         this.lastName=lname;
         this.firstName=fname;
         this.age=age;

         this.marryMe=function(person){
         	console.log("Will you marry me, " + person.firstName);
         };

};

var p1= new Person("Smith", "Steven");
var p2= new Person("Roberts", "Julia");

p1.marryMe(p2);

The code above uses the keyword this that refers to the object (a.k.a. context) where the code will execute. If you are familiar with the meaning of this in Java or C#, it’s similar, but not exactly the same, and we’ll illustrate it in the section titled "Who’s this". The method marryMe() of one Person object takes an instance of another Person object and makes an interesting proposition: "Will you marry me, Julia".

This time we won’t run this code in the Firebug’s console, but rather will include it in the HTML file. In Aptana, create a new File | New | File, enter marryme.html as the file name and press the button Finish. Don’t press the button Next as it’ll offer you to select from one of the HTML templates, but this would generate lots of HTML content, which is not needed for our code sample. Just type in the following in the newly created empty file marryme.html.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

	<body>
		<h1>Making Proposal</h1>

		<script src="marryme.js"></script>
	</body>
</html>

Debugging JavaScript in Firebug

In Aptana, right-click on the file marryme.html and select the option Run As | JavaScript Web Application. We continue using Firefox as Aptana’s default browser, and you’ll see it open a new Web page that reads "Making Proposals". Open the Firebug using the View menu, refresh the page and switch to the Firebug’s tab Script. You’ll see the split panel with the JavaScript code from marryme.js on the left.

fig 02 08
Figure 8. Firebug’s Script panel

Let’s set a breakpoint inside the method marryMe() by clicking in the Firebug’s gray area to the left of the line 7. You’ll see a red circle that will reveal a yellow triangle as soon as your code execution will hit this line. Refresh the content of the browser to re-run the script with a breakpoint. Now the execution stopped at line 7, the right panel contains the runtime information about the objects and variables used by your program.

fig 02 09
Figure 9. Firebug’s Script panel at a breakpoint

On the top of the left panel you’ll see usual for debuggers curved arrows (Step Into, Step Over, Step Out) as well as triangular button to continue code execution. The right panel depicts the information related to this and global Window objects. In Firebug’s Script panel at a breakpoint this represents the instance of the Person object represented by the variable p1 (Steven Smith). To see the content of the object, received by the method marryMe() you can add the watch variable by clicking on the text "New watch expression…​" and entering person - the name of the parameter of marryMe(). Firebug’s Script panel at a breakpoint shows the watch variable person (Julia Roberts) that was used during the invocation of the method marryMe().

fig 02 10
Figure 10. Firebug’s Script panel at a breakpoint

Now click on the Firebug’s Net panel, which shows what goes over the network during communication between the Web browser and Web server. Figure 2-11 shows a screen shot of the Net panel where we clicked on the Headers tab for marryme.html and the Response tab of marryme.js. The code 200 for both files means that they arrived successfully to the browser. It also shows the IP address of the Web server they came from, their sizes, and plenty of other useful information. Both Script and Net panels of Firebug or any other developers tools are your best friends of any Web developer.

fig 02 11
Figure 11. Firebug’s Net panel

We like Firebug, but testing and debugging should be done in several Web browsers. Besides Firebug, we’ll be using excellent Google Chrome developers tools. Their menus and panels are similar and we won’t be including such mini-tutorials on using such tools - you can easily learn them on your own.

Notes on Arrays

A JavaScript array is a grab bag of any objects. You don’t have to specify in advance the number of elements to store, and there is more than one way to create and initialize array instances. The following code samples are self-explanatory.

var myArray=[];
    myArray[0]="Mary";
    myArray[2]="John";

// prints undefined John
console.log(myArray[1] + " " + myArray[2]);

var states1 = ["NJ", "NY", "CT", "FL"];

var states = new Array(4);  // size is optional

states[0]="NJ";

states[1]="NY";

states[2]="CT";

states[3]="FL";

// remove one array element
delete states[1];


// prints undefined CT length=4
console.log(states[1] + " " + states[2] + " Array length=" + states.length);

// remove one element starting from index 2
states.splice(2,1);

// prints undefined  FL length=3
console.log(states[1] + " " + states[2] + " Array length=" + states.length);

Removing elements with delete creates gaps in the arrays while using the array’s method splice() allows to remove or replace the specified range of elements closing gaps.

The next code sample illustrates an interesting use case when we assign a string and a function text as array elements to mixedArray. During array initialization the function promt() will be invoked, the user will be prompted to enter name, and after that, two strings will be store in mixedArray, for example "Hello" and "Mary".

var mixedArray=[
    "Hello",
    prompt("Enter your name", ”Type your name here")
];

Prototypal Inheritance

JavaScript doesn’t support classes, at least till the ECMAScript 6 will become a reality. But JavaScript allows you to create objects that inherit properties and methods of other objects. By default, all JavaScript objects are inherited from Object. Each JavaScript construction function has a special property called prototype, which points at this object’s ancestor. If you want to create an inheritance chain where an instances of constructor function ObjectB extend ObjectA just write one line of code: ObjectB.prototype=ObjectA;.

fig 02 12
Figure 12. Prototypal Inheritance

Consider two constructor functions Employee and Person shown in the code snippet below.They represent two unrelated objects. But assigning the Person object to the prototype property of Employee creates an inheritance chain, and now the object emp will have all properties defined in both Employee and Person.

function Person(name, title){
	this.name=name;
	this.title=title;
	this.subordinates=[];
}

function Employee(name, title){
	this.name=name;
	this.title=title;
}

// All instances of Employee will extend Person
Employee.prototype = new Person();            // (1)

var emp=new Employee("Mary", "Specialist"); // (2)

console.log(emp);      // (3)
  1. Assigning an ancestor of type person

  2. Instantiating Employee

  3. Printing the object referred by emp will output [object Object]. It happens because each object has a method toString(), and if you want it to output useful information - override it. You’ll see how to do it later in this section.

We want to stress, that the property prototype exists on constructor functions. After creating specific instances of such objects you may see that these instances have another property called proto. At the time of this writing this property is not a standard yet and won’t be supported in some older browsers, bit ECMAScript 6 will make it official. To illustrate the difference between prototype and proto let’s add the following piece of code to the above sample:

//Create an instance of Person and add property dependents
var p=new Person();
p.dependents=1;                                 // (1)


var emp2=new Employee("Joe", "Father");

//This employee will have property dependents

emp2.__proto__=p;                               // (2)

console.log("The number of Employee's dependents " + emp2.dependents); // (3)
  1. Creating an instance of Person and adding an extra property dependents just for this instance

  2. Assigning this instance to the proto property of one instance

  3. The code will properly print 1 as a number of dependents of the Employee instance represented by the variable emp2. The variable emp from the previous code snippet won’t have the property dependents.

To try it hands-on, open the file WhoIsYourDaddy.html in Aptana. Just for a change, this time we’ll use Google Chrome Developer Tools by opening the menu View | Developer | Developer Tools. Set the breakpoint at the last line of the JavaScript, refresh the Web page content, and add the watch expressions for the variables p, emp, and emp2. When the JavaScript code engine runs into emp2.dependents it tries to find this property in property on the Employee object. If not found, the engine checks all the objects in the prototypal chain (in our case it’ll find it in the object p) all the way up to the Object if need be.

Tip
If you need to do some programmatic manipulations with only those properties that are defined on the specific object (not in its ancestors) do the check with the method hasOwnProperty().
fig 02 13
Figure 13. The instance-specific proto variable
Tip
You can find a tutorial on using Google Chrome Developer Tools at https://developers.google.com/chrome-developer-tools/. The cheatsheet of Chrome developer Tools is located at http://anti-code.com/devtools-cheatsheet/.

Please not the difference in the content of the variables proto of the instances represented by emp and emp2. These two employees are inherited from two differnet objects Person. Isn’t it scary? Not really.

Where to Declare Methods

If you take a closer look at the screenshot from The instance-specific proto variable you’ll see that the Person and Employee objects have redundant properties name and title. We’ll deal with this redundancy in the section titled "Call and Apply". But first let’s introduce and cure the redundancy in method declarations when the prototypal inheritance is used.

Let’s add a method to addSubordinate() to the ancestor object Person that will populate its array subordinates. Who knows, maybe an object Contractor (descendant of a Person) will need to be added in the future, so the ancestor’s method addSubordinate() can be reused. First, we’ll do it the wrong way to illustrate the redundancy problem, and then we’ll do it right. Consider the following code:

// Constructor function Person
function Person(name, title){
	this.name=name;
	this.title=title;
	this.subordinates=[];

    // Declaring method inside the constructor function
	this.addSubordinate=function (person){
		this.subordinates.push(person)
	}


}

// Constructor function Employee
function Employee(name, title){
	this.name=name;
	this.title=title;
}

// Changing the inheritance of Employee
Employee.prototype = new Person();

var mgr =  new Person("Alex", "Director");
var emp1 = new Employee("Mary", "Specialist");
var emp2 = new Employee("Joe", "VP");

mgr.addSubordinate(emp1);
mgr.addSubordinate(emp2);
console.log("mgr.subordinates.length is " + mgr.subordinates.length);

The method addSubordinate() here is declared inside the constructor function Person, which becomes an ancestor of the Employee. After instantiation of two Employee objects the method addSubordinate() is duplicated for each instance.

Let’s use Google Chrome Developer Tools profiler to see the sizes of the objects allocated on the Heap memory. But first we’ll set up two breakpoints - one before, and one after creating our instances as shown on Preparing Breakpoints Take 1..

fig 02 14
Figure 14. Preparing Breakpoints Take 1.

When the execution of the code will stop at the first breakpoint, we’ll switch to the Profiler tab and take the first Heap snapshot. Upon reaching the second breakpoint we’ll take another Heap snapshot. The dropdown at the status bar allows to view the objects allocated between the snapshots 1 and 2. Objects allocated between snapshots 1 and 2 depicts this view of the profiler. Note that the total size (the Shallow Size column) for the Person instances is 132 bytes. Employee instances weigh 104 bytes.

fig 02 15
Figure 15. Objects allocated between snapshots 1 and 2

Now we’ll change the code to declare the method not inside the Person constructor function, but on it’s prototype - and this is the right way to declare methods in functions to avoid code duplication.

// Constructor function Person
function Person(name, title){
	this.name=name;
	this.title=title;
	this.subordinates=[];

}

//Declaring method on the object prototype
Person.prototype.addSubordinate=function(subordinate){
   this.subordinates.push(subordinate);
   return subordinate;
}

// Constructor function Employee
function Employee(name, title){
	this.name=name;
	this.title=title;
}

// Changing the inheritance of Employee
Employee.prototype = new Person();

var mgr =  new Person("Alex", "Director");
var emp1 = new Employee("Mary", "Specialist");
var emp2 = new Employee("Joe", "VP");

mgr.addSubordinate(emp1);
mgr.addSubordinate(emp2);
console.log("mgr.subordinates.length is " + mgr.subordinates.length);

Similarly, we’ll set up two breakpoints before and after object instantiation as shown in <<>FIG2-16>.

fig 02 16
Figure 16. Preparing Breakpoints Take 2.

Let’s take two more profiler snapshots upon reaching each of the breakpoint. While the weight of the Employee instances remained the same (104 bytes), the Person instances became lighter: 112 bytes. While 20 bytes may not seem like a big deal, if you’ll need to create hundreds or thousands of object instances it adds up.

fig 02 17
Figure 17. Objects allocated between snapshots 3 and 4

So if you need to declare a method on the object that will play a role of the ancestor, do it on the prototype level. The only exception to this rule is the case when such method needs to use some object specific variable that’s different for each instance - in case declare methods inside the constructors (see the section on closures for details).

Note
All modern Web browsers support the function Object.create(), which creates a new object based on another prototype object. For example, var objectB=Object.create(objectA);. What if you must support an older browser and need such "create by example" functionality? Of course, you can always create a custom arbitrarily named function with the similar functionality as the latest implementation of Object.create(). But the future-proof approach is to create the missing methods with the same signatures and on the same objects as the latest ECMAScript specification prescribes. In case of Object.create() you can use the implementation offered by Douglas Crockford:
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
newObject = Object.create(oldObject);

Such approach of custom implementation of missing pieces according to the latest ECMAScript specifications or W3C drafts is known as polyfills. People who can’t wait till the browser vendors will implement the newest functionality create cross-browser polyfills and some of them submit their source code to the public domain. You can find a number of polyfills in the git repository of the Modernizr project. The Web site http://caniuse.com/ contains the current information about browser’s support of the latest HTML5, JavaScript, and CSS features.

Method overriding

Since JavaScript allows declaring methods on an object as well as on its prototype, overriding a method becomes really simple. The following code sample declares the method addSubordinate() on the prototype of the Person object, but then the object p1 overrides this method.

function Person(name, title){

  this.name=name;
  this.title=title;
  this.subordinates=[];
}

Person.prototype.addSubordinate=function(person){

   this.subordinates.push(person);
   console.log("I'm in addSubordinate on prototype " + this);
}

var p1=new Person("Joe", "President");

    p1.addSubordinate=function(person){

    this.subordinates.push(person);
    console.log("I'm in addSubordinate in object " + this);
  }

var p2 = new Person("Mary", "Manager")

    p1.addSubordinate(p2);

Running the above code prints only one line: "I’m in addSubordinate in object [object Object]". This proves that the method addSubordinate() on the prototype level is overridden. We can also improve this example a little bit and override the method toString() on the Person. Just add the following fragment to the prior to instantiating p1.

Person.prototype.toString=function(){
   return "name:" + this.name +" title:" + this.title;
}

Now the code prints "I’m in addSubordinate in object name:Joe, title:President". Overriding the method toString() on objects is a common practice as it gives a textual representation of your objects.

Scope or who’s this?

You are about to read one of the most confusing sections in this book. The confusion is caused by some inconsistencies in JavaScript design and implementations by various browsers. Do you know what will happen if you’ll remove the keywords this from the toString() method from previous section? You’ll get an error - the variable title is not defined. Without the keyword this the JavaScript engine tries to find the variable title in the global namespace. Declaring and initializing the variable title outside of the Person declaration get rid of this error, but this is not what we want to do. Misunderstanding of the current scope can lead to difficult to debug errors.

Caution
Interestingly enough replacing this.name with name doesn’t generate an error, but rather initializes the variable name with an empty string. Although name is not an officially reserved JavaScript keyword, there are articles in the blogosphere that don’t recommend using the word name as a variable name. Keep this list of reserved words handy to avoid running into an unpredictable behavior.

Let’s consider several examples that will illustrate the meaning of this variable in JavaScript. The code sample below defines an object myTaxObject and calls its method doTaxes(). Notice two variables with the same name taxDeduction - one of them has global scope and another belongs to myTaxObject. This little program was written for mafia and will apply some under the table deduction for the people who belong to Cosa Nostra.

var taxDeduction=300;      // global variable

var myTaxObject = {

    taxDeduction: 400,    // object property

    doTaxes: function() {
         this.taxDeduction += 100;

         var mafiaSpecial= function(){
           console.log( "Will deduct " + this.taxDeduction);
         }

         mafiaSpecial();  // invoking as a function
    }
}

myTaxObject.doTaxes();  //invoking method doTaxes

This code fragment illustrates the use of nested functions. The object method doTaxes() has a nested function mafiaSpecial(), which is not visible from outside of the myTaxObject, but it can be certainly invoked inside doTaxes(). What number do you think this code will print after the words "Will deduct "? Will it print three, four, or five hundred? Run this code in Firebug, Chrome Developer Tools or any other way and you’ll see that it’ll print 300!

But this doesn’t sound right, does it? The problem is that in JavaScript the context where the function executes depends on the way it was invoked. In this case the function mafiaSpecial() was invoked as a function (not a method) without specifying the object it should apply to, and JavaScript makes it operate in the global object, hence the global variable taxDeduction having the value of 300 is being used. So in expression this.taxDeduction the variable this means global unless the code is operated in the strict mode.

Note
ECMAScript 5 introduced a restricted version of JavaScript called strict mode, which among other things places stricter requirements to variable declarations and scope identification. Adding "use strict" as the first statement of the method doTax() will make the context undefined, and it’ll print the error "this is undefined" and not 300. You can read about the strict mode at Mozilla’s developers site.

Let’s make a slight change to this example and take to control what this represents. When the object myTaxObject was instantiated its own this reference was created. The following code fragment stores this reference in additional variable thisOfMyTaxObject changes the game and the expression thisOfMyTaxObject.taxDeduction evaluates to 500.

var taxDeduction=300;      // global variable

var myTaxObject = {

    taxDeduction: 400,    // object property

    doTaxes: function() {
    var thisOfMyTaxObject=this;
         this.taxDeduction += 100;

         var mafiaSpecial= function(){
           console.log( "Will deduct " + thisOfMyTaxObject.taxDeduction);
         }

         mafiaSpecial();  // invoking as a function
    }
}

myTaxObject.doTaxes();  //invoking method doTaxes

You’ll see a different way of running a function in the context of the specified object using special functions call() and apply(). But for now consider one more attempt to invoke mafiaSpecial()`shown in the following example that uses `this.mafiaSpecial() notation.

var taxDeduction=300;      // global variable

var myTaxObject = {

    taxDeduction: 400,    // object property

    doTaxes: function() {
         this.taxDeduction += 100;

         var mafiaSpecial= function(){
           console.log( "Will deduct " + this.taxDeduction);
         }

         this.mafiaSpecial();  // trying to apply object's scope
    }
}

myTaxObject.doTaxes();  //invoking method doTaxes

Run the above code and it’ll give you the error "TypeError: this.mafiaSpecial is not a function" and rightly so. Take a closer look at the object myTaxObject represented by the variable this. The myTaxObject has only two properties: taxDeduction and doTaxes. The function mafiaSpecial is hidden inside the method doTaxes and can’t be accessed via this.

Call and Apply

Visualize the International Space Station, and add to the picture an image of a approaching space shuttle. After attaching to the docking bay of the station the shuttle’s crew performs some functions on the station (a.k.a. object) and then flies to another object or back to Earth. What is has to do with JavaScript? It can serve as an analogy for creating a JavaScript function that can operate in the scope of any arbitrary object. For this purpose JavaScript offers two special functions: call() or apply(). Both call() and apply() can invoke any function on any object. The only difference between them is that apply() passes required parameters to a function as an array, while call() uses a comma-separated list.

Tip
Every function in JavaScript is a Function object. Both call() and apply() are defined in the Function object.

For example, a function calcStudentDeduction(income,numOfStudents) can be invoked in a context of a given object using either call() or apply(). Note that with call() parameters have to be listed explicitly, while with apply parameters are given as an array:

calcStudentDeduction.call(myTaxObject, 50000, 2);

calcStudentDeduction.apply(myTaxObject, [50000, 2]);

In the above example the instance of myTaxObject can be referred as this from within the function calcStudentDeduction() even though this is a function and not a method. The last example from the previous section can be re-written to invoke mafiaSpecial(). The following code will ensure that mafiaSpecial() has this pointing to `myTaxObject' and will print on the console "Will deduct 500".

var taxDeduction=300;      // global variable

var myTaxObject = {

    taxDeduction: 400,

    doTaxes: function() {
         this.taxDeduction += 100;

         var mafiaSpecial= function(){
           console.log( "Will deduct " + this.taxDeduction);
         }

         mafiaSpecial.call(this);  // passing context to a function
    }
}

myTaxObject.doTaxes();

Callbacks

Can you live without using call() and apply()? Sure you can, but in JavaScript can easily create callbacks - you can pass the code of one function as a parameter to another function for execution in the latter function’s context. Most likely you’ve seen how event handlers are declared. If a user clicks on this button here’s the name of the handler function to call: myButton.addEventListener("click", myFunctionHandler)

It’s important to understand that you don’t not immediately call the function myFunctionHandler here - you are just registering it. If and only if the user will click on myButton then the callback myFunctionHandler has to be invoked in the context of the myButton object. The functions call() and apply() exist exactly for this purpose.

Let’s consider an example when you need to write a function that will take two arguments - and array with preliminary tax data and a callback function to be applied to each element of this array. The following code sample creates myTaxObject that has two properties: taxDeduction and the applyDeduction. The latter is a method with two parameters: array and a callback to be applied to this array.

var myTaxObject = {

    taxDeduction: 400, // state-specific  deduction

    // this function takes an array and callback as parameters
    applyDeduction: function(someArray, someCallBackFunction){

        for (var i = 0; i < someArray.length; i++){

            // Invoke the callback
           someCallBackFunction.call(this, someArray[i]);
        }

    }
}

// array
var preliminaryTaxes=[1000, 2000, 3000];

// tax handler function
var taxHandler=function(currentTax){
                   console.log("Hello from callback. Your final tax is " +
                   (currentTax - this.taxDeduction));
                }

// invoking applyDeduction passing an array and callback
myTaxObject.applyDeduction(preliminaryTaxes, taxHandler);

The above code invokes applyDeduction() passing it the array preliminaryTaxes and the callback function taxHandler that takes the currentTax and subtracts this.taxDeduction. By the time this callback will be applied to each element of the array the value of this will be known and this code will print the following:

Hello from callback. Your final tax is 600
Hello from callback. Your final tax is 1600
Hello from callback. Your final tax is 2600

You may be wondering, why passing the function to another object if we could take an array, subtract 400 from each of its elements and be done with it? The solution with callbacks gives you an ability to make the decision on what function to call during the runtime and call it only when a certain event happens. Callbacks allow you to do asynchronous processing. For example, you make an asynchronous request to a server and register the callback to be invoked if a result comes back. The code is not blocked and doesn’t wait until the server response is ready. Here’s an example from AJAX: request.onreadystatechange=myHandler. You register myHandler callback but not immediately call it. JavaScript functions are objects, so get used to the fact that you can pass them around as you’d be passing any objects.

Hoisting

A variable scope depends on where it was declared. You already had a chance to see that a variable declared inside a function with the keyword var is visible only inside this function. Some programming languages allow to narrow down the scope even further. For example, in Java declaring a variable inside any block of code surrounded with curly braces makes it visible only inside such a block. In JavaScript it works differently. No matter where in the function you declared the variable its declaration will be hoisted to the top of the function, and you can use this variable anywhere inside the function.

The following code snippet will print 5 even though the variable b has been declared inside the if-statement. It’s declaration has been hoisted to the top:

function test () {
    var a=1;

    if(a>0) {
        var b = 5;
    }
    console.log(b);

}

test();

Let’s make a slight change to the above code to separate the variable declaration and initialization. The following code has to console.log(b) statements. The first one will output undefined and the second will print 5 just as in the previous example.

function test () {
    var a=1;

    console.log(b);  // b is visible, but not initialized

    if(a>0) {
        var b;
    }

    b=5;

    console.log(b);  // b is visible and initialized
}

test();

Due to hoisting, JavaScript doesn’t complain when the first console.log(b) is invoked. It knows about the variable b, but its value is undefined just yet. By the time the second console.log(b) is called, the variable b was initialized with the value of 5. Just remember that hoisting just applies to variable declaration and doesn’t interferes with your code when it comes to initialization. JavaScript function declarations are hoisted too, and this is illustrated in the following code sample.

function test () {
    var a=1;

    if(a>0) {
        var b;
    }

    b=5;

    printB();

    function printB(){
        console.log(b);
    }
}

test();

This code will print 5. We can call the function printB() here because its declaration was hoisted to the top. But the situation changes if instead of function declaration we’ll use the function expression. The following code will give you an error "PrintB is not a function". Notice that it the error doesn’t complain about printB being undefined cause the variable declaration was hoisted, but since the function expression wasn’t the JavaScript engine doesn’t know yet that printB will become a function really soon. Anyway, moving the invocation line printB() to the bottom of the function test() cures this issue. Function expressions are not being hoisted.

function test () {
    var a=1;

    if(a>0) {
        var b;
    }

    b=5;

    printB();

    var printB = function(){
        console.log(b);
    }

}

test();

All code samples in this section first declare the function test() and then invoke it. This function test() is being called once and there is no reason to give it a name. Using so called self-invoked function notation allows to declare and automatically invoke the function (note the extra parentheses at the end of the following code).

(function () {
    var a=1;

    if(a>0) {
        var b;
    }

    b=5;

    printB();

    var printB = function(){
        console.log(b);
    }

})();

Function properties

Functions as any other objects can have properties. You can attach any properties to a Function object and their values can be used by all instances of this object. Static variables in programming languages with the classical inheritance is the closest analogy to function properties in JavaScript.

Let’s consider an example of a constructor function Tax. An accounting program can create multiple instances if Tax - one per person. Say this program will be used in a Florida neighborhood with predominantly Spanish speaking people. The following code illustrates the case when the method doTax() can be called with or without parameters.

function Tax(income, dependents){
    this.income=income;              // instance variable
    this.dependents=dependents;      // instance variable

    this.doTax = function calcTax(state, language){
           if(!(state && language)){     // (1)
              console.log("Income: " + this.income + " Dependents: "+ this.dependents
              + " State: " + Tax.defaults.state + " language:" + Tax.defaults.language);
           } else{                       // (2)
              console.log("Income: " + this.income + " Dependents: "+ this.dependents
              + " State: " + state + " language:" + language);
           }
    }
}

Tax.defaults={                           // (3)
     state:"FL",
     language:"Spanish"
};

// Creating 2 Tax objects
var t1 = new Tax(50000, 3);
    t1.doTax();                          // (4)
var t2 = new Tax(68000, 1);
    t2.doTax("NY","English");            // (5)
  1. No state and language were given to the method doTax()

  2. The state and language were provided as doTax() parameters

  3. Assigning the object with two properties as a defaults property on Tax. The property default is not instance specific, which makes it static.

  4. Invoking doTax() without parameters - use defaults

  5. Invoking doTax() with parameters

This program will produce the following output:

Income: 50000 Dependents: 3 State: FL language:Spanish
Income: 68000 Dependents: 1 State: NY language:English

You can add as many properties to the constructor function as needed. For example, to count the number of instances of the Tax object just add one more property Tax.counter=0;. Now add to the Tax function something like console.log(Tax.counter++); and you’ll see that the counter increments on each instance creation.

Tip
If multiple instances of a function object need to access certain HTML elements of the DOM, add references to these elements as function properties so objects can reuse them instead of traversing the DOM (it’s slow) from each instance.

Closures

Imagine a function that contains a private variable, and a nested function. Is it possible to invoke the nested function from the outside of the outer one? And if it’s possible, what this inner function knows about its surroundings?

Larry Ullman, a Web developer and computer books author offers the following definition: "Closure is a function call with memory". We can offer you our version: "Closure is a function call with strings attached". Now it’s turn for the explanation of these mysterious definitions, and we’ll do it by example. Consider the following code that is yet another example of implementing tax collection functionality.

(function (){                // this is an anonymous function expression

    var taxDeduction = 500;  // private context to remember

      //exposed closure
      this.doTaxes=function(income, customerName) {

      	var yourTax;

        if (customerName != "Tony Soprano"){
          yourTax =   income*0.05 - taxDeduction;
        } else{
          yourTax =   mafiaSpecial(income);
        }

         console.log( "   Dear " + customerName + ", your tax is "+ yourTax);
         return yourTax;
      }

      //private function
      function mafiaSpecial(income){
          return income*0.05 - taxDeduction*2;
      }

})();    // Self-invoked function

// The closure remembers its context with taxDeduction=500
doTaxes(100000, "John Smith");
doTaxes(100000, "Tony Soprano");

mafiaSpecial();        // throws an error - this function is private

First, a self-invoking function will create an anonymous instance of an object in the global scope. It contains a private variable taxDeduction, a public method doTaxes(), and a private method mafiaSpecial(). Just by the virtue of declaring doTaxes on this object, this method becomes exposed to the current scope, which is global in this example.

After that we call the method doTaxes() twice. Note that the function doTaxes() uses the variable taxDeduction that was never declared there. But when doTaxes was initially declared, the variable taxDeduction with a value of 500 was already there. So the internal function "remembers" the context (the neighborhood) where it was declared and can use it for its calculations.

The algorithm of tax calculations makes doTaxes() calls the function mafiaSpecial() if the customer’s name is "Tony Soprano". The function mafiaSpecial() is not visible from outside, but for insiders like doTaxes() it’s available. Here’s what the above code example will print on the console:

Dear John Smith, your tax is 4500
Dear Tony Soprano, your tax is 4000
Uncaught ReferenceError: mafiaSpecial is not defined

The Closure view in Chrome’s Developer Tools. shows the screenshot taken when doTaxes() hit the breakpoint inside doTaxes - note the right panel that shows what’s visible in the Closure scope.

fig 02 18
Figure 18. Closure view in Chrome’s Developer Tools.
Tip
JavaScript doesn’t give you an explicit way to mark an variable as private. By using closures you can get the same level of data hiding that you get from private variables in other languages. In the example above the variable taxDeduction is local for the object enclosed in the outermost parentheses and can’t be accessed from outside. But taxDeduction can be visible from the object’s functions doTaxws and mafiaSpecial.

Closure doTaxes gives yet another visual representation of our above code sample. The self-invoked anonymous function is shown as a cloud that exposes only one thing to the rest of the world: the closure doTaxes.

fig 02 19
Figure 19. Closure doTaxes

Let’s consider a couple of more cases of returning a closure to the outside world so it can be invoked later. If the previous code sample was exposing the closure by using this.taxes notation, the next two examples will simply return the code of the closure using the return statement. The code below declares a constructor function Person, adds a function doTaxes() to its prototype, and finally creates two instances of the Person calling the method doTaxes() on each of them.

// Constructor function
function Person(name){

	this.name = name;

}

// Declaring a method that returns closure
Person.prototype.doTaxes= function(){

    var taxDeduction = 500;

      //private function
      function mafiaSpecial(income){
          return income*0.05 - taxDeduction*2;
      }

      //the code of this function is returned to the caller
      return function(income) {

      	var yourTax;

        if (this.name != "Tony Soprano"){
          yourTax =   income*0.05 - taxDeduction;
        } else{
          yourTax =   mafiaSpecial(income);
        }

         console.log( "My dear " + this.name + ", your tax is "+ yourTax);
         return yourTax;
      }
}();     // important parentheses!

//Using closure
var p1 = new Person("John Smith");
var result1 = p1.doTaxes(100000);

var p2 = new Person("Tony Soprano");
var result2 = p2.doTaxes(100000);

The calculated taxes in this example are the same as in the previous one: John Smith has to pay $4500, while Tony Soprano only $4000. But we used different technique for exposing the closure. We want to make sure that you didn’t overlooked the parentheses at the very end of the function expression for doTaxes. These parenthesis force the anonymous function to self-invoke itself, it’ll run into a return statement and will assign the code of the anonymous inner function that takes parameter income to the property doTaxes. So when the line var result1 = p1.doTaxes(100000); calls the closure the variable result1 will have the value 4500. Remove these important parentheses, and the value of result1 is not the tax amount, but the the code of the closure itself - the invocation of the closure is not happening.

The following code fragment is yet another example of returning the closure that remembers its context.First, the closure is returned to the caller of prepareTaxes(), and when the closure will be invoked it’ll remember the values defined in its outer context. After looking at this code you can say that there is nothing declared in the closure’s outside context! There is - by the time when the closure is created the value of the studentDeductionAmount will be known.

function prepareTaxes(studentDeductionAmount) {

	return function (income) {           // (1)
	   return income*0.05 - studentDeductionAmount;
	};

}

var doTaxes = prepareTaxes(300);         // (2)
var yourTaxIs = doTaxes(10000);          // (3)
console.log("You tax is " + yourTaxIs);  // (4)
  1. When the function prepareTaxes is called, it immediately hits the return statement and returns the code of the closure to the caller.

  2. After this line is executed, the variable doTaxes has the code of the closure, which remembers that studentDeductionAmount is equal to 300.

  3. This is actual invocation of the closure

  4. the console output is "your tax is 200"

Tip
Check the quality of your code with the help of the JavaScript code quality tool JSLint.

Closures as callbacks

Let’s revisit the code from the section Callbacks above. That code has shown how to pass an arbitrary function to another one and invoke it there using call(). But if that version of the function taxHandler was not aware of the context it was created in, the version below will. If in classical object-oriented languages you’d need to pass a method that knows about it’s context, you’d need to create an instance of an object that contains the method and the required object-level properties, and then you’d be passing this wrapper-object to another object for processing. But since the closure remembers its context anyway, we can just pass a closure instead of object. Compare the code below with the code from the Callbacks section.

var myTaxObject = {

    // this function takes an array and callback as parameters
    applyDeduction: function(someArray, someCallBackFunction){

        for (var i = 0; i < someArray.length; i++){

            // Invoke the callback
           someCallBackFunction.call(this, someArray[i]);
        }

    }
}

// array
var preliminaryTaxes=[1000, 2000, 3000];


var taxHandler = function (taxDeduction){

// tax handler closure
	return function(currentTax){
                   console.log("Hello from callback. Your final tax is " +
                   (currentTax - taxDeduction));
                };
}


// invoking applyDeduction passing an array and callback-closure
myTaxObject.applyDeduction(preliminaryTaxes, taxHandler(200));

The last line of the above example calls taxHandler(200), which creates a closure that’s being passed as a callback to the method applyDeduction(). Even though this closure is executed in the context of myTaxObject, it remembers that tax deduction is 200.

Mixins

The need to extend capabilities of objects can be fulfilled by inheritance, but this is not the only way of adding behavior to objects. In this section you’ll see an example of something that would not be possible in the object-oriented languages like Java or C#, which don’t support multiple inheritance. JavaScript allows taking a piece of code and mix it into any object regardless of what its inheritance chain is. Mixin is a code fragment that an object can borrow if need be.

// Defining a function expession
var Tax = function(income, state){
	this.income=income;
	this.state=state;

	this.calcTax=function(){
		var tax=income*0.05;
		console.log("Your calculated tax is " + tax)
		return tax;
	}
};


// Defining a mixin
var TaxMixin = function () {};

TaxMixin.prototype = {

  mafiaSpecial: function(originalTax){
    console.log("Mafia special:" + (originalTax - 1000));
  },

  drugCartelSpecial: function(originalTax){
     console.log("Drug Cartel special:" + (originalTax - 3000));
  }

};

// this function can blend TaxMixin into tax
function blend( mainDish, spices ) {

  for ( var methodName in spices.prototype ) {
      mainDish.prototype[methodName] = spices.prototype[methodName];
  }
}

// Blend the spices with the main dish
blend( Tax, TaxMixin );

// Create an instant of Tax
var t = new Tax(50000, "NY");

var rawTax = t.calcTax();

// invoke a freshly blended method
t.mafiaSpecial(rawTax);

The function blend() loops through the code of the TaxMixin and copies all its properties into Tax. Mixins can be useful is you want to provide a specific feature to a number of different object without changing their inheritance. The other use case is if you want to prepare a bunch of small code fragments (spices) and add any combination of them to the various objects (dishes) as needed. Mixins give you a lot of flexibility in what you can achieve with the minimum code, but they may decrease the readability of your code.

If you’ve read this far, you should have a good understanding of the syntax of the JavaScript language.Studying the code samples provided in this chapter has one extra benefit: now you can apply for a job as a tax accountant in a mafia near you.

JavaScript in the Web Browser

After learning all these facts and techniques about the language you might be eager to see "the real-world use of JavaScript". Slowly but surely a Web browser becomes the leading platform for development of the user interface. The vast majority today’s JavaScript programs primarily manipulate HTML elements of Web pages. In this section we’ll be doing exactly this – applying JavaScript code to modify the content or style of HTML elements.

DOM stands for Document Object Model. It’s an object representing the hierarchy of HTML elements of a Web page. Every element of the HTML document is loaded into DOM. Each DOM element has a reference to its children and siblings. When DOM was invented, the Web pages were simple and static. DOM was not meant to be an object actively accessed by the code. This is the reason that on some of the heavily populated Web pages manipulating of DOM elements can be slow. Most likely DOM is the main target for anyone who’s trying to optimize the performance of a Web page.

Tip
If your Web page is slow, analyze it with YSlow, the tool built based on the Yahoo! rules for high performance Web sites. Also, you can minimize and obfuscate your JavaScript code with the help of JavaScript Compressor.

When a Web Browser is receiving the content it keeps performing the following activities:

  • Adding arriving HTML elements to DOM and laying out the content of the Web pages

  • Rendering of the UI

  • Running JavaScript that was included in the HTML

  • Processing events

The amount of time spent on each of these activities varies depending the content of the page.

Tip
If you are interested in learning how the browsers work in detail, read an excellent writeup titled "How Browsers Work: Behind The Scenes of Modern Web Browsers" at http://bit.ly/how-browsers-work [http://bit.ly/how-browsers-work].

Let’s consider the operations your application needs to be able to perform inside the Web page:

  • Programmatically finding the required element by id, type, or a CSS class

  • Changing styles of the elements (show, hide, apply fonts and colors et al.)

  • Processing events that may happen to HTML elements (click, mouseover and the like)

  • Dynamically adding or removing HTML elements from the page or changing their contents

  • Communicating with the server side, e.g. submitting forms or making AJAX requests for some data from the server

Now you’ll see some code samples illustrating the use of JavaScript for the listed above operations. Even if you’ll be using one of the popular JavaScript frameworks, your program will be performing similar operations applying the syntax prescribed by your framework of choice. So let’s learn how it can be done.

Working with DOM

If you want to change the appearance of an HTML page, you need to manipulate with the DOM elements. Older Web applications were preparing the HTML content on the server side. For example, a server-side Java servlet would compose and send to the client HTML whenever the application logic required to change the appearance of the UI. The current trend is different - the client’s code takes care of the UI rendering, and only the data go back and forth between the client and the server. You’ll see how this works in more detail in Chapter 4 that explains the use of AJAX and JSON.

Earlier in this chapter we were talking about the global namespace where all JavaScript objects live unless they were declared with var inside the functions. If the JavaScript code is running in a Web browser, this global namespace is represented by a special variable window. It’s an implicit variable and you don’t have to use it in your code, but whenever we say that a variable is global, we mean that it’s exists on the window object. For example, the code below will print "123 Main Street" twice:

var address ="123 Main Street";

console.log(address);
console.log(window.address);

The window object has a number of useful properties like cookie, location, parent, document and others. The variable document points at the root of the DOM hierarchy. Pretty often your JavaScript code would find an element in the DOM first, and then it could read or modify its content. Firebug’s representation of DOM is a snapshot from Firebug showing the fragment of a DOM of a simple Web page mixins.html.

fig 02 20
Figure 20. Firebug’s representation of DOM
Single Page Applications

Have you ever seen a monitor of a trader working for a Wall Street firm? Actually, they usually have three or four large monitors, but let’s just look at one of them. Imagine a busy screen with lots and lots constantly changing data grouped in dedicated areas of the window. This screen shows the constantly changing prices from financial markets, the trader can place orders to buy or sell products, and notifications on completed trades are also coming to the same screen. If this is would be a Web application it would live in the same Web page. No menus to open another windows.

The price of Apple share was $590.45 just a second ago and now it’s $590.60. How can this be done technically? Here’s one of the possibilities: every second an AJAX is being made to the remote server providing current stock prices and the JavaScript code finds in the DOM the HTML element responsible for rendering the price and then modifies its value with the latest price.

Have you seen a Web page showing an input box of Google’s Gmail? It looks like a table with a list of rows representing the sender, subject, and the date of when each email arrived. All of a sudden you see a new row in bold on top of the list - the new email came in. How was this done technically? A new object(s) was created and inserted into a DOM tree. No page changes, no needs for the user to refresh the browser’s page - an undercover AJAX call gets the data and JavaScript changes the DOM. The content of DOM changed - the user sees an updated value.

Below are some of the methods that exist on the `document` object:

document.write(text) – adds the specifies text to the DOM. Careless using of the method write() can result in unpredictable results if after changing the DOM the HTML content is still arriving.

document.getElementById(id) – get a reference to the HTML element by its unique identifier

document.getElementsByTagName(tname) - get a reference to one or more elements by tag names, e.g.get a reference to all <div> elements.

document.getElementsByName(name) - get a reference to all elements that have requested value in their name attribute.

document.getElementsByClassName(className) – get a reference to all elements to use specified CSS class.

document.querySelector(cssSelector) – Find the first element that matches provided CSS selector. string.

document.querySelectorAll(cssSelector) – Find all elements that match provided CSS selector string.

The next code sample contains the HTML <span> element that has an id emp. Initially it contains ellipsis, but when the user enters the name in the input text field, the JavaScript code will find the reference to this <span> element and will replace the ellipsis with the content of the input text field.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

	<body>
        <h2>Selecting DOM elements</h2>

        <p>
        	The employee of the month is <span id="emp">...</span>
        <br>
        <input type="button" value="Change the span value"
               onclick="setEmployeeOfTheMonth()"/>
        Enter your name  <input type="text" id="theName" />
        </p>

        <script>
           function setEmployeeOfTheMonth(){

        	   var mySpan = document.getElementById("emp");

        	   var empName= document.getElementsByTagName("input")[1];

        	   mySpan.firstChild.nodeValue= empName.value;

        	}
        </script>

	</body>
</html>

Note the input field of type button, which includes the onclick property that corresponds to the click event. When the user clicks on the button, the browser dispatched click event, and calls the JavaScript function setEmployeeOfTheMonth(). The latter queries the DOM and finds the reference to the emp by calling the method getElementBuId(). After that, the method getElementByTagName() is called trying to find all the references to the HTML <input> elements. This methods returns an array cause there could be more than one element with the same tag name on a page, which explains the use of array notation. The first <input> element is a button and the second is the text field we’re interested in. Remember that arrays in JavaScript have zero-based indexes. Changing the content of the HTML <span> element shows the Web page after the user entered the name Mary and pressed the button.

fig 02 21
Figure 21. Changing the content of the HTML <span> element

While manipulating the content of your Web page you may you may need to traverse the DOM tree. The code example below shows you an HTML document that includes JavaScript that walks the DOM and prints the name of each node. If a node has children, the recursive function walkTheDOM() will visit each child.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

    <body>
     <h1>WalkTheDom.html</h1>

     <p>
        Enter your name: <input type="text"
                                name="customerName" id="custName" />
     </p>

     <input type="button" value="Walk the DOM"
                          onclick="walkTheDOM(document.body, processNode)"/>

     <script>
        	function walkTheDOM(node, processNode){

                   processNode(node)
                    node = node.firstChild;

			      while(node){
			         // call wakTheDOM recursively for each child
			         walkTheDOM(node,processNode);
			         node = node.nextSibling;
			      }
            }

         function processNode(node){
            // the real code for node processing goes here

        	console.log("The current node name is "+  node.nodeName);
         }
      </script>
    </body>
</html>

Our function processNode() just prints the name of the current node, but you could implement any code that your Web application requires. Run this code in different browsers and check the output on the JavaScript console. Traversing the DOM in Firefox depicts two snapshots taken in the F12 Developer Tools in Internet Explorer (left) and FIrebug running in Firefox (right).

fig 02 22
Figure 22. Traversing the DOM in Firefox

While some of the output is self-explanatory, there is a number of #text nodes that you won’t find in the code sample above. Unfortunately, Web browsers treat whitespaces differently, and inserts different number of text nodes in the DOM representing whitespaces found in the HTML document. So you’ll be better off using one of the JavaScript frameworks for traversing the DOM cross-browser way. For example, JQuery framework’s API for DOM traversing is listed at http://bit.ly/WXj2r2.

Styling Web Pages with CSS

CSS stands for Cascading Style Sheets. During the last 15 years several CSS specifications reached the level of Recommendation by W3C: CSS Level 1, 2, and 2.1. The latest CSS Level 3 (a.k.a. CSS3) adds new features to CSS 2.1 module by module, which are listed at http://www.w3.org/Style/CSS/current-work.

Tip
You can find CSS tutorial as well as tons of other learning resources at webplatform.org.

You can include CSS into a Web page either by linking to separate files using the HTML tag <link> or by in-lining the styles with the tag <style>. For example, if CSS is located in the file mystyles.css in the folder css add the following tag to HTML:

<link rel="stylesheet" type="text/css" href="css/mystyles.css" media="all">

The <link> tag allows specifying the media where specific css file has to be used. For example, you can have one CSS file for smartphones and another one for tablets. We’ll discuss this in detail in the section on media queries in Chapter 11.

You should put this tag in the section of your HTML before any JavaScript code to make sure that they stiles are loaded before the content of the Web page.

Placing the @import attribute inside the <style> tag allows to include styles located elsewhere:

<style>
   @import url (css/contactus.css)
</style>

What’s the best way of including CSS in HTML? Keeping CSS in multiple files separately from HTML and JavaScript makes the code more readable and reusable. On the other hand, if your Web site has consists of many files, the Web browser will have to make multiple round trips to your server just to load all resources required by the HTML document, which can worsen the responsiveness of your Web application.

HTML documents are often prettyfied by using CSS class selectors, and you can switch them programmatically with JavaScript. Imagine that a <style> section has the following definition of two class selectors badStyle and niceStile:

   <style>
   	 .badStyle{
      	font-family: Verdana;
      	font-size:small;
      	color:navy;
      	background-color:red;
    }

    .niceStyle{
      	font-family: Verdana;
      	font-size:large;
      	font-style:italic;
      	color:gray;
      	background-color:green;
    }
  </style>

Any of these class selectors can be used by one or more HTML elements, for example

<div id="header" class="badStyle">
   <h1>This is my header</h1>
</div>

Imagine that some important event has happened and the appearance the <div> styled as badStyle should programmatically change to <niceStyle>. In this case we need to find the badStyle element(s) first and change their style. The method getElementsByClassName() returns a set of elements that have the specified class name, and since our HTML has only one such element, the JavaScript will use the element zero from such set:

   	  document.getElementsByClassName("badStyle")[0].className="niceStyle";

The next example will illustrate adding a new element to the DOM. On click of a button the code below dynamically creates an instance of type img and then assigns the location of the image to its src element. In a similar way we could have assigned values to any other attributes of the img element like width, height, or alt. The method appendChild() is applied to the <body> container, but it could be any other container that exists on the DOM.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

    <body>
     <h2>Employee of the month</h2>
        <p>
             <input type="button" value="Show me"
                    onclick="setEmployeeOfTheMonth()"/>
        </p>

     <script>

         function setEmployeeOfTheMonth(){

           // Create an image and add it to the <body> element
           var empImage=document.createElement("img");
        	   empImage.setAttribute('src','resources/images/employee.jpg');
        	   document.body.appendChild(empImage);
        	}

     </script>
    </body>
</html>
Tip
Some HTML elements like <div> or <span> have contain other elements (children), and if you need to change their content use their property innerHTML. For example, to delete the entire content of the document body just do this: document.body.innerHTML="".

If you run this example and click on the button "Show me" you’ll see an image of the employee of the month added to the <body> section of the HTML document as shown on After clicking the button "Show me".

fig 02 23
Figure 23. After clicking the button "Show me"

DOM Events

Web browser will notify your application when some changes or interactions occur. In such cases the browser will dispatch an appropriate event, for example load, unload, mousemove, click, keydown etc. When the Web page finished loading the browser will dispatch the load event. When the user will click on the button on a Web page the click event will be dispatched. A Web developer needs to provide JavaScript code that will react on the events important to the application. The browser events will occur regardless of if you provided the code to handle them or not. It’s important to understand some terms related to event processing.

An event handler (a.k.a. event listener) is a JavaScript code you want to be called as a response to this event. The last code sample from the previous section was processing the click event on the button "Show me" as follows: onclick="setEmployeeOfTheMonth()".

Tip
Each HTML element has a certain number of predefined event attributes, which start with the prefix on followed by the name of the event. For example onclick is an event attribute that you can use for specifying the handler for the click event. You can find out what event attributes are available in the online document titled Document Object Model Events.

The preferred way of adding event listener was introduced in the DOM Level 2 specification back in 2000. You should find the HTML element in the DOM, and then assign the event listener to it by calling the method addEventListener(). For example:

document.getElementById("myButton").addEventListener("click", setEmployeeOfTheMonth);

The advantage of using of such programmatic assignment of event listeners is that this can be done for all controls in a in a central place, for example in a JavaScript function that runs immediately after the Web page completes loading. Another advantage is that you can programmatically remove the event listener if it’s not needed any longer by invoking removeEventListener(). The following example is a re-write of the last example from the previous section.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

    <body>
     <h2>Employee of the month</h2>
        <p>
             <input type="button" value="Show me" id="myButton"/> <!-- <1> -->
        </p>

     <script>
         window.onload=function(){         // (2)
         	document.getElementById("myButton").addEventListener("click",
           	                                      setEmployeeOfTheMonth);
         }

         function setEmployeeOfTheMonth(){

           // Create an image and add it to the <body> element
           var empImage=document.createElement("img");
        	   empImage.setAttribute('src','resources/images/employee.jpg');
        	   document.body.appendChild(empImage);

        	 document.getElementById("myButton").removeEventListener("click",
           	                                 setEmployeeOfTheMonth); // (3)
        	}

     </script>
    </body>
</html>
  1. Compare this button with the one from the previous section: the event handler is removed, but it has an ID now.

  2. When the Web page completes loading, a load event is dispatched and the function attached to the event attribute onload assigns the event handler for the button 'click' event. Note that we are passing the callback setEmployeeOfTheMonth as the second argument of the addEventListener()

  3. Removing the event listener after the image of the employee of the month has been added. Without this line each click on the button would add to the Web page yet another copy of the same image.

Each event goes through three different phases: Capture, Target, and Bubble. It’s easier to explain this concept by example. Imagine that a button is located inside the <div>, which is located inside the <body> container. When you click on the button, the event travels to the button through all enclosing containers, and this is the capture phase. You can intercept the event at one of these containers even before it reached the button if need be. For example, your application logic may need to prevent the button from being clicked if certain condition occurs.

Then event reaches the button, and it’s a target phase. After the event is handled by the button’s click handler, the event bubbles up through the enclosing containers, and this is the bubble phase. you can create listeners and handle this event after the button finished its processing at the target phase. The next code sample is based on the previous one, but it demonstrates the event processing in all three phases.

Note that if your event handler function is declared with the event parameter, it’ll receive the Event object, which contains a number of useful parameters. For more information refer to the "Document Object Model Events" online.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
	</head>

    <body>
     <h2>Employee of the month</h2>
        <div id="myDiv">
             <input type="button" value="Show me" id="myButton"/>
        </div>

     <script>
         window.onload=function(){
         	document.getElementById("myButton").addEventListener("click",
           	                                          setEmployeeOfTheMonth);

        	document.getElementById("myDiv").addEventListener("click",
           	                                          processDivBefore, true); // (1)
        	document.getElementById("myButton").addEventListener("click",
           	                                          processDivAfter);

         }

         function setEmployeeOfTheMonth(){

           console.log("Got the click event in target phase");

           // Create an image and add it to the <body> element
           var empImage=document.createElement("img");
        	   empImage.setAttribute('src','resources/images/employee.jpg');
        	   document.body.appendChild(empImage);

        	 document.getElementById("myButton").removeEventListener("click",
           	                                              setEmployeeOfTheMonth);
        	}

         function processDivBefore(evt){
         	console.log("Intercepted the click event in capture phase");

         	// Cancel the click event so the button won't get it

         	// if (evt.preventDefault) evt.preventDefault();        (2)
         	// if (evt.stopPropagation) evt.stopPropagation();
         }

         function processDivAfter(){
         	console.log("Got the click event in bubble phase");
         }
     </script>
    </body>
</html>
  1. We’ve added two event handler on the <div> level. The first one intercepts the event on the capture phase. When the third argument of addEventListener() is true, this handler will kick in during capture phase.

  2. If you uncomment these two lines, the default behavior if the click event will be cancelled and it won’t reach the button at all. Unfortunately, browsers may have different method implementing prevent default functionality hence additional if-statements are needed.

Running the above example will cause the following output in the JavaScript console:

Intercepted the click event in capture phase
Got the click event in target phase
Got the click event in bubble phase

You can see another example of using intercepting the event during the capture phase in the Donate Section of Chapter 2.

Tip
The Microsoft’s Web browsers Internet Explorer 8 and below didn’t implement the W3C DOM Level 3 event model - they handled events differently. You can read more on the subject at this MSDN article http://bit.ly/anZZgZ.

Summary

This chapter was covering the JavaScript language constructs that any professional Web developer should know. A smaller portion of this chapter was illustrating how to combine JavaScript, HTML, and CSS. There are lots of online resources and books that cover just the HTML markup and CSS, and you’ll definitely need to spend more time mastering details of the Web tools like Firebug or Google Developer Tools. Starting from the next chapter we’ll be working on the Save Sick Child application, which will help you in better understanding of how these ingredients of HTML5 work together and compliment each other.