JavaScript
Live Demo: https://www.youtube.com/watch?v=BrQKM_uaZKE
Github Repo: https://github.com/web-engineering-tuwien/recipe-search-live-demo
https://developer.mozilla.org/en-US/docs/Web/Tutorials#javascript-tutorials
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures
https://eloquentjavascript.net/
JavaScript
interpreted scripting language.
Standardized as ECMAScript language in the ECMA-262
Other ECMAScript implementations: JScript, ActionScript, QtScript, …
In this course: EXMAScript 6
Embedding into HTML
External
linking to an external JavaScript file in <head>
defer
= asynchronous loading
It will defer (= delay) loading the JS until the page load is completed.
<script type="text/javascript" src="foo.js" defer> </script>Internal
In <body> or <head>
type="module"
is
defer
by default
<script type="module">
statement;
statement;
...
</script><script type="text/javascript">
statement;
statement;
...
</script>As event handlers
<a href="http://www.bar.com" onmouseover="alert('hi');">Pseudo-URLs in links
<a href="javascript:alert('You clicked');">Click me</a>Syntax
- Key words for declaration, Scoping- Function-scope: - var→ try to avoid- will only live in the function or the outer scope that it was called in
 - Function scopes can nest with nested functions
 - hoisting
: optimzing code before executing it within the virtual machine → During the hoisting process all
varvariables get declared in the beginning of every function without being initialized .Therefore accessing / reading an previously un-initialized variable with varwon´t cause an issue and is accessible everywhere within the function. → This makes code prone to error.
 - Block-scope: - let,- const- will only exist within its block (just like Java)
 - const identifiers cannot change → improves memory efficiency. Useful for objects and functions that shouldn´t change.
 - Global Scope: no keyword - Variables are global by default if no keyword is used
 
- Variables, Data types- There are 8 basic data types in JavaScript. - numberfor numbers of any kind: integer or floating-point
 - bigintis for integer numbers of arbitrary length.
 - stringfor strings. A string may have zero or more characters, there’s no separate single-character type.
 - booleanfor- true/- false.
 - nullfor unknown values – a standalone type that has a single value- null.
 - undefinedfor unassigned values – a standalone type that has a single value- undefined.
 - objectfor more complex data structures.
 - symbolfor unique identifiers.
 - The - typeofoperator allows us to see which type is stored in a variable.- 
Two forms:
typeof xortypeof(x).
 - 
Returns a string with the name of the type, like
"string".
 - 
For
nullreturns"object"– this is an error in the language, it’s not actually an object.
 - Type conversions: 
