Data Attributes and Templates - Dynamic HTML5 Web Applications with JavaScript and jQuery - HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

Part II Dynamic HTML5 Web Applications with JavaScript and jQuery

1. Lesson 11: JavaScript

2. Lesson 12: Debugging

3. Lesson 13: Functions

4. Lesson 14: Objects

5. Lesson 15: JSON

6. Lesson 16: Document Object Model

7. Lesson 17: jQuery Selection

8. Lesson 18: jQuery Traversal and Manipulation

9. Lesson 19: jQuery Events

10.Lesson 20: Data Attributes and Templates

11.Lesson 21: jQuery Plugins

Lesson 11 JavaScript

JavaScript has been around almost as long as web browsers themselves. It first appeared in 1995 with Netscape Navigator 2.0 and is the only programming language supported by all the most popular browsers. As a result, if you want to build dynamic websites, you need to know JavaScript.

For a long time, JavaScript was dismissed as a second-rate language, only appropriate for implementing basic functionality such as field validation. In the last five years, JavaScript's reputation has improved dramatically. This happened partly as a result of the massive performance increases that have occurred with JavaScript engines, beginning in Chrome and rippling out to all the other major browsers. More important, however, programmers began to re-evaluate the language itself and learned to harness its power.

Although JavaScript contains more than its fair share of idiosyncrasies, and although the designers of the language made some unusual decisions, JavaScript turns out to be a powerful and flexible language when it is used correctly. The goal of the next few lessons is to not only introduce the language, but also to offer some advice on how you should use the language if you want to write large and complex web applications.

This lesson will provide a quick introduction to the data types and syntax of JavaScript. These aspects of the language are reasonably conventional and are easy to pick up for anyone with a background in other programming languages.

JavaScript Console

In this lesson, you will write JavaScript directly in the Chrome JavaScript console. In order to use this, open the contacts.html web page from Lesson 8, and open the development tools using:

· Command+Option+i on OS X

· F12 or Ctrl+Shift+I on Windows

Once the development tools are open, click the Console tab. This provides a command prompt for writing JavaScript and allows you to directly manipulate the current web page. In order to see this, type the equation 1 + 1 at the command prompt. This should display the result immediately, as shown in Figure 11.1.

image

Figure 11.1

Pressing Enter always executes the statement in the console; therefore, if you need to write code that spans more than one line, hold down the Shift key when you press Enter.

In the sections that follow I will insert a > to show I am writing code into the console. You should omit this when you write the same code. Additionally, I will show the response on the next line if appropriate. For instance:

> 1 + 1

2

Data Types

You will start your look at JavaScript by examining the different types it uses to represent data.

Strings

Character strings in JavaScript can be surrounded by either single or double quotes. To see an example, type the following into the console:

> "Welcome to JavaScript"

This is referred to as a string literal because the statement evaluates to the string itself. It is of course possible to assign a string to a variable. For instance:

> s1 = "Welcome to JavaScript";

Note

A semicolon should terminate statements in JavaScript. The semicolon is technically optional, but if it is omitted, JavaScript will insert a semicolon for you, and there are some circumstances where it is inserted in unexpected locations, causing hard-to-understand bugs.

The variable s1 now refers to this string, and if you type s1 at the console, the string will be printed. Additionally, you can ask JavaScript what data type the variable has:

> typeof s1;

"string"

It is also possible to perform operations on a string. Technically these are called methods, as you will see when you look at objects in Lesson 14. In order to see the available methods, simply type s1. in the console; the autocomplete feature will then show the available methods (see Figure 11.2).

image

Figure 11.2

This book is not a reference book so I will not you walk through the entire API, but the following methods are the most commonly used methods on strings:

· toUpperCase: Convert text to uppercase.

· toLowerCase: Convert text to lowercase.

· substr: Extract a portion of the string using a starting and (optional) ending index. For instance, s1.substr(0, 7) returns Welcome. Counting always starts at 0.

· indexOf: Returns the first index of a provided string inside the string; for instance, s1.indexOf('e') returns 1. Counting in JavaScript always starts at 0, so the second character is at position 1.

· length: This is a property of the string rather than a method; therefore, you do not use brackets when invoking it. For instance, s1.length returns 21.

