CSCE 120 Learning to Code: JavaScript


JavaScript

Source: youtube.com

This section will cover the following


Introduction to JavaScript

Developed by Netscape in mid 1990s for adding dynamic elements to HTML.

Originally known as "LiveScript"; later changed to JavaScript.

JavaScript Versions: Both ECMAScript 5 (ES5) and ECMAScript 6 (ES6) versions are widely used. Some features of ES6 are not supported by all browsers.

JavaScript is a high-level and interpreted programming language.

High-level means it has all the functionalities of well-received language. It has high abstraction from the users, which makes it easy to use. In contrast, C programming language is a low-level language, which is more complicated but gives you more control over low-level processing like memory management.
Interpreted means it does not need to be compiled before it's executed, it is interppreted at runtime.

JavaScript is NOT Java

JavaScript is a cross-platform scripting language

JavaScript is object-oriented

JavaScript is used to make webpages interactive such as animations, clickable / touchable elements and more

One of the most popular programming language in the world

JavaScript is used to develop these type of applications

  • Web
  • Desktop (using Electron)
  • Smartphone and Tablet (Cordova, Ionic, ReactNative, more)
  • Server Side Apps (using NodeJS)
  • Games

Introduction to Development Tools

Online Tools

Online tools are great for demonstrations, proof of concepts, and sharing solutions.

Development Environment and Tools

There are many editors and tools that help accelerate software development; some tools are specifically targeted for web development. Within the web development, some tools are geared toward front-end development and some toward back-end (server side) development. In this class, we will use the latest version of Visual Studio (VS), which is free. VS is designed for full-stack development where both front-end and back-end development can be done. We will also use several tools, such as jQuery and Bootstrap when necessary.

Additional tools

Semantics, Syntax, and Types

JavaScript uses the Unicode character set and is case-sensitive. If you are familiar with one of the C based languages, you will recognize JavaScript code easily. According to Mozilla Developer Network (MDN), "JavaScript borrows most of its syntax from Java, C, and C++, but is also influenced by Awk, Perl and Python"

Variable Declaration

JavaScript presents three keywords for variable declaration: var, let, const


    var firstName; // OR var firstName, lastName;
    let firstName; // OR let firstName, lastName;

    // When using var and let, the variable may be optionally initialized i.e: let firstName = "John";

The var statement declares a variable, while let declares a block scope local variable and was introduced with ES6.

Which one do I use?

Using let is less error prone, however, some older browser may not support let because it was introduced with ES6. Developers need to know where the JavaScript will run before they use new ES6 features. If possible, use let.

const

const stands for constant and are block-scoped, much like variables defined using the let statement. The value of a constant can't be changed through reassignment, and it can't be redeclared. const variables are read-only.

variable names must start with a letter, underscore (_), or the dollar sign ($); subsequent characters can also be digits (0-9)

JS is case-sensitive


    // Three different variable names
    var firstName;
    var FirstName;
    var FürstName; // uses the Unicode character set - ü

Comments in JavaScript

Comments are discarded during script execution


    // a one line comment

    /* this is a longer,
    * multi-line comment
    */

undefined

When a variable is declared with no assigned value specified has the value of undefined

Variable Hoisting

Variable hoisting is an unusual thing about variables in JavaScript. Hoisting makes it possible to refer to a variable declared later, without getting an exception. Variables declared using var are, in a sense, "hoisted" or lifted to the top of the function or statement. Variables that are hoisted always return a value of undefined, even if they are declared and initialized after referencing the variable.

let and const are hoisted but not initialized. Referencing the variable in the block before the variable declaration results in a ReferenceError not undefined With let and const variables are in a "temporal dead zone" from the start of the block until the declaration is processed.

Function hoisting will be covered in the Functions section

Semantics, Syntax, and Types

JavaScript categorizes data types into two:

  • Primitive Types
  • Object

Object is a subject that will be covered later

Primitive Types are as follows:

  • Number. An integer or floating point number
  • String. A sequence of characters that represent a text value
  • Boolean. true and false
  • undefined. A top-level property whose value is not defined
  • null. A special keyword denoting a null value
  • BigInt. An integer with arbitrary precision
  • Symbol. A data type whose instances are unique and immutable. Introduced by ES6

Numbers, Expressions, and Operators

According to MDN, "In JavaScript, numbers are implemented in double-precision 64-bit binary format IEEE 754 (i.e., a number between ±2−1022 and ±2+1023, or about ±10−308 to ±10+308, with a numeric precision of 53 bits). Integer values up to ±253 − 1 can be represented exactly."

Also, the number type has three symbolic values: +Infinity, -Infinity, and NaN (not-a-number). And Number can also be used as an object (objects will be covered later in this class)

BigInt was introduced by ES6, provides the ability to represent integers that may be very large. BigInt and Number values cannot be mixed and matched in the same operation.

Binary, Octal numbers, and Hexadecimal numbers can also be represented in JavaScript.

JavaScript math operations follow the same order of precedence as algebra. The order in which mathematical operations must be executed: Parentheses, Exponents, Multiplication, Division, Addition, Subtraction.

Operators

JavaScript has several types of operators. Below are the most frequently utilized types of operators

  • Assignment operators
  • Arithmetic operators
  • Comparison operators
  • Logical operators
  • Conditional (ternary) operator
  • String operators
  • Unary operators
  • Relational operators

Assignment operators

An assignment operator assigns a value to its left operand based on the value of its right operand.
let name = "John";
x = y;

Arithmetic operators

An arithmetic operator takes numerical values (either literals or variables) as their operands and returns a single numerical value.

JavaScript uses the following operators for arithmetic;

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
  • Modulus (division remainder) (%)
  • Increment (++)
  • Decrement (--) - operands are equal and of the same type.
  • Unary negation (-)
  • Unary plus (+)

Arithmetic operators follow the operator precedence, determined in algebra.

Comparison operators

A comparison operator compares its operands and returns a logical value based on whether the comparison is true.

JavaScript uses the following operators for comparison;

  • Equal (==)
  • Not Equal (!=)
  • Strict Equal (===) - operands are equal and of the same type.
  • Strict Not Equal (!==)
  • Greater than (>)
  • Greater than or equal (>=)
  • Less than (<)
  • Less than or equal (<=)

Logical operators

Logical operators are used to determine the logic between variables or values

JavaScript uses the following logical operators;

  • Logical AND (&&)
  • Logical OR (||)
  • Logical NOT (!)

Conditional (ternary) operator

condition ? val1 : val2
let status = (age >= 18) ? "adult" : "minor";

String operators


    console.log("John " + "Smith"); // console logs the string "John Smith".
    var name = "John";
    name += " Smith";
    console.log(name); // console logs the string "John Smith".

Unary operators

Unary operators have only one operand. The most common used unary operator is typeof

Other unary operators are delete and void

Relational operators

A relational operator compares its operands and returns a Boolean value based on whether the comparison is true.

There are two main relational operators: in and instanceof

Expressions

An expression is a valid unit of code that resolves to a value. JavaScript expressions can be separated into two categories: Assigned expressions and Evaluated expressions.

Assigned expressions are self-explanatory. A value is assigned to a variable x = 5 The value of the variable becomes 5.

Evaluated expressions are more involved. These types of expressions use more than one operation and operators to evaluate the result, which may or may not be assigned to a variable. In other words, evaluated expressions are code snippets that result in a single value. JavaScript has several expression categories: Arithmetic, String, Logical, Left-hand-side, and Primary expressions.

We will dig deep into expressions in the the functions section.

String and Dates

Strings

JavaScript treats strings as a sequence of characters that represent a text value. A string can be any text inside double or single quotes. Each element in the String occupies a position in the String. The first element is at index 0, the next at index 1, and so on. Any data type can be converted to string.

JavaScript treats strings as objects, which gives "string" methods and properties. The most commonly used String Properties are

  • length: Returns the length of a string
  • prototype: Makes it possible to add properties and methods to a string(object)