- Strings, Template Literals- Strings: (“…”, ‘…’) - Backslash escapes (\) String concatenation with + operator: "Dear " + s1.name + ", thank you for…”
 - JavaScript Template Literals (Replaces concatenation operations) - Use backquote (`) as delimiter
 - Can span multiple lines (new line included in the string)
 - 
Can have embedded expressions → ${expression} — computes expression and replaces it with string value
message = `Dear ${student.name}, Your GPA, ${gpa(student)}, is lower than the average: ${averageGPA}`
 
- Operators- Numerical operators: +,-,*,/,++,--,%
 - 
Comparison operators: >,>=,<,<=,==,!=,===,!==
Two kinds of comparison operators console.log("1" == 1); // true - compares content console.log("1" === 1); // false - compares type + content
 
- Functions, Callbacks- Declared with keyword - function:- 
Functions are first-class citizens, can be passed as parameters, can return other functions
- Callbacks (= higher order functions)- Here is a quick example: - function greeting(name) { alert('Hello ' + name); }function processUserInput(callback) { var name = prompt('Please enter your name.'); callback(name); }processUserInput(greeting);- The above example is a synchronous callback, as it is executed immediately. - Note, however, that callbacks are often used to continue code execution after an asynchronous (In other words, actions that we initiate now, but they finish later) operation has completed — these are called asynchronous callbacks. - For instance, one such function is the setTimeout function. 
 - Callback Hell / Pyramid of Doom- In a “callback-based” style of asynchronous programming. A function that does something asynchronously (at a later point in time) should provide a callback argument (usually an anonymous function) where we put the function to run after it’s complete. - As calls become more nested, the code becomes deeper and increasingly more difficult to manage. That’s sometimes called “callback hell” or “pyramid of doom”: - (Here the loadScript function executes the anonymous function that is its second parameter if script was loaded successfully → the goal is to load a series of scripts sequentially) - Callback Hell example- Take a look at the function - loadScript(src), that loads a script with the given- src:- function loadScript(src) { // creates <script src="…"> with given src // this causes the script with given src to start loading and run when complete let script = document.createElement('script'); script.src = src; document.head.append(script); }- We can use this function like this: - loadScript('/my/script.js');- The script is executed “asynchronously”, as it starts loading now, but runs later, when the function has already finished. If there’s any code below - loadScript(src), it doesn’t wait until the script loading finishes.- Let’s say we need to use the new script as soon as it loads. It declares new functions, and we want to run them. - Let’s add a - callbackfunction as a second argument to- loadScriptthat should execute when the script loads:- function loadScript(src, callback) { let script = document.createElement('script'); script.src = src;script.onload = () => callback(script);document.head.append(script); }- Now: How can we load two scripts sequentially: the first one, and then the second one after it (with error handling)? - Here’s an improved version of - loadScriptthat tracks loading errors:- function loadScript(src, callback) { let script = document.createElement('script'); script.src = src;script.onload = () => callback(null, script); script.onerror = () => callback(new Error(`Script load error for ${src}`));document.head.append(script); }- It calls - callback(null, script)for successful load and- callback(error)otherwise.- To use the loadScript function: - loadScript('/my/script.js', function(error, script) { //anonymous function that takes 2 params if (error) { // handle error } else { // script loaded successfully } });- From the first look, it’s a viable way of asynchronous coding. And indeed it is. For one or maybe two nested calls it looks fine. - But for multiple asynchronous actions that follow one after another we’ll have code like this: - loadScript('1.js', function(error, script) {if (error) { handleError(error); } else { // ... loadScript('2.js', function(error, script) { if (error) { handleError(error); } else { // ... loadScript('3.js', function(error, script) { if (error) { handleError(error); } else { // ...continue after all scripts are loaded (*)} });} }); } });- In the code above: - 
We load
1.js, then if there’s no error.
 - 
We load
2.js, then if there’s no error.
 - 
We load
3.js, then if there’s no error – do something else(*).
 - That’s sometimes called “callback hell” or “pyramid of doom.” - There are some solutions but none of them really solve the problem. - Luckily, there are other ways to avoid such pyramids. One of the best ways is to use “promises”. 
- 
We load
 
 
 - Function call only matched by name, not parameters → no overloading
 - Missing parameters replaced by undefined, Additionally passed parameters are ignored
 - 
Since ES6:
Optional parameters
by specifying
defaultfunction topGrade(student, threshold=1.5) { return gpa(student) <= threshold; }
 - Other function concepts: - Anonymous functions (= lambda expressions)- Named function: - function greet(name){ return "Hello"; }- Anonymous function: without a name, - var greet = function(name){ return "Hello";}
 - Arrow Functions- Their behavior are the same as of a function. They are anonymous functions with a special syntax. (syntactic sugar) - To define an arrow function, we use the - () => {}structure as follows:- const greet = (name) => { return "Hello " + name + "!"; } console.log(greet("Eric")); // prints out Hello Eric!- In this function, the - nameargument to the- greetfunction is used inside the function to construct a new string and return it using the- returnstatement.- In case that the function only receives one argument, we can omit the parenthesis: - const greet = name => { return "Hello " + name + "!"; } console.log(greet("Eric")); // prints out Hello Eric!- And, in case that we want to do a explicit return of the function and we have only one line of code, we can avoid the - returnstatement and omit brackets too:- const greet = name => "Hello " + name + "!"; console.log(greet("Eric")); // prints out Hello Eric!- Using an arrow as a callback compared to a normal function: - let numbers = [3, 5, 8, 9, 2];// Old way function multiplyByTwo(number){ return number * 2; } console.log(numbers.map(multiplyByTwo)); // prints out: 6, 10, 16, 18, 4// Using ES6 arrow functions const multiplyByTwo = number => number * 2; console.log(numbers.map(multiplyByTwo)); // prints out: 6, 10, 16, 18, 4
 - Also: - 
Arrow functions don’t have their own
thisorsuper, so they transparently fit into the surrounding context. - That makes them very useful in some cases.
 
- 
Functions are first-class citizens, can be passed as parameters, can return other functions
- Objects- var student = new Object(); student.nr = 'e11912007'; student.name = 'A Student'; student.age = 19; student.hasSTEOP = true; student = { nr : 'e120...', name : 'A Student', age : 19, hasSTEOP : true };- Objects have no underlying class → (Almost) everything is an object!! Objects are associative arrays. - key = property, value = value
 - Added when value assigned
 - Support dynamically adding/deleting values
 - JSON - JavaScript Object Notation- The JSON (JavaScript Object Notation) is a general format to represent values and objects. It is described as in RFC 4627 standard. Initially it was made for JavaScript, but many other languages have libraries to handle it as well. So it’s easy to use JSON for data exchange when the client uses JavaScript and the server is written on Ruby/PHP/Java/.... - JavaScript provides methods: - JSON.stringifyto convert objects into JSON.
 - JSON.parseto convert JSON back into an object.
 - Limitations: Cannot de/serialize JS functions → JSON can not transfer data that contains functions 
 
- Classes- operator "new" - The regular - {...}syntax allows to create one object. But often we need to create many similar objects, like multiple users or menu items and so on.- That can be done using constructor functions and the - "new"operator.- Constructor function - They are named with capital letter first.
 - 
They should be executed only with
"new"operator.function User(name) { this.name = name; this.isAdmin = false; }let user = new User("Jack");When a function is executed with new, it does the following steps:- 
A new empty object is created and assigned to
this.
 - 
The function body executes. Usually it modifies
this, adds new properties to it.
 - 
The value of
thisis returned.
 In other words, new User(...) does something like: function User(name) { // this = {}; (implicitly)this.name = name; this.isAdmin = false;// return this; (implicitly) }
- 
A new empty object is created and assigned to
 - The more advanced OOP syntax - The basic class syntax looks like this: - class MyClass { prop = value; // propertyconstructor(...) { // constructor // ... }method(...) {} // methodget something(...) {} // getter method set something(...) {} // setter method[Symbol.iterator]() {} // method with computed name (symbol here) // ... }- MyClassis technically a function ( the one that we provide as- constructor), while methods, getters and setters are not. They are written to the- .prototype.- The - constructor()method is called automatically by- new, so we can initialize the object there.
- Functions as Objects- Functions are objects too: they can have properties and methods - Difference to pure objects: They can be called and can return a value
 - 
Definition assigned as properties (use
newandthis)function Student(nr, name, age, hasSteop) { this.nr = nr; this.name = name; this.age = age; this.hasSteop = hasSteop; this.finishSteop = function() { this.hasSteop = true; } } var jc = new Student('e0828…',‘Jurgen Cito', 29, false); jc.finishSteop();ES6 Class is syntactic sugar for functions as objects: class Student { constructor(nr, name, age, hasSteop) { this.nr = nr; this.name = name; this.age = age; this.hasSteop = hasSteop; } finishSteop() { this.hasSteop = true; } } var jc = new Student('e0828…', ‘Jurgen Cito', 29, false); jc.finishSteop(); //Student { nr: 'e0828112', name: 'Jurgen Cito', age: 29, hasSteop: true } //typeof(jc) === 'object'
 
- Events- Pop-up Boxes- Confirm boxes will return "true" if ok is selected, and return "false" if cancel is selected. Alert boxes will not return anything. Prompt boxes will return whatever is in the text box. (Note: prompt boxes also have an optional second parameter, which is the text that will already be in the text box.) - confirm("Hi!"); prompt("Bye!"); alert("Hello");
 - Event callback attached to HTML elements. - <button onclick="alert('Test!')"> Test me! </button>- let button = document.getElementsByTagName(“button")[0] header.click(); //Execute predefined event header.onclick = function(){alert('Clicked!');} //Set event listener - only one listener supported let func = function() {alert('Clicked!');} header.addEventListener(“click", func) header.removeEventListener(“click", func)- Event types 
- Modules- https://www.samanthaming.com/tidbits/79-module-cheatsheet/ - Establish namespace in separate module files: Ability to create named export or default exports - Rule: One module per file, one file per module - Export specific elements: - export function gpa(student) {…} //EITHER THIS WAY function gpa (student) {…}; export gpa; //OR THIS WAY- Import in other files: - import * as Student from ‘./student.js'; s = {…}; s.gpa = Student.gpa(s); //<- now gpa is in the Student namespaceimport { gpa } from ‘./student.js’; s = {…}; s.gpa = gpa(s); //<- now gpa can be accessed directly
- Promises- Analogy: - Fans have subscribed the mailing subscription list of a singer so that they get instantly notified once the next album becomes becomes available or if something goes wrong. - Components: - A “producing code” that does something and takes time. For instance, some code that loads the data over a network. That’s a “singer”.
 - A “consuming code” that wants the result of the “producing code” once it’s ready. Many functions may need that result. These are the “fans”.
 - A promise is a special JavaScript object that links the “producing code” and the “consuming code” together. The “producing code” takes whatever time it needs to produce the promised result, and the “promise” makes that result available to all of the subscribed code when it’s ready. This is the “subscription list”.
 - The constructor syntax for a promise object is: - let promise = new Promise(/*executor(resolve, reject)*/);- let promise = new Promise(function(resolve, reject) { // executor (the producing code) });- The executor runs automatically and attempts to perform a job. When it is finished with the attempt it calls - resolveif it was successful- rejectif there was an error.- The - promiseobject returned by the- new Promisehas 2 internal properties:- state- 
initially
"pending"
 - "fulfilled"when- resolveis called by the executor
 - "rejected"when- rejectis called by the executor
 
- 
initially
 - result- 
initially
undefined
 - valuewhen- resolve(value)is called by the executor
 - errorwhen- reject(error)is called by the executor
 
- 
initially
  - Example: Successful - let promise = new Promise(function(resolve, reject) { setTimeout(() => resolve("done"), 1000); //"done" is the result });- After one second of “processing” the executor calls - resolve("done")to produce the result. This changes the state of the- promiseobject:- Example: Unsuccessful 
- Consumers: then, catch, finally- A Promise object serves as a link between the executor (the “producing code” or “singer”) and the consuming functions (the “fans”), which will receive the result or error. - Consuming functions can be registered (subscribed) using methods .then, .catch and .finally. - .then- promise.then( function(result) { ... }, //RESOLVE FUNCTION function(error) { ... } //REJECT FUNCTION );- Can also be called with only a single parameter (resolve function). - .catch- The call - .catch(f)is a complete analog of- .then(null, f), it’s just a shorthand.- .finally- The call - .finally(f)is similar to- .then(f, f)in the sense that f always runs when the promise is settled: be it resolve or reject.
- async/await- The async/await pattern: allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function. - awaitcan only be used from inside an- asyncfunction.- awaitexpressions make promise-returning functions behave as though they're synchronous by suspending execution until the returned promise is fulfilled or rejected.- It literally suspends the function execution until the promise settles , and then resumes it with the promise result as the return value. - Here's an example: - resolveAfter2Seconds()returns a promise but the- resultvariable only stores the result of the promise:- valuewhen- resolve(value)
 - errorwhen- reject(error)
 - function resolveAfter2Seconds() { return new Promise( resolve => { //executor function setTimeout(() => { resolve('resolved'); }, 2000); //resolve function }); }async function asyncCall() { console.log('calling'); const result = await resolveAfter2Seconds(); console.log(result); // expected output: "resolved" }asyncCall();- Asyncfunctions always return a promise.- If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. - For example, the following: - async function foo() { return 1 }- ...is similar to: - function foo() { return Promise.resolve(1) }
Inheritance
- Object Prototypes, Prototypal inheritance- In JavaScript, objects have a special hidden property - [[Prototype]], that is either null or references another object. That object is called “a prototype”.- The property - [[Prototype]]is internal and hidden, but there are many ways to set it.- One of them is to use the special name - __proto__, like this:- Now if we read a property from - rabbit, and it’s missing, JavaScript will automatically take it from- animal.- For instance: - let animal = { eats: true }; let rabbit = { jumps: true };rabbit.__proto__ = animal; // we can find both properties in rabbit now: alert( rabbit.eats ); // true alert( rabbit.jumps );- All objects have a prototype - All prototype are objects, any object can be a prototype
 - Objects inherit properties and methods from prototype
 - 
Object.prototype is top of the prototype chain (its prototype is null) (similar to Object.class in Java)
var aStudent = { nr : 'e120...', ... }; // aStudent -> Object.prototype var students = [ aStudent, ... ]; // students -> Array.prototype -> Object.prototpye var jc = new Student('e08…', ...); // aStudent -> Student.prototype -> Object.prototype function print() { ... }; // print -> Function.prototype -> Object.prototype
 - Existing prototypes can be extended at any time: its called "monkey-patching" and should be avoided! - String.prototype.distance = function() { ... }; // monkey patching
- Class inheritance- To extend a class: - class Child- extends- Parent:- That means - Child.prototype.__proto__will be- Parent.prototype, so methods are inherited.
Browser and Document APIs
Standard Library/Common APIs
Overview
Overview: There’s a root object called window.
APIs accessible through Javascript.
Browser Object Model BOM → interact with browser
Window,Frames,History,Location,Navigator
(browser type & version), ...
Storage (Local Storage, Cookies)
Document Object Model DOM → interact with HTML page
Properties:
document.forms,document.links
, …
Methods:
document.createElement,document.getElementsByTagName
, …
Browser Object Model BOM (window)
Allows access to browser objects. → Not standardized but very similar in most browsers.
Object Property and Methods
window Other global objects, open(), close(), moveTo(), resizeTo()
screen width, height, colorDepth, pixelDepth, …
location hostname, pathname, port, protocol, assign(), …
history back(), forward()
navigator userAgent, platform, systemLanguage, …
document body, forms, write(), close(), getElementById(), …
Popup Boxes alert(), confirm(), prompt()
Timing setInterval(func,time,p1,…), setTimeout(func,time)
Storage (Local Storage, Cookies)
Cookies
Cookies are sent with every single request.
String/value pairs, Semicolon separated.
document.cookie	=	"name=Jane Doe; nr=1234567;	expires=" + date.toGMTString()Web Storage
Data that the user is required to store (as key / value pairs)
Browser defines storage quota.
Both storage objects provide same methods and properties:
- setItem(key, value)– store key/value pair.
- getItem(key)– get the value by key.
- removeItem(key)– remove the key with its value.
- clear()– delete everything.
- key(index)– get the key on a given position.
- length– the number of stored items.
- Local Storage(window.localStorage)stored in users browser without any expiration date. In comparison to Cookies: more secure, larger, not transferred (stays local) 
- Session Storage(window.sessionStorage)Data is destroyed when tab/browser is closed. 
Document Object Model DOM
For HTML, XHTML, XML
HTML elements as objects with properties, methods and events - DOM tree nodes.
The
document
object is the trees root.

Everything in the html file becomes a node:
text nodes (spaces and \n are stored as seperate nodes), comment nodes ...
Getting nodes
ID, tag name, class name, Document properties
let	title	=	document.getElementById("title");
let	links	=	document.getElementsByTagName("a");
let	greens	=	document.getElementsByClassName("green");
let	imgs	=	document.images;
let	firstParaBox	=	document.querySelector(“p.box”);
let	allBoxes	=	document.querySelectorAll(“p.box,div.box”);Reading properties
<UL id="t1">
<LI>Item 1</LI>
</UL>document.getElementById('t1').nodeName
// -> returns 'UL'
document.getElementById('t1').getAttribute('id')
// -> returns 't1'
document.getElementById('t1').innerHTML
// -> returns '<li>Item 1</li>'
document.getElementById('t1').children[0].nodeName
// -> returns 'LI'
document.getElementById('t1').children[0].innerText
// -> returns 'Item 1'Manipulating nodes
- Content (innerHTML)
- Element attributes
- Element style
- 
Element class (
className,classList)
title.innerHTML	= "newTitle";
links[0].href	= "http://...";
links[0].setAttribute("href",…)
greens[0].style.color	= “red";
greens[0].className	=	“red"
greens[0].classList.add(“dangerzone”)Adding nodes
Create, append, remove, …
let	header	=	document.createElement("h2");
let	text	=	document.createTextNode("SubTitle");
header.appendChild(text);
document.removeChild(title);
document.replaceChild(title, header);Adding Event Handlers
let list = document.getElementById('t1');
list.addEventListener('click', (event) => {
alert(`Clicked: ${event.target.innerText}`);
});Traversal of nodes
parentElement, nextElementSibling, previousElementSibling, childNodes

Accessibility
DOM Updates
Changing / updating the DOM frequently
can confuse screen readers
not be visible in high magnification
Updates may come too fast
Guidelines - Accessible Rich Internet Applications (ARIA)
If the content updates more than 5 seconds, provide ability to pause, stop, or hide them
Inform users of changes: Setting focus, Highlight, Alert, Live Region (ARIA Term)
Communicate to user that page is dynamic
Provide static HTML page alternatives
Event-Driven Programming
- Flow of the program is determined by responding to user actions called events
- Writing programs driven by user events
<img src="..." alt="..." onclick="alert('Hello');" />let	button = document.getElementsByTagName("button")[0]
header.click();	//Execute	predefined event
header.onclick = function(){alert('Clicked!');}	//Set	event	listenerlet	func = function() {alert('Clicked!');}
header.addEventListener("click", func);
header.removeEventListener("click",	func);DOM Event Types
Event Description
load,unload User enters/leaves page
change Form input field changes
focus/blur User focuses/unfocuses an input field
Submit Form is submitted
mouseover, mouseout Mouse enters/leaves region
mousedown/mouseup/click Mouse click events
keydown/keyup/keypress Keyboard events
drag User drags an element
Asynchronous Programming
Asynchronous Programming ≠ Multithreading
Waiting for actions to finish is implicit in the synchronous model, while it is explicit, under our control, in the asynchronous one.

Sending Asynchronous Requests with Callbacks and Promises (like HTTP Fetch)