· replace: This method replaces the first occurrence of one string for the new one provided. For instance, s1.replace('e', ‘E') returns “WElcome to JavaScript”.

It is also possible to append text to an existing string using the + operator. If you execute the following, a new string will be returned that concatenates the two strings:

> s1 + " - Let's get started";

If, however, you look at the value of s1 after executing this, you will see it has retained its old value:

> s1;

"Welcome to JavaScript"

Once a string has been assigned a value, it can never be modified (it is immutable). Any time an operation appears to modify a string, a new string is actually created. Therefore, to update the value of s1 you need to assign the result of the expression to it:

> s1 = s1 + " - Let's get started";

Finally, if you need to use special characters inside a string, you can prepend a backslash to it. For instance, the next example contains a ‘ character inside a quoted string so I use a backslash before it:

s2 = 'This is Dane\'s code';

Of course, in this case I could have simply wrapped the string inside double quotes because the quote character would have no special meaning in such a string:

s2 = "This is Dane's code";

Numbers

JavaScript uses a single numeric type for all numbers, including decimals: All numbers are technically 64-bit floating-point numbers.

Variables can be assigned numeric values as follows:

> n1 = 200;

> n2 = 2.432432432;

The typeof operator will confirm these are numbers:

> typeof n1

"number"

JavaScript then supports all the common mathematical operators for manipulating numbers. For example:

> n1 / 2

100

> n1 * (200 + n2);

40486.486486400005

For more advanced operations, JavaScript also provides a library called Math that is modeled on the same library in Java. For instance:

> Math.pow(3,2)

9

> Math.round(n2)

2

JavaScript also supports three special numeric values. These are numbers, but they cannot be represented as conventional numbers:

· Number.POSITIVE_INFINITY: This value is created when a positive number is divided by 0. Although you may have been taught that numbers cannot be divided by 0, because all numbers are floating-point in JavaScript, the language assumes that the number 0 could be a tiny, but still non-zero, number that cannot be represented in 64 bits of memory. If you divide a number by such a tiny number, the result will approach infinity.

· Number.NEGATIVE_INFINITY: This is returned when a negative number is divided by 0.

· NaN: This stands for not-a-number, but confusingly, it is still a number. This value is created when operations on numbers return values that cannot be represented as numbers. For instance: 1 / “hello” or Math.sqrt(-1). It is possible to check for this value using a special JavaScript function: isNaN(Math.sqrt(-1)).

Booleans

Booleans are used to capture the values true and false. For instance:

> b1 = true;

> b2 = false;

Boolean values are commonly returned by logical operations. For instance:

> 10 > 5

true

Null

Before looking at what null is, it is worth looking at variables in slightly more detail. When you execute a statement such as this:

> n1 = 200;

the variable n1 takes on the data type of number. The variable n1 is not intrinsically linked to numbers, however; you can change its type by assigning it a new value:

> n1 = "Testing";

Another way of looking at this is that the variable n1 starts out by referring to the number 200, and then it is changed to refer to the string “Testing”. You can therefore also change n1 so that it refers to nothing at all:

> n1 = null;

null therefore means the absence of a value. JavaScript has a small quirk with null values:

> typeof n1

"object"

This is a historic bug in the language itself: Despite this, null is a distinct data type in JavaScript.

Undefined

The value of undefined is returned if you access a variable, or a property on an object, that does not exist. For instance, if you type the following at the command line, the value of undefined will be returned:

> typeof n3

"undefined"

Arrays

Arrays are not technically a distinct data type; they are a type of object, but it is still worth introducing them in this section.

An array contains zero or more elements of any data type. You can declare an array as follows:

a1 = [];

The initial elements in the array can also be provided as a comma separated list inside the square brackets:

a1 = [1,2,3,4];

You do not need to declare the size of the array; you can simply start inserting elements, and it will expand to support them:

a1[2] = 20;

a1[1] = "hello"

Because arrays are objects, they also support methods; for instance, this will add a new element at the end of the array.

a1.push(200);

while this will sort the array:

a1.sort()

You can access elements in the array by specifying their position inside the square brackets:

> a1[1]

"hello"

The lessons ahead will make extensive use of arrays, and many additional features will be introduced.

Objects

All other values in JavaScript are objects. You will spend a lot of time looking at these over the next few lessons so I will not discuss them here.

Functions

Functions are the basic building blocks of many JavaScript applications. A function in JavaScript accepts zero or more parameters, executes a series of statements, and then optionally returns a value.

You can create a function as follows (remember to hold down the Shift key when entering a new line into the console; you may also decide to copy and paste the code from a text editor):

function doubleTheNumber(num) {

var result = num * 2;

return result;

}

In this example, you are creating a function called doubleTheNumber and have stated that it accepts a single parameter called num.

In the body of the function you then multiply num by 2 and store the result in a local variable called result. Finally, on the last line of the function you return this variable. The curly brackets denote the code block relating to the function.

You can then execute this function as follows:

> doubleTheNumber(9);

18

Notice that the variable result is declared with the var keyword. This means that the variable is local to the function, and is automatically destroyed when the function ends. The var keyword can be omitted, and the function will still work. To prove this, change the function as follows:

function doubleTheNumber(num) {

result = num * 2;

return result;

}

If you execute this, it will continue to work as expected:

> doubleTheNumber(10);

20

The overall outcome is not the same, however. The variable result has been created as a global variable, and will exist even after the function has finished executing. You can see this by executing the following:

> result;

20

Using global variables is dangerous and should be kept to a minimum because there is always the possibly that two independent blocks of code will accidentally use the same variable name.

You will return to look at functions in substantially more detail in Lesson 13.

Control Structures

JavaScript includes a standard set of control structures for looping and branching. These will be familiar to anyone with a programming background because they use the same basic syntax as those in Java, C#, and Python (among others).

It is possible to perform looping with either a for loop or a while loop. The following example uses a for loop to add the contents of an array together:

> a1 = [3,6,4,1,4,9]

> var result = 0;

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

result = result + a1[i];

}