JavaScript string has a large list of methods. Below are some of the most common use methods

  • charAt() --> Returns the character at the specified index (position)
  • concat() --> Concatenate two or more string to make new string
  • includes() --> Checks whether a string contains the specified string/characters
  • indexOf() --> Returns the position of the first found occurrence of a specified value in a string
  • replace() --> Searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced
  • slice() --> Extracts a part of a string and returns a new string
  • split() --> Splits a string into an array of substrings
  • substr(), substring() --> Extracts a substring from a string
  • toLocaleLowerCase() --> Converts to lowercase letters, according to the host's locale
  • toLocaleUpperCase() --> Converts uppercase letters, according to the host's locale
  • toLowerCase() --> Converts to lowercase letters
  • toUpperCase() --> Converts to uppercase letters
  • trim() --> Removes whitespace from both ends of a string
  • toString() --> Converts to a string(String object)

Dates

JavaScript does not have a Date Type, however Date Object provides the functionality to work with dates. Date objects contain a number that represents milliseconds since January 1, 1970 UTC. When used in browsers, JavaScript will use the browser's time zone and display a date as a full-text string:

Date Object

Date objects are created with the new Date() constructor. When an object is created, its default method is called. Some objects may have more than one default method. These methods are known as a constructor. Which constructor gets called is based on the constructors' signature.

JavaScript Date object has several constructors:


    new Date()
    new Date(year, month, day, hours, minutes, seconds, milliseconds)
    new Date(milliseconds)
    new Date(date string)

Every instance of Date object inherits from Date.prototype. The prototype object of the Date constructor can be modified to affect all Date instances.

There are also several methods provided with the date object. These methods allow date operations and manipulations.

To the full list of properties and methods on Date object, check ou MDN or open your .js file in Visual Studio, create an instance of Date object as seen in the following image.

date-object-instance
JavaScript Date instance

Program & Control Flow

JavaScript programs run top to bottom; every instruction is executed. However, most programs include statements or blocks of code which alters the execution sequence. In this section, we will cover JavaScript statements.

Block statement

Block statements are the most basic and easy to understand. Block is identified by a pair of curly brackets


    statement 1;
    statement 2;
    statement 3;

    var nameES5 = "John";
    {
       var nameES5 = "James";
    }
    console.log(nameES5); // outputs "James"

    let nameES6 = "John";
    {
       let nameES6 = "James";
    }
    console.log(nameES6); // outputs "John"  -- What? I axpected "James"

Another easy to understand statement is used with loops


    //while loop
    while (x < 10) {
       displayValue();
       x++;
    }

Important: block scope was introduced to JavaScript via ES6 (ECMAScript2015). In ES5, variables introduced within a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not define a scope (Source: MDN)

Conditional statements

The if statement is a straightforward example


    if (person.age > 34) {
        eligibleForDiscount();   
        addToGolfTeam();
    }

What's going on: As JavaScript executes instructions top to bottom, it will run into the if statement. The eligibleForDiscount(); will only be executed when the if the condition is true.

if block can included in one or more statements. if may have one or more statements for the condition being false. This is known as else condition. Also, the if statement may include multiple conditions. Each of which may have one or more statements. There may also be nested if.


    if (person.age > 34) {
       eligibleForDiscount();
       addToGolfTeam();
    }
    else if (person.age > 25 && person.age < 34)
    {
       if (person.age < 30) {
       addToSoccerTrainer(); // will help other player in the team
       }
       addToSoccerTeam();
    }
    else {
       addToFootballTeam();
    }
switch

The switch statement works very similarly to the if statement: It a program to evaluate an expression and attempt to match the expression's value to a case label.


    switch (expression) {
       case label_1:
          statements_1
          [break;]
       case label_2:
          statements_2
          [break;]
       default:
          statements_def
          [break;]
    }

Loops and iteration

A loop in programming describes functionality that repeats a set of instructions. Often a set of functionality will iterate a statement based on specified boundaries. For example, repeat the phrase "Good Day!" 5 times. It is clear from the example that the phrase will repeat 5 times, then it will stop. To make it a little more challenging, let's figure out the following statements:
Count 1 to 10, when the number is even, write "Good Day!"
Read the name of all states, if the name contains more than one word, write "Name Split!"

JavaScript supports several kinds of loops.

  • for loop
  • while loop
  • do...while loop
  • for...in loop
  • for...of loop

for loop

JavaScript for loops follows C-family style statement


    for (initialization; testing condition; increment / decrement;)
    {
        statement(s)
    }

for loop executes as follows:

  1. Mark the start of the loop - initialization
  2. Test the exit condition - go through the loop only if true
  3. Execute statement(s)
  4. Update the variable for next iteration - increment / decrement
  5. Terminate loop - when the exit condition is false

    let i;

    for (i = 1; i < 5; i++)
    {
    console.log("Value of i is " + i );
    //alert("Value of i is " + i );
    }

while loop

while loop executes its statement (or block statement) until the condition evaluates to true


    while (testing condition)
    {
        statements(s)
    }

while loop executes as follows - Almost identical to for loop

  1. Initialization occurs outside of the loop
  2. Test the exit condition - go through the loop only if true
  3. Execute statement(s)
  4. Update the variable for next iteration - increment / decrement
  5. Terminate loop - when the exit condition is false

    let i = 1;

    while (i < 5)
    {
    console.log("Value of i is " + i );
    //alert("Value of i is " + i );
    i++;
    }

do while loop

do while is similar to while loop except do wile checks for condition after the statement, not before. do loop is also known as Exit Control Loop: The execution occurs at least one iteration.


    do
    {
    statement(s)
    }
    while (condition);

    let i = 5;
    do
    {
        console.log("Value of i is " + i );
        i++;
    } while (i < 4);

infinite loop

This is the type of a loop that should be avoided.

infinite loop occurs when the condition in a loop never becomes false.


    let i = 2;
    let j = 5;
    while (i < j ) {
      console.log("I will loop forever!...");
      //i++; // This statement will make the statement --> NON infinite
    }

for...in loop

for...in loop is very useful while working with objects. It provides a mechanism to iterate over user-defined properties of an object. We will revisit for...in loop when we learn objects.


    for (variable in Object)
    {
       statement(s)
    }

    //object
    var mainSubjects = {
    first : "HTML",
    second : "CSS",
    third : "JavaScript"
    };
    //counter variable
    let i = 0;
    //for...in loop
    for (var subject in mainSubjects) {
       i++;
       console.log(i + " - " +  mainSubjects[subject]);
    }

for...of loop

for...of loop is useful iterating over all collections and collections of objects such as objects, Array, Map, Set, arguments object. We will revisit for...of loop when we learn objects.


    for (variable of Object)
    {
       statement(s)
    }

    
    //let animals = ['🐈', '🐔', '🐕'];
    let animals = ['Cat', 'Bird', 'Dog',];

    for (let animal of animals) {
    console.log("Animal is " + animal);
    }

Functions

In programming, a function is a smaller program or a "subprogram" that completes a task. Functions are executed when they are called (or invoked). Functions can be called by code within the larger program, often external to the function code. A function can also be called by its own code, which is known as recursion. These type of functions are called recursive functions. Like the program itself, a function is composed of a sequence of statements called the function body. Values can be passed to a function, and the function may return a value.

Contrary to most C based languages, JavaScript treats functions as objects. In other words, JavaScript functions can have their own properties and methods just like any object. Moreover, ES6 introduced classes to JavaScript. While a JavaScript class is a type of function, "classes" are declared with the class keyword. Typically classes are the blueprint for creating an object.

Defining Functions

JavaScript provides two different ways to define a function

Function declaration

This method defines a named function. Below are the basic components of a function:

  • Function Name
  • Zero or more parameters. The parameters are enclosed in parentheses and separated by commas
  • Statements that define the function, enclosed in curly brackets, { }

    function name(parameters){
       statements
    }

    // ------Example: -------------
    function square(number) {
       return number * number;
    }

square is the name of the function. number is the parameter. This example has just one parameter. The word argument is also used instead of parameter however, there are important distinctions between the two. In this class, we can use the two terms interchangeably.
return number * number; is the statement. Function declaration is the method used for creating functions by most C based programming languages.

Function expression

Using Function Expressions, we can define named or anonymous functions. An anonymous function is a function that has no name.


    let name = function(parameters){
       statements
    }

    // ------Example: -------------
    let square = function (number) {
       return number * number;
    }

ES6 introduced Arrow Function Expression which is a shorter syntax for writing function expressions. The above functions can be written as follows


    let name = (parameters) => {
       statements
    }

    // ------Example: -------------
    let square = (number) => {
       return number * number;
    }
Calling (Invoking) a Function

When a function is called, the code inside the function gets executed. Defining a function does not execute it. Calling a function is also known as function invocation.
To call a function: Reference the function name, followed by an open and closed parenthesis (). If there are any parameters, include them in the parentheses, separated by comma.
The order of the parameters matter


    square(2); // calls the function (square) which will execute the code in the square function.

It is clear we can call the square function whenever we like: square(3); or square(24) so on.

JavaScript provides the notion of function expressions that are invoked as soon as the function is declared, without explicitly being called. This idea is very useful when functions are used only once.
These types of functions are known as Immediately Invokable Function Expression (IIFE).


    (function() {
        statements
    })();

    // OR May use the following syntax (ES6) 
    (() => {
        statements
    })();

Example of Recursive function


    function factorial(n) {
       if ((n === 0) || (n === 1))
       {
          return 1;
       }
       else
       {
          return (n * factorial(n - 1));
       }
    }

Function Scope

Prior to ES6, JavaScript had two scopes: Global scope and Function scope.
Global scope: Variables that are declared outside of a function have global scope, which is accessible from anywhere in the code.
Function scope: Variables that are declared within a function have function scope, which is accessible from that function (and any nested function) only.

ES6(ES2015) introduced Block Scope local variables using let or const keywords.


    // global scope
    var age = 90,
    height = 5.11,
    name = "Jim Miller";

    // This function is defined in the global scope
    function getPersonalInfoGlobal() {
       return name + " is " + age + "years old and " + height + "ft tall";
    }

    getPersonalInfoGlobal(); // Returns ???

    //function example
    function getPersonalInfo() {
       var age = 20,
       height  = 6;
       return name + " is " + age + "years old and " + height + "ft tall";
       //A nested function example
       //function info() {
       //  return name + " is " + age + "years old and " + height + "ft tall";
       //}
       //
       //return info();
    }

    getPersonalInfo(); // Returns ???

    // describe let and const scope as well.

Closures

JavaScript scope is built around functions. A function can access variables outside of it, but not the ones inside. In the case of nesting of functions, JavaScript grants the inner function full access to all the variables and functions defined inside the outer function. The inner function also has access to all other variables and functions that the outer function has access to. However, the outer function does not have access to the functions and variables defined inside the inner function. This is very similar to the notion of encapsulation in object oriented programming languages such as C++, Java or C#. A closure gives the inner functions the ability to have access to the outer functions's scope even after the outer function goes out of scope.


    // Method 1: Nested function
    function manageStudent() {
    var name = "John";        // local variable (local to manageStudent function)
    function displayName() {  // displayName() is the inner function, a closure
    alert(name);              // use variable declared in the parent function
    }
    return displayName;
    }
    manageStudent();

    // Method 2: Closure - The same result
    function manageStudent() {
    var name = "John";        // local variable (local to manageStudent function)
    alert("in manageStudent but outside of displayName");

    function displayName() {  // displayName() is the inner function, a closure
    alert(name);              // use variable declared in the parent function
    }
    return displayName;
    }

    var student = manageStudent(); // executes manageStudent function. done
    student();                     // executes displayName function because that's what was returned by manageStudent

In Method 2, the outer function returns the inner function (displayName). However, once the outer function is executed, it goes out of scope, not when the inner function is executed using

 student(); 
, it displays the student name ("John"). This is the behaviour made possible by closure. In most programming language, this behaviour is not possible.

Closures also provide emcapsulation, the ability to declare variables and methods that can only be accessed by other methods in the same function. These variables and methods are known as private variables and methods.

Classes

In almost all programming languages, Classes are a template for creating objects. They encapsulate data with code to work on that data. While this statement is true, in JavaScript Classes are are also function, more like "special functions", and just as you can define function expressions and function declarations, the class syntax has two components: class expressions and class declarations. There are however some differneces between functions and classes. The noticeable difference between the two is the fact that functions are hoisted while classes cannot be hoisted. Developers need to declare their class and then access it, otherwise code like the following will throw a ReferenceError.

Note: Hoisting exists for function declarations.

Class Declaration

To declare a class, you use the class keyword with the name of the class

    class Rectangle {
        constructor(height, width) {
            this.height = height;
            this.width = width;
        }
    }

    class Circle {
        constructor(x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
        }
    }


The body of a class is the part that is in curly brackets {}. This is where you define class members, such as methods or constructor.

JavaScript classes provide three type of methods

The Constructor Method

The constructor method is a special method for creating and initializing an object created with a class. There can only be one special method with the name "constructor" in a class. A SyntaxError will be thrown if the class contains more than one occurrence of a constructor method. A constructor can use the super keyword to call the constructor of the super class.


    class Circle {
        constructor(x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
        }
    }


Static Methods

The static keyword defines a static method for a class. Static methods are called without instantiating their class and cannot be called through a class instance. Static methods are often used to create utility functions for an application.


    class Point {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    
      static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;
    
        return Math.hypot(dx, dy);
      }
    }
    
    const p1 = new Point(5, 5);
    const p2 = new Point(10, 10);
    p1.distance; //undefined - cannot be used this way
    p2.distance; //undefined - cannot be used this way
    
    console.log(Point.distance(p1, p2)); // Use the name of the class directly

Prototype Methods


    class Rectangle {
      constructor(height, width) {
        this.height = height;
        this.width = width;
      }
      // Getter
      get area() {
        return this.calcArea();
      }
      // Method
      calcArea() {
        return this.height * this.width;
      }
    }
    
    const square = new Rectangle(10, 10);
    
    console.log(square.area); // 100                        
                        

You may implement classes with static and non-static methods as well


    class Animal { 
      speak() {
        return this;
      }
      static eat() {
        return this;
      }
    }                        
                        

Instance properties


    class Circle {
        constructor(x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
        }
    }


x, y, and r are instance properties and must be defined inside of the class.

Arrays

In computer science, arrays are a collection of data, which are compartmented in a separate cell and each cell is identified by an index. JavaScript does not have an explicit array data type, however, arrays are treated as objects and have predefined methods for manipulating arrays. There's more than one way that JavaScript allows us to create arrays.


    var elementArray = new Array(element-0, element-1, ..., element-N);
    var elementArray = Array(element-0, element-1, ..., element-N);
    var elementArray = [element-0, element-1, ..., element-N];

In the code above, elementArray is created in three different ways and initialized. When array elements are specified at creation time, it's said that the array is initialized. The most important property of an array is length which sets the number of arguments.

The following syntax is called an "array literal" or "array initializer." It's shorter than other forms of array creation and is generally preferred.


    var elementArray = [element-0, element-1, ..., element-N];

Often, developers would create arrays with a known length but without any items.


    var elementArray = new Array(arrayLength);
    var elementArray = Array(arrayLength);

    // Or the preferred method
    var elementArray = [];
    elementArray.length = arrayLength;

In the above code, arrayLength must be a number https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections

Techniques for Creating an Array

    // Creates an array with three element: 4, 5, 6
    var myarray = [4, 5, 6];

    // Creates an array with no elements and myarray.length set to 42;
    var myarray = Array(42);
    //This is equivalent to the following two lines
    var myarray = [];
    myarray.length = 42;

Creating an empty array, then populating


    let employees = []; // Create an empty array
    employees[0] = "John Smith";
    employees[1] = "Muhammed Ali";
    employees[2] = "Jane Tarzan";

    employees.length; // will return 3

Important: hote that the indexes are numeric and integer values. If we supply a non-integer value to the array operator in the code above, we will transform the array into an object. The array length will remain the same.


    let employees = []; // Create an empty array
    employees[0] = "John Smith";
    employees[1] = "Muhammed Ali";
    employees[2] = "Jane Tarzan";
    employees[3.8] = "Princess Fiona";

    alert(employees.length);     // return 3
    or
    alert(employees['length']);  // return 3

    //object notation
    alert(employees.hasOwnProperty(1));    // return true
    alert(employees.hasOwnProperty(3.8)); // return true
    //
    alert(employees[1]);                 // return "Muhammed Ali"
    alert(employees[3.8]);              // return "Princess Fiona"