> result

27

The for loop consists of three distinct portions:

· A variable called i is declared to act as the counter; this is initially set to the value 0.

· You declare that looping should continue while the value of i is less than the length of the array (6).

· You declare that the variable i should have its value increased by 1 (i++) each time the loop completes a cycle.

The loop also uses curly brackets to denote its scope so each time the loop executes, the following statement will be executed:

result = result + a1[i];

Because the first index of an array is 0, the first iteration will therefore set the result variable to 3, and so on, until all the elements in the array have been evaluated.

If you would like to see more details as the loop executes, you can add console.log statements to print logging information to the console. For instance:

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

console.log('The value of i is ' + i);

console.log('The value in the array is ' + a1[i]);

result = result + a1[i];

}

The second main loop variant is the while loop. While loops evaluate an expression with each iteration. While this is true, they keep iterating through the loop; if it is ever false the loop ceases. For instance:

var result = 0;

var counter = 0;

while (counter < a1.length) {

result = result + a1[counter];

counter++;

}

result;

You will notice that this still initializes a counter variable to 0 and increments its value with each iteration, but these are done before the loop starts and inside the loop respectively, not in the loop declaration.

JavaScript supports break and continue statements to control loop execution. I will introduce these along with the next subject: control structures. The following function accepts two parameters: an array of positive numbers, and a number. It then adds together all the even numbers in the array and returns true if this sums to more than the number passed as an argument to the second parameter:

function checkCountEven(a1, n1) {

var result = false;

var count = 0;

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

var number = a1[i];

if (number % 2 != 0) {

continue;

}

count = count + number;

if (count > n1) {

result = true;

break;

}

}

return result;

}

You can call this as follows:

> a1 = [3, 6, 4, 1, 4, 9]

> checkCountEven(a1, 20)

false

This function starts by declaring two local variables and then starts looping through the array using a for loop.

Inside the for loop, you start by extracting the number from the array for the position you are at. You then check whether this is an odd number using the expression number % 2 != 0. This expression literally states “return true if the remainder of dividing the number by 2 is not 0”. If this is true, the if block executes.

If the statement returns true, you do not want to count the number so you use the continue keyword to skip immediately to the next loop iteration.

If the number is even, you add it to the result and then check to see whether the running total is greater than the number passed in using another if statement. If this evaluates to true, you know that the overall result must be true, and therefore you do not need to check any more numbers in the loop. You therefore use the break keyword to jump out of the loop immediately, and the function simply returns its result.

Conditional expressions can also support if else and else statements. For instance:

function describeNumber(num) {

if (num >= 0 && num % 2 == 0) {

console.log(num + ' is a positive even number');

} else if (num >= 0 && num % 2 == 1) {

console.log(num + ' is a positive odd number');

} else if (num < 0 && num % 2 == 0) {

console.log(num + ' is a negative even number');

} else {

console.log(num + ' is a negative odd number');

}

}

Notice in this example that you combine multiple Boolean expressions with the and (&&) operator. When this is used, the entire expression returns true only if both sub-expressions are true.

Note

This example has used == to determine if two values are equal. You should generally avoid this because it still returns true if the data types are different. For instance, the string “1” is equal to the number 1. In general, you should use the === operator to determine if values are equal and the !== operator to determine if values are not equal, since this also checks the data-types are the same.

JavaScript also supports a switch statement and a ternary operator for performing conditional logic. Although these will not be introduced, they work in a manner familiar to anyone who has used them in other languages.

Truthy and Falsy Values

One unique aspect of JavaScript is that every value and every expression evaluates to either true or false. To see this in action, create the following function:

function whatAmI(v1) {

if (v1) {

console.log('I am true');

} else {

console.log('I am false');

}

}

Notice that because values evaluate to true or false, you can simply state if (v1) to determine if the argument passed in is true. You can now call this with a variety of values:

> whatAmI("hello")

I am true

> whatAmI("")

I am false

> whatAmI(22)

I am true

> whatAmI(null)

I am false

> whatAmI(8 + 9)