Create and populate an array at the same time

    let name = "John";
    let randomStuff = new Array("CSCE 120", name, 3.14159);

    let fruits = ["Apple", "Orange", "Banana"];
Reading (Traversing) array elements

In JavaScript, we refer to an array's elements by using the element's index or ordinal number. For example, using the fruits array above, we can refer to the first element of the array as fruits[0] and the second element of the array as fruits[0]. The index of the elements begins with zero.

In order to read all the elements of an array and perform operations, we iterate over the elements of the array referencing the index of the element. The process is accomplished using loop(s).

The following snippet iterates over the values of the fruits array and alerts each value


    let fruits = ["Apple", "Orange", "Banana"];
    for (var i = 0; i < fruits.length; i++) {
      //Alert each element in the fruits array
      alert(fruits[i]);
    }

The forEach() method provides another way of iterating over an array:


    let fruits = ["Apple", "Orange", "Banana"];
    fruits.forEach(function(fruit) {
    alert(fruit);
    });

    // ES2015 (ES6) introduced the Arrow Functions. The above forEach can be written as follows, using the arrow function
    fruits.forEach(fruit => alert(fruit));

Array Methods

JavaScript Arrays have many methods. In order to understand Array methods, we should have a solid understanding of functions. Review the functions section if you need to. In this section we will cover the most commonly used methods.

concat()

This method joins two or more arrays and returns a new array.


    let fruits = ["Apple", "Orange", "Banana"];
    let vegetables = ["Beets", "Asparagus", "Spinach"];
    let fruitsandvegetables = fruits.concat(vegetables);
    // fruitsandvegetables is ["Apple", "Orange", "Banana", "Beets", "Asparagus", "Spinach"]
join()

This method joins all elements of an array into a string.


    let fruits = ["Apple", "Orange", "Banana"];
    let fruitsJoined = fruits.join(' - ');
    // fruitsJoined  is "Apple - Orange - Banana"
push()

This method adds one or more elements to the end of an array and returns the resulting length of the array.


    let fruits = ["Apple", "Orange", "Banana"];
    fruits.push("Pear");
    // fruits is now ["Apple", "Orange", "Banana", "Pear"]
pop()

This is the opposite of push() method. Removes the last element from an array and returns that element


    let fruits = ["Apple", "Orange", "Banana"];
    let last = fruits.pop();
    // last is "Banana"
    // fruits is now ["Apple", "Orange"]
shift()

This method removes the first element from an array and returns that element.


    let fruits = ["Apple", "Orange", "Banana"];
    let first = fruits.shift();
    // first is "Apple"
    // fruits is now ["Orange", "Banana"]
unshift()

This method is not necessarily the opposite of shift().
unshift() adds one or more elements to the front of an array and returns the new length of the array.


    let fruits = ["Apple", "Orange", "Banana"];
    fruits.unshift("Apricot", "Avocado");
    // fruits is now ["Apricot", "Avocado", "Apple", "Orange", "Banana"]
slice(start_index, end_index)

Extracts a section of an array and returns a new array.


    let fruits = ["Apricot", "Avocado", "Apple", "Orange", "Banana"];
    let sliced_fruits = fruits.slice(1, 4); // starts at index 1 and extracts 3 elements (4 - 1 is 3)
    // sliced_fruits is  ["Avocado", "Apple", "Orange"];

splice(index, count_to_remove, addElement1, addElement2, ...)

This method removes elements from an array and replaces them with new items. The replacement is optional. It then, returns the items which were removed from the array.


    let fruits = ["Apricot", "Avocado", "Apple", "Orange", "Banana"];
    fruits.splice(1, 3, "Cherry", "Clementine", "Cucumber", "Dates");
    // fruits is now ["Apricot", "Cherry", "Clementine", "Cucumber", "Dates", "Banana"];
    // This code started at index one which refers to "Avocado",
    // removed 3 elements there, and then inserted all consecutive elements in its place.

indexOf(searchElement[, fromIndex])

This method searches the array for searchElement and returns the index of the first match.


    let fruits = ["Apricot", "Avocado", "Apple", "Apricot", "Orange", "Banana", "Apricot", "Apple" ];
    let first_apricot = fruits.indexOf("Apricot");      //first_apricot is the index of first "Apricot" which is 0
    let second_apricot = fruits.indexOf("Apricot", 2); //second_apricot is the index of second "Apricot" which is 3
    let non_existance = fruits.indexOf("CSCE120");    //non_existance is -1. Indication of not found

lastIndexOf(searchElement[, fromIndex]) worked similar to indexOf(searchElement[, fromIndex]) however it starts at the end and searches backwards.

forEach(callback[, thisObject])

This method processes every array item. Within forEach, there is a function that processes every item (in this case alert), JavaScript uses the word callback for such functions. Therefore, forEach(callback[, thisObject]) performs callback on every array item.


    let fruits = ["Apricot", "Avocado", "Apple", "Orange", "Banana"];
    fruits.forEach(function(item) {
    alert(item);
    });

map(callback[, thisObject])

map method is similar to forEach but it returns a new array. In other words, the map, returns a new array of the return value from executing callback on every array item.


    let fruits = ["Apricot", "Avocado", "Apple", "Orange", "Banana"];
    let big_fruits = fruits.map(function(item) {
    return item.toUpperCase();
    });
    alert(big_fruits); // big_fruits is now ["APRICOT", "AVOCADO", "APPLE", "ORANGE", "BANANA"];

filter(callback[, thisObject])

Returns a new array containing the items for which callback returned true.


    let fruits = ["Apricot", 10, "Avocado", 20, "Apple", 30, "Orange", 40, "Banana"];
    let number_list = fruits.filter(function(item) {
    return typeof item === 'number';
    });
    alert(number_list); // number_list is now [10, 20, 30, 40];

every(callback[, thisObject]) returns true if callback returns true for every item in the array.

some(callback[, thisObject]) returns true if callback returns true for at least one item in the array.

reverse() and sort() are self-explanatory.

Objects & Collections

In JavaScript, almost everything is an object, which is a collection of properties, and a property is an association between a name (or key) and a value. A property's value can be a simple type or it can be a complex type such as another object or even a method. Subsequently, while JavaScript does not the fit the norm of Object Oriented Programming languages, it is designed on a simple object-based paradigm.

Object definition and initialization

JavaScript provides more than one way to create objects.


    var car = new Object(); // car object. This method uses constructor function
    const person = {};     // person object. 

Once an object is created, we create its properties or we associate properties to it. JavaScript allows us to use more than one to set and get object properties.

Below, we use dot-notation for setting the object's properties.


    var car = new Object(); // car object
    car.make = 'Ford';
    car.model = 'Mustang';
    car.year = 1999;

Bracket notation can be used as well. The result is the same.


    var car = new Object(); // car object
    car["make"] = 'Ford';
    car["model"] = 'Mustang';
    car["year"] = 1999;

Often, we will initilize or polupate our object at the creation time, as follows. This method is known as creating the object "using object initializer".


    const person = {
    name: ["John", "Smith"],
    age: 32,
    gender: "Male",
    interests: ["Playing Soccer", "Skiing"],
    bio: function() {
    alert(this.name[0] + " " + this.name[1] + " is " + this.age + " years old. He likes " + this.interests[0] + " and " + this.interests[1] + ".");
    },
    greeting: function() {
    alert("Hi! I'm " + this.name[0] + ".");
    }
    };

Accessing or reading object and its properties and methods is the same. objectName.propertyName

Example:


    person.name[0]; // outputs "John"" 
    person.age; // outputs 32

As we can create nested objects, we can also create array of objects.

this

In JavaScript, this keyword refers to the current object the code is being written inside. For example, if you are using this in a function, it refers to the function. If you are outside of the all functions then it refers to the windows object.


    const person = {
    name: ["John", "Smith"],
    age: 32,
    gender: "Male",
    interests: ["Playing Soccer", "Skiing"],
    bio: function() {
    alert(this.name[0] + " " + this.name[1] + " is " + this.age + " years old. He likes " + this.interests[0] + " and " + this.interests[1] + ".");
    },
    greeting: function() {
    alert("Hi! I'm " + this.name[0] + ".");
    }
    };

In the above alert(person.greeting()); will alert

 Hi! I'm John. 
.
In this example, this refers to person. We can say this is replacement of person

When more than one person object is created using constructor notation, this will always ensure that the correct values are used when a member's context changes. For example, two different person object instances may have different names, but each will want to use their own name when saying their greeting.

Collections

JavaScript divides Collections into two main categories:

  • Indexed collections
  • Keyed collections

Arrays are a good example of indexed collections. Review the Arrays section for details.

JavaScript also provides collections of data which are ordered by a key such as Map and Set objects. This type of collection contains elements which are iterable in the order of insertion.

Map

The Map object is a collection of unique keyed data items, holds key-value pairs and remembers the original insertion order of the keys. The Map object can be treated like any other JavaScript object and it allows keys of any type; however, each key has to be unique.

The Map has several built-in methods. The example below demonstrates how to create Map, set, get, delete items


    let departments = new Map();
    departments.set("Computer Science", "Prepares students for the most innovative, challenging and promising careers of the 21st Century");
    departments.set("Chemistry", "Research aims to prevent resistance to staph infection treatment");
    departments.set("Music", "Music Education and Performance at its best!");
    departments.set(5, "The most referenced digit");

    departments.size; // 4

    departments.get("Chemistry"); // "Research aims to prevent resistance to staph infection treatment"
    departments.get("Biology"); // undefined

    departments.has("Chemistry"); // true
    departments.has("Biology"); // false

    departments.delete("Chemistry"); // false

    departments.size; // 3

Looping through the items in the Map object can easily be accomplished using JavaScript loop statements
Example: using for...of loop to return an array of [key, value] for each item.


    for (var [key, value] of departments) {
    alert(key + " => " + value);
    }

    // using forEach:
    departments.forEach( (value, key, map) => {
    alert(`${key} => ${value}`); 
    });

Sets

A Set is a special collection of values or "set of values". Set is different from maps in that set is without keys. Each value in a Set may only occur once.


    let toys = new Set();
    toys.add("Mr. Potato Head");
    toys.add("Buzz Lightyear");
    toys.add("Sheriff Woody");
    toys.add(5);

    toys.size; // 4

    toys.has(1); // false
    toys.has(5); // true
    toys.has("Sheriff Woody"); // true

    toys.delete("Mr. Potato Head"); // true
    
    toys.size; // 3

    // iterating over each item
    for (let item of toys) {
    alert(item);
    }

Map and Set objects have their respective WeakMap and WeakSet objects. Read more on MDN

Web Programming with JavaScript

Web programming requires detail knowledge of every item that makes and serves a web application. In this section, we will learn how to program large objects like The Browser Object Model (BOM), The Document Object Model (DOM) as well as JavaScript APIs that interact with HTML elements

The Browser Object Model (BOM)

BOM provides JavaScript with the ability to manage and to interact with the web browser, not the content of the page. There is no standard defined for BOM, hence each browsers may have their own implementation. The main object is the window object which is the very root element, everything else is attached to it either directly or indirectly. Java Script has a direct access to it. Browser instances or tabs do not share window object, each has their own.
The window is the most global JavaScript object; any global variables become properties and any global functions become methods of the window object.

window Objects
window Objects

When an HTML page loaded into a browser window, it becomes a Document object (hence DOM) which is an object in the BOM. Therefore, BOM comprise DOM (Document Object Model).

The window object has a many objects, methods and properties.
Below are the important BOM objects:

  • document
  • location
  • history
  • navigator
  • screen
  • timing
  • cookies
  • frames

The document will be covered in next section.

Size Properties

    window.innerHeight
    window.innerWidth 
Basic Methods

    window.alert() // no need to use windows
    //alert("Hello CSCE 120");
    //Confirm Box
    if (confirm("Press a button!")) {
    alert("You pressed OK!");
    } 
    else 
    {
    alert("You pressed Cancel!");
    }

    //more ..
    window.open();
    window.close();
    window.resizeTo();

The most frequently used methods are timing functions. setTimeout and setInterval


    ///setTimeout. Runs only one time.
    function timeoutFunction()
    {
    setTimeout(function () {
    alert("Hello CSCE after 1 sec");
    }, 1000);
    }
    timeoutFunction();

    // You can make it to keep running after every (interval)
    // Important: The counter functions get called two times. 
    const elem = document.getElementById("display");
    var i = 0;
    var counter = function test() {
    i++;
    if (i > 10) {
    i = 0;
    }
    elem.innerHTML = i.toString();
    setTimeout(counter, 1000)
    }
    counter();

    //setInterval. Runs after every interval
    var i = 0;
    var intervalId = setInterval(function(){
    if(i === 10){
    clearInterval(intervalId);
    }
    console.log(i);
    i++;
    }, 1000);

We will cover other objects and methods using examples.

The Document Object Model (DOM)

DOM is an application programming interface (API) for HTML and XML documents. When a web page is loaded, the browser constructs the Document Object Model (DOM), which is a tree like representation of elements in the page. JavaScript accesses and manipulates the DOM via a series of APIs.

Document Objects
Document Objects
Accessing the DOM

Once JavaScript is references in an HTML page, it has immediate access to document, window objects. These objects provide a array of interfaces for accessing and manipulating the document.

The important objects are as follows:

  • Document : This object is the root document object itself
  • Node : Every object located within a document is a node which can be an element node, a text node or an attribute node.
  • Element : The element object is based on node. Often used interchangeably
  • NodeList : A nodeList is an array of elements
  • Attribute : An interface for exposing attributes
  • NamedNodeMap : A namedNodeMap is like an array, but the items are accessed by name and/or index

The following is the most commonly used APIs for manipulating DOM.

  • document.getElementById(id)
  • document.getElementsByTagName(name)
  • document.createElement(name)
  • parentNode.appendChild(node)
  • element.innerHTML
  • element.style.left
  • element.setAttribute()
  • element.getAttribute()
  • element.addEventListener()
  • window.content
  • window.onload
  • console.log()
  • window.scrollTo()
Read and Update Element

In order to read or make updates to an element, one needs to read the element first. getElementById("elementID") will find the element in the document and returns it as Element object

According to MDN, the Document method getElementById() returns an Element object representing the element whose id property matches the specified string. Since element IDs are required to be unique if specified, they're a useful way to get access to a specific element quickly.

Syntax

    var element = document.getElementById(id); 
Example

document.getElementById returns the DOM element, if the element exist. null if there is no match (element is not found).


    <html>
    <head>
    <title>getElementById example</title>
    </head>
    <body>
    <p id="loremIpsum">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam ac metus consectetur, efficitur libero vitae, efficitur velit.</p>
    </body>
    </html>

    function changeColor(betterColor) {
    var elem = document.getElementById("loremIpsum");
    elem.style.color = betterColor; // "blue"
    }

Also, JavaScript has access to the querySelector() family of interface which are commonly used get access to an element that does not have an ID. querySelector() can be utilized to find the element using any selector. By default, querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned

Syntax

    var element = document.querySelector(selectors);

Example:


    //Return (get) the first element in the document with the class "myclass"
    var element = document.querySelector(".myclass");

    // Return the first <input> element with the name "login" (<input name="login" />) 
    located inside a <div>
    whose class is "user-panel main" (<div class="user-panel main">)
    var element = document.querySelector("div.user-panel.main input[name='login']");

In order to get a list of the document's elements that match the specified group of selectors querySelectorAll() is utilized. The syntax is similar to querySelector()