I am true

There are some surprising results here. The following are not true:

· false

· 0 (zero)

· ”” (empty string)

· null

· undefined

· NaN (this value is neither true or false, which is why the isNaN function is needed to detect it)

All other values evaluate to true.

You can actually simplify this function down to a single line as follows:

function whatAmI(v1) {

console.log('I am '+ !!v1);

}

! is the not operator so if it is applied to any variable, it returns the opposite of its Boolean value. You can then negate this with an additional ! operator to return its actual truthy value.

JavaScript code makes extensive use of the fact that values are either true or false in if statements. For instance, if you only want to print the string held in s1 if it has a value, you can use the following:

if (s1) {

console.log(s1);

}

Dynamic Typing

JavaScript is a dynamically typed language. This means that the types of variables are only determined at runtime. Although dynamically typed languages are very flexible in many ways, they are also prone to bugs when types are not as expected. Consider a function such as this:

function add(n1, n2) {

return n1+n2;

}

This function operates as expected when called with two numbers, but what happens if you invoke this as follows?

> add(1, '0')

In this case, the result is the string value 10. This may or may not be what you were expecting.

In a statically typed language, you would declare that n1 and n2 were numbers and refuse to allow it to be invoked with strings. This is not possible in JavaScript.

This is made slightly worse due to the fact that JavaScript is very forgiving. Consider the following examples:

> add(1, [])

"1"

> add(1, true)

2

JavaScript does have its own internal logic to explain these results, but they are seldom intuitive or expected. In order to circumvent issues such as this, it is common to write functions so that they generate errors if they are passed unexpected data types. For instance:

function add(v1, v2) {

if (typeof v1 === "number"

&& typeof v2 === "number") {

return v1+v2;

} else {

throw "both arguments must be numbers";

}

}

Notice the throw statement in this example: This will generate an error to the caller, as shown in Figure 11.3.

image

Figure 11.3

This is still not as explicit as a compile time error, but at least it ensures that, if the program fails, it is obvious why it has failed.

Try It

In this Try It, you will use the techniques you have learned in this lesson to write two utility functions. If you get stuck on either of these examples, you may want to watch the screencast, which will walk through both examples. Completed versions of both functions are available on the book's website.

Lesson Requirements

You will use the Chrome console for these examples. It is, however, recommended that you write the code in a text editor and copy the completed versions into the Chrome console.

Step-by-Step

The first utility function you will create will accept a single parameter, which should be a string, and will return the reverse of the string: If it is passed “Hello,” it will return “olleH.”

1. Start by creating a function called reverse and declare that it accepts a single parameter.

2. Check that the argument passed in is a string: If it is not, then throw an error for the caller.

3. You will construct an empty string variable to hold the result of the operation.

4. You can now iterate through the string one character at a time using a for loop. You will need to initialize a counter variable with an initial value of 0, and loop while this is less than the length of the string.

5. With each iteration, you want to extract the character at the position “length of the string – current count - 1”. This will ensure that you extract the last character of the string on the first iteration, the second to last on the second iteration, and so on. For instance, if the string has seven characters, you will extract the character at position 6 on the first iteration (remember that the count starts at 0 so the last position in a string with seven characters is 6). You can use the charAt method to extract a character at a given position.

6. Once the character has been extracted, you need to append it to the result variable using the + operator.

7. Once the loop completes, you need to return the result.

Once the function is complete, you should be able to call it as follows:

> reverse("Hello");

"olleH"

The second utility function will accept an array of numbers, and return true if the sum of all the positive numbers is greater than the sum of the absolute value of all the negative numbers.

1. Start by creating a function called calculateSums, and declare that it accepts a single parameter, which in this case will be an array.

2. Create two variables to hold the result of the positive and negative numbers respectively. These should be initialized to 0.

3. You will use a while loop in this example so you also need to create a counter variable and initialize it to 0.

4. Create a while loop, and add curly brackets for its code block. The while loop should test that the counter is less than the length of the array.

5. Inside the code block, you need to add an if-else block to determine if the number is greater than 0.

6. If the number is greater than or equal to 0, simply add it to the sum of positive numbers. If it is less than 0, you need to calculate its absolute value using Math.abs() and add the result to the sum of negative numbers.

7. You also need to remember to increase the counter variable by 1 inside the loop. If you omit this, the while loop will run forever: This is called an infinite loop.

8. After the loop finishes, you can simply return whether the sum of positive numbers is greater than or equal to the sum of negative numbers.

It should be possible to call the function as follows:

> calculateSums([-1,2])

true

> calculateSums([-1,2,-3])

false

Reference

Please go to the book's website at www.wrox.com/go/html5jsjquery24hr to view the video for Lesson 11, as well as download the code and resources for this lesson.