Examples

    //To obtain the NodeList of all of the <p> elements in the document
    var elements = document.querySelectorAll("p");

    //Get the list of all <div> elements within the document with a class of either note or alert
    var matches = document.querySelectorAll("div.note, div.alert");

    //Get the list of <p> elements whose immediate parent element is a <div>
    //with the class highlighted and which are located inside a container whose Id is "test"
    var container = document.querySelector("#test");
    var matches = container.querySelectorAll("div.highlighted > p");

    //Get the list of the list items contained within a list whose ID is "userlist" which
    //have a "data-active" attribute whose value is "1"
    var container = document.querySelector("#userlist");
    var matches = container.querySelectorAll("li[data-active='1']");

Once we have the NodeList of matching elements, we can examine it just like any array. Use standard array notation to access the contents of the list.


    var matchedItems = userList.querySelectorAll(".highlighted");

    matchedItems.forEach(function(userItem) {
       // process each item
       alert(userItem);
    });
Create an Element

The document object provides us with createElement() method to create an HTML element in the DOM. We can create a particular element (tag) if we specify a tag name at the time of creattion. Otherwise we will create an unknown element.

Syntax

    var element = document.createElement(tagName[, options]);
Example

    var div = document.createElement("div");
    div.textContent = "CSCE 120 is the cool";
    div.setAttribute('class', 'colorfulbackground');
    document.body.appendChild(div);

In the code above, createElement is used to create an element (div tag). After creating div, we use textContent property to for setting text content. Then we add a class to the div using setAttribute At this time we may set more properties if we need to. Once we are done setting all of the properties, we need to append our tag to an existing tag using appendChild property. In this example, we append to the body element.

Removing an Element

The removeChild() method removes a child element(node) from the DOM and returns the removed element.

Example:


    <div id="parentelement">
    <div id="childelement"></div>
    </div>

    let par = document.getElementById("parentelement");
    let chld = document.getElementById("childelement");
    let removedElement = par.removeChild(chld);

Check out MDN for the comprehensive list of document object, methods and properties.

JavaScript Events

Events are an transformations that occurs as a result of the user action or as result of state change of some components. Web developers often handle varies events, most of which are HTML DOM events. JavaScript interacts with HTML events, in other word, JavaScript can be executed when an event occurs.

Example of DOM events:

  • clicks event: when a user clicks the button
  • load event: when a web page has loaded
  • mouse event: when the mouse moves over an element
  • change event: when an input field is changed
  • submit event: when an HTML form is submitted
  • key event: when a user strokes a key

Common HTML Events

By far, the most commonly used event is the click event.

Methods to introduce Events

1. Inline
The click event may be used inline, similar to css inline.

    <h1 onclick="this.innerHTML = 'Hello, You just clicked me'">Click on this text!</h1>

    // or you can use a function
    <h1 onclick="changeText(this)">Click on this text!</h1>

    function justClickedMe(elem) {
    elem.innerHTML = "Hello, You just clicked me";
    }

2. Assign functionality to an event in JavaScript

    <h1 id="clickableHeader" >Click on this text!</h1>

    document.getElementById("clickableHeader").onclick = justClickedMe;

    function justClickedMe() {
    var elem = document.getElementById("clickableHeader");
    elem.innerHTML = "Hello, You just clicked me";
    }

Clearly the 2nd method is superior than than the 1st one, in terms of seperating the html code from html code.

3. Using addEventListener method

The addEventListener() method sets up a function that will be called whenever the specified event is delivered to the target. The addEventListener() may be setup for HTML Elements, Document and window. The important distinction is that the target need to be an object that supports XMLHttpRequest. We will cover XMLHttpRequest in Data Access Using HTTP section.

Syntax for using addEventListener() method

    //The common Syntax
    target.addEventListener(type, listener, useCapture);

    //The official syntax from MDN(https://developer.mozilla.org)
    target.addEventListener(type, listener[, options]);
    target.addEventListener(type, listener[, useCapture]);
    target.addEventListener(type, listener[, useCapture, wantsUntrusted  ]); // Gecko/Mozilla only

  • target: is often a DOM element but it could be Document or window
  • type: is a case-sensitive string representing the event type to listen for. Example: "click"
  • listener: is function that implements the logic when the event occurs
  • useCapture: is a boolean value specifying whether to use event bubbling or event capturing. This parameter is optional.

    <h1 id="clickableHeader" >Click on this text!</h1>

    var elem = document.getElementById("clickableHeader");
    element.addEventListener("click", justClickedMe);

    function justClickedMe() {
    elem.innerHTML = "Hello, You just clicked me via addEventListener";
    }

    //window event
    window.addEventListener("resize", justStrachedMe);

    function justStrachedMe() {
    elem.innerHTML = "Hello, You just Strached the window";
    }
A Good Example


    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>JavaScript addEventListener()</title>
        <style>
            * {
                text-align: center;
            }
        </style>
    </head>
    <body>
        <h2>addEventListener()</h2>

        <p>This example demonstrates how addEventListener() method is setup and used.</p>

        <p>Square - this function was in assigment 7.</p>
        <p>Enter a number in the text field below, then click the button to perform a calculation.</p>

        <div><input type="text" id="txtInput" /></div>
        <div><button id="btnCalculate">Calculate</button></div>

        <p id="result"></p>

        <script>

            var input = document.getElementById("txtInput");
            var btn = document.getElementById("btnCalculate");
            var result = document.getElementById("result");

            //Method 1: Not so clean
            //btn.addEventListener("click", square);

            //function square() {
            //    var number = parseInt(input.value);
            //    result.innerHTML =  number * number;
            //}

            //Method 2: cleaner
            btn.addEventListener("click", function () {
                var number = parseInt(input.value);
                if (isNaN(number)) {
                    result.innerHTML = "Input should be a numeric value";
                    return;
                }
                var squared = square(number);
                result.innerHTML = "The square of " + number + " is " + squared;
                //result.innerHTML =  "The square of " + number + " is " + square(number);
            });

            function square(number) {
                return number * number;
            }

        </script>

    </body>
</html>

Forms

Forms are utilized to collect data from the users. Forms consist of a subset of special HTML elements which allow users to enter data. The data, collected from the user input, is sent to a server for processing

In this section, we will demonstrate a web form and how it can be coded using JavaScript.


    <form class="contact_form" action="" method="post" name="contact_form" id="contact_form">
        <ul>
            <li>
                Requered Fields
            </li>
            <li>
                <label>Username:</label>
                <input type="text" required pattern="\w{5,90}" name="username" id='username' placeholder="TonyArslan" />
                <span class="form_hint">Minimum 5 characters long, no spaces</span>
            </li>
            <li>
                <label>Email:</label>
                <input required type="email" name="email" id='email' placeholder="tony@arslan.com" />
                <span class="form_hint">should be email adress</span>

            </li>
            <li>
                <label>Password:</label>
                <input pattern="\w{5,90}" type="password" name="passwordOne" id="passwordOne" />
                <span class="form_hint">Minimum 5 characters long</span>
            </li>
            <li>
                <label>Confirm Password:</label>
                <input type="password" name="passwordTwo" id="passwordTwo" />
            </li>
            <li>
                Optional Fields
            </li>
            <li>
                <label>First Name</label>
                <input pattern="\w{1,90}" placeholder="Tony" type="text">
            </li>

            <li>
                <label>Last Name</label>
                <input pattern="\w{2,10}" placeholder="Arslan" id="lastname" optional type="text">
            </li>
            <li>
                <label>Phone</label>
                <input type="tel" placeholder="(402) 456-7891" pattern="^\(?\d{3}\)?[-\s]\d{3}[-\s]\d{4}.*?$" />
            </li>
            <li>
                <label>Adress</label>
                <input placeholder="" id="adress" type="text">

            </li>

            <li>
                <label>Programing Language</label>
                <input optional list="PrograminLanguage" name="PrograminLanguage" />
            </li>
            <li>
                <datalist id="PrograminLanguage">
                    <option value="JavaScript">
                    <option value="Phthon">
                    <option value="Java">
                    <option value="C#">
                    <option value="C++">
                </datalist>
            </li>
        </ul>
        <input type="submit" value="Send Request">
        <!--<button type="submit">Send Request</button>-->
    </form>

Forms are often accompanied with a css and a JavaSript file. Below are the css and JavaScript companian files for the form above.

 css file:   <link rel="stylesheet" href="../css/css-form.css" />  
 js file :   <script src="../js/js-form.js"></script>  

Here is the working example

HTML <form> action Attribute

The action attribute specifies where to send the form-data when a form is submitted.

Example:

    <form action="{url}" method="get">
        <label for="username">Name:</label>
        <input type="text" id="username" name="username">
        <input type="submit" value="Submit">
    </form>
Value of the {url}:
- An absolute URL - points to full web resource (i.e: action="http://www.mysite.com/handlemyform.html")
- A relative URL - points to a file (resource) within a web site (i.e: action="/handlemyform.html")
The method attribute
The method attribute defines how data is sent. The HTTP protocol provides several ways to perform a request. HTML form data can be transmitted via a number of different methods, the most common being the GET method and the POST method.
The GET method

The GET method is the method used by the browser to ask the server to send back a given resource. Using this method the data sent to the server is appended to the URL. The body of the message is empty This method is great for retrieving data.

The POST method

The POST method is the method the browser uses to talk to the server when asking for a response that takes into account the data provided in the body of the HTTP request. Using this method the data is included in the request body instead of appended to the URL. The body of the message is not empty The HTTP request looks like the following


    POST / HTTP/2.0
    Host: foo.com
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 13

    say=Hi&to=Mom

The Content-Length header indicates the size of the body, and the Content-Type header indicates the type of resource sent to the server

JavaScript APIs

In general, Application Programming Interfaces (APIs) are constructs made available, by technology providers or software vendors, in programming languages to allow developers to build complex functionality more easily and without knowing the detail implementation. The implementation may be in another programin language than the consumer language. For example, an API may be developed in C++ and has some methods or properties exposed to JavaScript.

There are many APIs that are available to JavaScript. Most APIs are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language.

In JavaScript world, the APIs are classified into two categories:

  • Browser APIs: Functionality built into the browser that sit on top of the JavaScript language and allow developers to implement functionality more easily.
  • Third party APIs: Functionality built into third-party platforms (e.g. Twitter, Facebook) that allow developers to use some of those platform's functionality in their own web applications.

In addition, there are also libraries and frameworks developed to help rapid development. Libraries such as jQuery, Mootools and React hepled developers to quickly construct their application and not worry about the short coming of browsers.

In this section, we will focus on Browser APIs which is seperated into several categories.

  • APIs for manipulating documents : We have already seen and used document object which allows us to manipulate HTML and CSS — creating, removing and updating HTML and CSS on the page.
  • APIs that fetch data from the server : We will cover this API in Asynchronous JavaScript section.
  • Device APIs : These are the APIs for manipulating and retrieving data from device hardware.
  • Client-side storage APIs : We use Storage APIs for storing and retrieving data on the client-side .
  • Audio and Video APIs : These APIs allow developers to create custom UI controls for playing audio and video, display text tracks like captions and subtitles. Text-to-Speach and speach recognition are some of the most interesting applications
  • APIs for drawing and manipulating graphics : The two main APIs in this category are Canvas and WebGL. Both are widely supported by modern browsers. These APIs allow developers to programmatically update the pixel data to create 2D and 3D scenes. These APIs are often used for creating animation loops such as window.requestAnimationFrame(). A lot of HTML games are developed using these APIs. In the rest of this section, we will study canvas API

animation, canvas API, drawing

The <canvas> element was introduced by HTML5 to replce Flash. Flash is not supported by major browsers anymore, therefore all drawing, and animations should be done using HTML native technologies such as canvas, WebGL, Scalable Vector Graphics (SVG), CSS and JavaScript. It's important to know that the canvas has been designed for pixel-based graphics, while SVG (Scalable Vector Graphics) is for vector-based graphics. This course will focus on the fundamental drawing capabilities of the HTML5 canvas element.

Canvas is great fit for writing 2D graphics and games and it performs well.

To use canvas in HTML, we need to place the following element in HTML page, anywhere within the body tag.


    <canvas id="gamecanvas" width="400" height="300">
    Sorry canvas is not supported. Either your web browser
    does not support the canvas element or JavaScript is disabled. Do you have pop-up blockers?
    </canvas>

This example defines an area of 400 by 300 pixels on which content can be rendered with JavaScript. by default canvases are "transparent", users should see nothing as a result on an empty canvas. It's fair to treat canvas element similar to other HTML interm of appying CSS.

Providing alternative content incase user's browser do not support canvas is essential.

The canvas coordinate system

X axis is horizontal, directed to the right
Y axis is vertical, directed downwards
The coordinate system used for drawing in canvasis in the top left corner. The X axis is going to the right and the Y axis to the bottom.

The canvas coordinate system
The canvas coordinate system

The canvas coordinate system adjusted
The canvas grid system

Once canvas element is placed on our page, we are ready to access and use it via JavaScript API.


    var canvas = document.getElementById("gamecanvas");
    //OR
    var canvas = document.querySelector("#gamecanvas");

getElementById() or querySelector() method may be used to gain access to the canvas element.

In JavaScript, the next necessary step is to get a "2D context" associated with the canvas. This will enable us to be able to do drawing and/or setting drawing properties (color, etc.). This should be done only once.


    var context = canvas.getContext('2d');
In Summary

In order to use canvas, do the following

  1. Add the canvas element into an HTML page
  2. Select the canvas element for use from JavaScript
    
        var canvas = document.getElementById("gamecanvas");
    
  3. get a "2D context" associated with the canvas
    
        var context = canvas.getContext('2d');
    
Basic Example

canvas basics
There are three functions that draw rectangles on the canvas:

fillRect(x, y, width, height)
Draws a filled rectangle.

strokeRect(x, y, width, height)
Draws a rectangular outline.

clearRect(x, y, width, height)
Clears the specified rectangular area, making it fully transparent.


    function draw() {
    var canvas = document.getElementById("canvas");
    if (canvas.getContext) {
    var context = canvas.getContext("2d");

    context.fillRect(10, 10, 100, 100);
    context.clearRect(45, 45, 60, 60);
    context.strokeRect(50, 50, 50, 50);
    }
    }

Drawing paths

A path is a list of points similar to strings are list of characters.

Example: Drawing paths

Below are the steps to make shapes using paths

  1. Step: Create the path
  2. Step: Draw into the path use drawing commands. A complete list of drawig commands can be found at MDN
  3. Step: Stroke or fill the path to render

    Here are the functions used to perform these steps:

    beginPath()
    Creates a new path. Once created, future drawing commands are directed into the path and used to build the path up.
    Path methods
    Methods to set different paths for objects.
    closePath()
    Adds a straight line to the path, going to the start of the current sub-path.
    stroke()
    Draws the shape by stroking its outline.
    fill()
    Draws a solid shape by filling the path's content area.

Example


    function draw() {
    var canvas = document.getElementById("canvas");
    if (canvas.getContext) {
    var context = canvas.getContext("2d");

    context.beginPath();
    context.moveTo(75, 50);
    context.lineTo(100, 75);
    context.lineTo(100, 25);
    context.fill();
    }
    }

    moveTo(x, y)
    Moves the pen to the coordinates specified by x and y.

    lineTo(x, y)
    Draws a line from the current drawing position to the position specified by x and y.

Arcs

To draw arcs or circles, we use the arc() or arcTo() methods.


    arc(x, y, radius, startAngle, endAngle, anticlockwise)
    Draws an arc which is centered at (x, y) position with radius r starting at startAngle and ending at endAngle going in the given direction indicated by anticlockwise (defaulting to clockwise).

    arcTo(x1, y1, x2, y2, radius)
    Draws an arc with the given control points and radius, connected to the previous point by a straight line.

Introduction to Web Animation

Animation is a great way to make your web application cheerful and striking to a larger audiance. Developers have several distinct ways to implement animatios. Some animation may not need any programming at all, CSS transitions may be sufficient for most cases, while more complicated animations will require more complex user interaction. JavaScript is the best tool for such tasks. JavaScript makes applying CSS to DOM elements dynamicall, very easy. In this section, we will intoduce some of the most practiced methods.

Animation with JavaScript
JavaScript transform:translate

3D Animation
3D Animation Using Three.js

Drawing using canvas API
Drawing using canvas

Animation using canvas API
Animation using canvas

Basic Game Development in JavaScript

The

<canvar></canvar>
element is the most popular and a resolution-dependent tool that is used for rendering game graphics, graphs and/or other visual images on the fly. We will use canvas for drawing images, graphs and doing animations. There can be more than one canvas on a single page. Some may be stacked on top of one another to provide layers. Each canvas on the page, behaves like any other html element in DOM Previously we used canvas to draw in this example: Drawing using canvas API. We also used canvas to animate in this example: Animation using canvas API.
In this section we will use the same skill we have learned previously to develop components for developing a basic game.

The "game loop"

The game loop, separates the game logic and the visual layer from a user's input and actions, and is the main structure of any game. For example, in web form, if the user does not enter the "submit" button, nothing will happen. The form waits for an action from the user.

On the other hand, games behave differently. It must continue to operate some action regardles of the user action, hence loop. Some of the operations that may occur in our game are draw graphics, play sounds, calculate new positions fot each object, update core board etc. There are various methods and tools available to JavaScript for developing the game loop.

Tools for implementing the Game Loop

setInterval(...) function

We covered setInterval in this section. Below is reminder of the syntax and another example

Syntax

    setInterval(function, ms);

The setInterval function, evaluates a set of statements for a specified interval. It returns a unique id of the action which can be used the stop the execution.


    function display_greeting() {
    var div = document.createElement("div");
    div.textContent = "Hello there!";
    document.body.appendChild(div);
    };
    //this will add one line of greeting message every 1000ms (1s)
    intervalId = setInterval(display_greeting, 1000);

    //Implement logic to stop displaying greeting message
    function stop_display_greeting() {
    clearInterval(intervalId);
    }
    //invoke stop action
    stop_display_greeting();

The setInterval executes when the interval time is reached. It does not wait unltil all the code is executed. If the execution of the code take more time than the interval time, it will run into Unpredictable behavior.

Click Animation using the setInterval for complete implementation

setTimeout(...) function

setTimeout works similar to setInterval. The difference is that setTimeout it executes after a given amount of time. Unlike setInterval, setTimeout waits for the function to finish everything inside before calling it again. This is a great improvement over the setInterval

Syntax

    setTimeout(function, ms);

The setTimeout does not returns a unique id of the action. Developers will find another way to stop execution. Below, we demonstrate one solution.


    function display_greeting() {
    var div = document.createElement("div");
    div.textContent = "Hello there!";
    document.body.appendChild(div);
    };
    //this will add one line of greeting message every 1000ms (1s)
    isplaying = true;
    setTimeout(display_greeting, 1000);

    //Implement logic to stop displaying greeting message
    function stop_display_greeting() {
    //Will Stop
    isplaying = false;
    }
    //invoke stop action
    stop_display_greeting();

Click Animation using the setTimeout for complete implementation.

For many years, game loops were developed using setTimeout until requestAnimationFrame API became available.

requestAnimationFrame API

When we work with either setTimeout or setInterval, we set the execution time up front, the browser has no knowledge of what we are doing. The browser doesn't know if we want to repaint the DOM structure and when or do we even want to work with canvas. This created un-smooth animations. If browser engine did have some knowledge, it could optimize the loop. requestAnimationFrame will help us resolve this problem

According to developer.mozilla.org (MDN): The requestAnimationFrame tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.

Similar to setTimeout the callback routine must itself call requestAnimationFrame() to animate another frame at the next repaint.

Syntax

    requestAnimationFrame(callback);
    //or
    window.requestAnimationFrame(callback);

callback is the function to call when it's time to update your animation for the next repaint.

The requestAnimationFrame returns a unique id, known as request id which can be passed to cancelAnimationFrame() to cancel the refresh callback request. Developers will find another way to stop execution. Below, we demonstrate one solution.


    function display_greeting() {
    var div = document.createElement("div");
    div.textContent = "Hello there!";
    document.body.appendChild(div);

    requestAnimationFrame(display_greeting);
    };
    //this will asks the browser to call the display_greeting function every 16.6 ms: this corresponds to 60 times per second (16.6 ms = 1/60 s).
    requestAnimationFrame(display_greeting);

    //Implement logic to stop displaying greeting message
    function stop_display_greeting() {
    //Will Stop
    isplaying = false;
    }

    //invoke stop action
    stop_display_greeting();

Click Animation using the setTimeout for complete implementation.

JavaScript Design Patterns

The study of Design Patterns is beyond the scope of this class however it is imperative to recognize the importance of maintainable code which requires noticing recurring themes in the code and optimizing them. In this section, we will study one of the design pattern - The Revealing Module Pattern to demonstrate code reuseability, encapsulation and composition.

Click Animation using the setTimeout for complete implementation.

Game Module

When creating a game, we cannot do it all at once; we need to divide it into smaller tasks or components or modules. We should be able to test each task individually. We should not expose the detail implementation of our game however we should have public methods and properties through which each component will communicate. In other word, we will expose our game through a controlled set of methods and properties.

Lets's start with the skeleton of the game, this is sometimes called Framework. We will follow the Revealing Module Pattern. For details on JavaScript Patterns, read this resource .

Lets name our game CSCE120Game


    var CSCE120Game = function(){

    function mainLoop(time) {
    //Main function, called each frame
    requestAnimationFrame(mainLoop);
    };
    function start() {
    requestAnimationFrame(mainLoop);
    };

    // Our GameFramework returns a public API visible from outside its scope
    // Here we only expose the start method, under the "start" property name.
    return {
    start: start
    };
    };

Time-based animation

This technique is used nearly all game developments. All animations follow the steps below

  1. Erase the canvas
  2. Move the shapes
  3. Draw the shapes
  4. Go to step 1

The above concept is know as "animation loop" or "game loop". Step 2, and 3 may be swapped.

In this section, I will demonstrate an example that does NOT use time-based animation and an example that does use time-based animation

A example that does not use time-based animation

animation-non-time-based-canvas

The animation seem fairly smooth however we may not see the same smoothness insome smartphones with less resources. The images will move faster on the desktop computer screen than on smartphones. Because the frame rate differs between the computer and the smartphone. While it runs 60 frames per second (fps) on a laptop computer it may run 25 fps on the smartphones. As we only move the objects in the animationLoop, in one second the rectangle will be moved 25 times on the smartphone compared with 60 times on the computer. Since we move the rectangle the same number of pixels each time, the rectangle moves faster on the computer.

We, as developers, may can artificially slow down the animation to make it look similar motion in all devices. But this method will waste our recources. The best solution would be measuring time between frames to achieve a constant speed on screen, even when the frame rate changes.

There are a few methods in our arsenal for dealing with device differences.

Time based animation : Using the JavaScript Date object

Measure the time at the beginning of each animation loop, and store it. Compute the delta of times elapsed between two consecutive loops. Then apply some simple maths to compute the number of pixels we need to move the shape to achieve a given speed (in pixels/s).

animation-non-time-based-canvas

SVG: Scalable Vector Graphics

SVG is special version of Extensible Markup Language (XML) designed for describing vector graphics, often two dimensional. SVG images and animations are defined in XML files which means they can be searched, indexed, scripted and compressed. SVG works with other web standards such as CSS, DOM similar to HTML elements.

Example: svg linear motion

Simulating Collisions

Object collisions, collisions detections and behaviours after the collosion occurs are the bases of most physics similation games. In your game, you will check for overlap between objects, apply collision detection and calculate new directions and velocities. A more natural game will also consider object mass, gravity and other properties.

We will construct our game in several steps:

JavaScript Libraries and Frameworks

Library: Offers functions to be called by its parent code

Framework: defines the entire application design. Developer code does not call a framework; instead the framework calls and uses the code in some particular way

TypeScript : {Better} JavaScript

Accoring to wikipedia.org, TypeScript is an open-source programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript, and adds optional static typing to the language.

When TypeScript code is compiled, the compiler will transcompile the code to JavaScript. Basically the compiler will read the TypeScript code, parse it, analyze it, and translate it into JavaScript.

https://www.typescriptlang.org

React code is also transcompile into JavaScript.

Babel is a very popular transcompiler

References

Eloquent Javascript

Clean Code Javascript