# The Web Dev Guide by Wishtack

After 5 years of web applications development, trainings and coachings, we decided to produce this free guide in order to share our experience.

## ​Our Goals

* **Quickly** produce **performant**, **stable** and **maintainable** applications.
* Emphasize **pragmatism** and **best practices**.
* Share the result of our **technical watch**, **research** and **experience**.

## Copyright <a href="#copyright" id="copyright"></a>

This guide is the property of Wishtack.

It can't be used completely or partially for trainings animation or any other business purpose except by Wishtack employees.

If you have any doubt, get in touch with Wishtack at: <contact@wishtack.com>​


# HTML

HTML is a **standard** **cross-browser** tag-based language describing the **structure** and the **display** of a web page.

HTML was first standardized in **June 1993**.


# HTML Tags

Some HTML tags describe the **semantic structure and features** of a web page.

## Semantic tags

**Semantic structure** is mainly used for SEO *(**Search Engine Optimization**)* and **accessibility**.

```markup
<html>

    <head>
        <title>Wishtack Course</title>
    </head>

    <body>

        <h1>Wishtack</h1>

        <p>Wishtack is cool...</p>

    </body>

</html>
```

<https://www.w3schools.com/html/html5_semantic_elements.asp>

{% embed url="<https://www.w3schools.com/html/html5_semantic_elements.asp>" %}

## Component tags

Other tags are used to add **components** to the web page.

```markup
<!-- Link. -->
<a href="https://www.wishtack.com">Wishtack</a>

<!-- Image. -->
<img src="https://www.wishtack.com/logo.svg">

<!-- Form. -->
<form
        action="/submit"
        method="POST">

    <input
            name="userName"
            placeholder="Enter your name here"
            type="text">
    
    <button type="submit">Submit</button>
    
</form>
```


# HTML Attributes

As you can notice with `a` and `img` tags, some tags **can&#x20;*****(or must)*****&#x20;be customized** using HTML attributes.

**Attributes are for HTML tags what parameters are for functions**.

{% hint style="success" %}
Some tags might need multiple attributes especially when combined with frameworks like Angular.

To avoid duplicates and to improve readability, attributes should be used in **alphabetical order** and on a **new line for each attribute**.
{% endhint %}


# Content Formatting

Some tags and attributes can be used for content formatting :

```markup
<!-- Carriage return. -->
<br>

<!-- Bold. -->
<b>Bold text.</b>

<!-- Italic. -->
<i>Italic text.</i>

<!-- Element's height & width. -->
<div height="600px" width="800px"></div>
```

{% hint style="warning" %}
For an improved Software Design and in order to Separate Concerns, this usage should be avoided in favor of **dedicated CSS files**.
{% endhint %}


# Empty Tags vs Content Tags

Some tags like `div`, `span` and `p` need content.

{% hint style="warning" %}
Do not mix text with tags inside a content tag.

Otherwise, formatting and dynamic content modification can get complicated.

```markup
<!-- Dirty! -->
<div>
    Hello
    <span>Mr Foo</span>
</div>


<!-- Clean. -->
<div>
    <span>Hello</span>
    <span>Mr Foo</span>
</div>
```

{% endhint %}

With HTML5, empty tags don't need to be closed.

The following examples are equivalent:

```markup
<!-- Auto-closing tag. -->
<input type="text"/>

<!-- Implicit auto-closing tag. -->
<input type="text">
```

Closing empty tags might seem cleaner but it is better to leave them open.

{% hint style="warning" %}
Auto-closing tags might be ignored by some browsers and can cause trouble.
{% endhint %}


# Some Links

## HTML Tags Reference

<http://www.w3schools.com/tags/>

{% embed url="<http://www.w3schools.com/tags/>" %}

## Emmet

<https://emmet.io/>

{% embed url="<https://emmet.io/>" %}


# ECMAScript


# Some History

* **1995 :** Netscape creates a dynamic programming language named **JavaScript** that runs in the browser.
* **1995 :** Netscape enables backend JavaScript development with Netscape Enterprise Server.
* **1997 :** New **cross-browser** & **cross-platform** standard named **ECMAScript** and based on **JavaScript**.
* **1998 :** ECMAScript 2.
* **1999 :** ECMAScript 3.
* **2009 :** ECMAScript 5 *(a.k.a. ECMAScript 3.1)*.
* **2009 :** NodeJS.
* **June 2011 :** ECMAScript 5.1.
* **June 2015 :** ECMAScript 6 or ES2015.
* **June 2016 :** ECMAScript 7 or ES2016.
* **June 2017 :** ECMAScript 8 or ES2017.
* **June 2018 :** ECMAScript 9 or ES2018.


# Language Properties

## Typing <a href="#typage" id="typage"></a>

JavaScript is a **dynamically** and **weakly typed** language.

![](https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/assets%2F-L9vDDYxu6nH7FVBtFFS%2F-LAEA_TyQ1467afRM9Zd%2F-LAEEgb92HmErwla8pn_%2Flanguage-properties.jpg?alt=media\&token=9064bb53-0acf-45d4-a82d-9c4a0591e2d6)

## JavaScript is a multi-paradigm language <a href="#javascript-est-un-langage-multi-paradigme" id="javascript-est-un-langage-multi-paradigme"></a>

* Functional programming.
* Object-Oriented Programming.
* Reactive Programming.

## JavaScript is cross-browser and cross-platform <a href="#javascript-est-cross-browser-et-cross-platform" id="javascript-est-cross-browser-et-cross-platform"></a>


# Single-Threaded thus Asynchronous

## Multi-thread vs mono-thread

In a synchronous, multi-threaded and data-driven world, this works:

```javascript
function processRequest(request) {
​
    /*
     * Pre-processing.
     */
    var query = prepareQuery(...);
​
    var result = execQuery(query); // might take few seconds...
​
    /*
     * Post-processing.
     */
    var response = createResponse(result);
​
    return response;
​
}
```

... but in a single-threaded world, this can lead to trouble as the application would freeze until it receives a response.

**Until the function ends&#x20;*****(and its callees)*****, no other function can be executed simultaneously.**

## Asynchronous processing using callbacks

```typescript
function processRequest(request, callback) {
​
    /*
     * Pre-processing.
     */
    var query = prepareQuery(...);
​
    execQuery(query, function (result) {
​
        /*
         * Post-processing.
         */
        var response = createResponse(result);
​
        callback(response);
​
    });
​
}
```

## Asynchronous processing advantages

* No threads count limitation.
* No memory overhead due to threads.
* No locks or semaphores.
* No greedy locks.
* No deadlocks.
* Data doesn't change during the execution of a function.

## Closures

A **closure** is the combination of a function definition and the lexical environment in which the latter is defined.

Closures determine the scope of the variables.

Variables can be read and modified in the closure where they are declared **but also in the functions defined inside**.

```javascript
function main() {
​
    var userName = 'Foo';
​
    function setUserName(value) {
        userName = value;
    }
​
    function getUserName() {
        return userName;
    }
​
    setUserName('John');
​
    console.log(getUserName()); // 'John';
​
}
​
main();
```


# The Event Loop

## The Event Loop Behavior

What's the execution order of this code?

{% tabs %}
{% tab title=" 🧐" %}

```javascript
var value;
​
setTimeout(function () {
    value = 'VALUE';
}, 100 /* 100 ms. */);
​
console.log(value); // ???
​
setTimeout(function () {
    console.log(value); // ???
}, 200);
```

{% endtab %}

{% tab title="👍" %}

```javascript
var value;
​
setTimeout(function () {
    value = 'VALUE';
}, 100 /* 100 ms. */);
​
console.log(value); // 1 - undefined
​
setTimeout(function () {
    console.log(value); // 2 - VALUE
}, 200);
```

{% endtab %}
{% endtabs %}

And in this case?

{% tabs %}
{% tab title=" 🧐" %}

```javascript
function main() {
​
    var value;
​
    setTimeout(function () {
        value = 'VALUE';
    }, 0 /* 0 ms. */);
​
    console.log(value); // ???
​
    setTimeout(function () {
        console.log(value); // ???
    }, 0);
    
    console.log(value); // ???
​
}
​
main();
```

{% endtab %}

{% tab title="👍" %}

```javascript
function main() {
​
    var value;
​
    setTimeout(function () {
        value = 'VALUE';
    }, 0 /* 0 ms. */);
​
    console.log(value); // 1 - undefined
​
    setTimeout(function () {
        console.log(value); // 3 - VALUE
    }, 0);
    
    console.log(value); // 2 - undefined
    
}
​
main();
```

{% endtab %}
{% endtabs %}

## How the event loop works

1. **Register a listener** : Most asynchronous tasks requires the definition of a callback function in order to retrieve the result of the processing or simply in order to know that the processing ended.\
   During this step, we explicitly or implicitly subscribe a listener to some event source. Examples: `setTimeout`, `addEventListener` etc...
2. **Add the function to the queue**: The callback function cannot be called immediately when the result is received as the thread might be busy executing another function. In the example below, both callback functions are ready to be called the thread is busy executing our `main` function. The JavaScript engine adds references to the callback functions at the end of the callback queue in order to be called once the thread is free.
3. **Tick** : When the `main` function execution ends, the thread won't have time to stay idle and will immediately grab the callback at the top of the queue and execute it. More precisely, this is the event loop which simply loops forever executing every function in the queue. **The moment where the event loop ends the execution of a function and is ready to grab the next one is called a "tick"**.

![The event loop](https://3339142615-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LLu79csN7rNhazzx-Mu%2F-LLu_obX68mXP0B-8DkV%2F-LLucsiL6mHXS-m-4Bx0%2Fevent-loop.jpg?alt=media\&token=d3752594-f6a8-4fc4-9233-fa02bc2da830)

{% embed url="<https://www.youtube.com/watch?v=8aGhZQkoFbQ>" %}
What the heck is the event loop anyway?
{% endembed %}


# Classes

## ES6 Classes

{% tabs %}
{% tab title="ES6 Class" %}

```javascript
class Customer {

    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    getName() {
        return this.firstName;
    }

}
```

{% endtab %}

{% tab title="Legacy Prototype" %}

```javascript
var Customer = function(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Customer.prototype = {
    getName: function () {
        return this.firstName;
    }
}
```

{% endtab %}
{% endtabs %}

## Visibility

Meanwhile [class fields](https://github.com/tc39/proposal-class-fields) get supported, visibility rules are just based on a common naming convention where properties and methods get prefixed with the underscore character `_` if they are private.

```javascript
class Customer {

    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = null;
        this._isBadPayer = this._tellIfBadPayer();
    }
    
    getName() {
        return this.firstName;
    }
    
    _tellIfBadPayer() {
        return this.firstName === 'foo';
    }

}
```

## Properties

```javascript
class Customer {

    constructor(firstName, lastName) {
        this.firstName = firstName;
    }

    get firstName() {
        return this._firstName;
    }
    
    set firstName(value) {
        this._firstName = value;
    }
    
}

/* @HACK: Last time we use var, I promise! */
var customer = new Customer();

customer.firstName = 'Foo';

console.log(customer.firstName); // Foo
```

{% hint style="danger" %}
Avoid using properties.

Properties can become handy in some extreme cases like the integration of some legacy library, mock, implementing a runtime type checking decorator or something fancy like that etc...

Otherwise, properties will only introduce ambiguity.

Who would imagine that this code might trigger a runtime exception?

```javascript
var customer = new Customer();
element.textContent = customer.name;
```

Or even worse, things might end up like this:

```javascript
/* @HACK: Do not remove this useless line as it initializes
 * the user eagerly instead of running it lazily. */
request.user;
```

{% endhint %}

## Inheritance

This is inheritance:

```javascript
export class WishtackProduct extends Product {

    ...

    getProductId() {
        return 'wishtack-' + this._wishtackId;
    }

}
```

{% hint style="warning" %}
Now, avoid it...

... and prefer composition!
{% endhint %}

## Best practices

{% hint style="success" %}
Meanwhile we get the class fields in JavaScript, it is recommended to initialize all the attributes in the constructor. Otherwise, it's hard to figure out which attributes are available on a class. In addition to this, the available attributes will depend on the methods that have been called.
{% endhint %}


# Hoisting is Dead: var vs. let vs. const

## Reminder

### Global variables 🤮

```javascript
userName = 'Foo BAR';

console.log(userName); // Foo BAR
```

### Use strict 😅

```javascript
'use strict';

userName = 'Foo BAR'; // ReferenceError: userName is not defined
```

```javascript
'use strict';

console.log(userName); // ReferenceError: userName is not defined
```

## Hoisting

### Variable hoisting

{% tabs %}
{% tab title="🧐" %}

```javascript
'use strict';

console.log(userName); // ???

var userName = 'Foo BAR';
```

{% endtab %}

{% tab title="😱" %}

```javascript
'use strict';

console.log(userName); // undefined

var userName = 'Foo BAR';
```

{% endtab %}
{% endtabs %}

### Function hoisting

{% tabs %}
{% tab title="🧐" %}

```javascript
'use strict';

greetings(); // ???

function greetings() {
    console.log('HI!');
}

function greetings() {
    console.log('HELLO!');
}
```

{% endtab %}

{% tab title="😱" %}

```javascript
'use strict';

greetings(); // HELLO!

function greetings() {
    console.log('HI!');
}

function greetings() {
    console.log('HELLO!');
}
```

{% endtab %}
{% endtabs %}

### A little bit better

```javascript
'use strict';

greetings(); // TypeError: greetings is not a function.

var greetings = function () {
    console.log('HI!');
};

greetings(); // HI!

var greetings = function () {
    console.log('HELLO!');
};

greetings(); // HELLO!
```

## let

Variables are only accessible after their declaration.

```javascript
console.log(userName); // ReferenceError: userName is not defined

let userName = 'Foo BAR';
```

Variables are only accessible in the bloc where they are declared.

```javascript
if (true) {
    let userName = 'Foo BAR';
}

console.log(userName); // ReferenceError: userName is not defined
```

## const

`const` variables cannot be reinitialized.

```javascript
const user = {
    firstName: 'Foo',
    lastName: 'BAR'
}

user = null; // TypeError: Assignment to constant variable.
```

{% hint style="warning" %}
`const` does not mean immutable.

```javascript
user.firstName = 'John'; // OK!
```

{% endhint %}

{% hint style="success" %}
It is recommended to declare all variables as `const` except if reusing the variable is inevitable.

This is less error-prone and avoids some common inattention mistakes.

`const` usage avoids clumsy variable reuse:

```javascript
const user = {
    firstName: 'Foo',
    lastName: 'BAR'
}

/* 🤢*/
user = user.firstName; // TypeError: Assignment to constant variable.
```

{% endhint %}


# this & "binding"

## Who am I?

{% tabs %}
{% tab title=" 🧐" %}

```javascript
class Customer {
​
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    sayHi() {
        console.log('Hi ' + this.firstName);
    }
    
    sayHiLater() {
        setTimeout(function () {
            this.sayHi();
        }, 1000);
    }
​
}
​
const customer = new Customer('Foo', 'BAR');
​
customer.sayHiLater(); // ???
```

{% endtab %}

{% tab title=" 😱" %}

```javascript
class Customer {
​
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    sayHi() {
        console.log('Hi ' + this.firstName);
    }
    
    sayHiLater() {
        setTimeout(function () {
            this.sayHi();
        }, 1000);
    }
​
}
​
const customer = new Customer('Foo', 'BAR');
​
customer.sayHiLater(); // TypeError: this.sayHi is not a function
```

{% endtab %}
{% endtabs %}

## Binding

The callback function given to `setTimeout` is not bound to our `Customer` instance. In addition to this, `setTimeout` tries to help us by binding the timeout objet *(which is as well returned by setTimeout)* to our callback function.

```javascript
const const timeout = setTimeout(function () {
    console.log(this === timeout); // true
});
```

In order to fix this issue, we should bind our instance of `Customer` to callback function.

### The hacky way <a href="#the-hacky-way" id="the-hacky-way"></a>

```javascript
class Customer {
​
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    sayHi() {
        console.log('Hi ' + this.firstName);
    }
    
    sayHiLater() {
        setTimeout(function () {
            this.sayHi();
        }.bind(this), 1000);
    }
​
}
```

### The other hacky way <a href="#the-other-hacky-way" id="the-other-hacky-way"></a>

```javascript
class Customer {
​
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    sayHi() {
        console.log('Hi ' + this.firstName);
    }
    
    sayHiLater() {
        const _this = this;
        setTimeout(function () {
            _this.sayHi();
        }, 1000);
    }
​
}
```

### The clean way

See you at the [next chapter](/ecmascript/arrow-functions).


# Arrow Functions

```javascript
/* 90s */
function sayHi(userName) {
    console.log('Hi ' + userName);
}
​
/* 2000s */
var sayHi = function (userName) {
    console.log('Hi ' + userName);
};
​
/* 2015 */
const sayHi = (userName) => {
    console.log('Hi ' + userName);
});
```

## No binding

&#x20;Arrow functions cannot be bound to objects. The `this` variable's value will always be the one of the parent closure.

```javascript
class Customer {
​
    constructor(firstName, lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    sayHi() {
        console.log('Hi ' + this.firstName);
    }
    
    sayHiLater() {
        setTimeout(() => {
            this.sayHi();
        }, 1000);
    }
​
}
```

## Example with `Array.filter` and `Array.map`

```javascript
const productList = [
    {
        title: 'Browserstack',
        price: 50
    },
    {
        title: 'Keyboard',
        price: 20
    },
    {
        title: 'Prerender',
        price: 10
    }
];
​
const cheapProductList = productList.filter((product) => {
    return product.price < 25;
});
​
const cheapProductTitleList = cheapProductList.map((product) => {
    return product.title;
});
​
console.log(cheapProductTitleList); // ['Keyboard', 'Prerender']
```

## One-liner

In most cases, callbacks are just simple one-liners.

In this case, curly braces `{}` and the `return` statement can be removed.

If the arrow function only takes one parameter, the parentheses `()` can be removed.

```javascript
const cheapProductTitleList = productList
    .filter(product => product.price < 25)
    .map(product => product.title);
```

{% hint style="warning" %}
In case of variable name shadowing, try to avoid single letter variable names or generic names.

`filter(u => u.id === user.id)`

`filter(it => it.id === user.id)`
{% endhint %}

{% hint style="success" %}
Prefer the `_` prefix to mark the difference between the local variable and the one from the parent closure.

`filter(_user => _user.id === user.id)`
{% endhint %}


# Template Strings

```javascript
const appName = 'Wishtack';
const userName = 'Foo';
const greetings = `Hi ${userName},
Welcome to ${appName}!`
​
console.log(greetings);
​
// Result:
// Hi Foo,
// Welcome to Wishtack!
```

{% hint style="danger" %}
**Security** **Warning**

Template strings is not an HTML templating tool.\
Using template strings to produce HTML might expose you to XSS *(Cross-Site Scripting)* vulnerabilities.

Vulnerable example:

```javascript
/* userName is dynamically retrieved from malicious source:
 * query string, api, storage etc... */
const userName = '<img src=404 onerror=alert(1)>'; 
document.body.innerHTML = `<span>Hi ${userName}</span>`
```

{% endhint %}


# Syntactic Sugar


# Spread

## Array Spread

```javascript
const itemList = [1, 2, 3];
const additionalItemList = [5, 6];
​
const newItemList = [...itemList, 4, ...additionalItemList];
​
console.log(newItemList); // [1, 2, 3, 4, 5, 6]
```

## Object Spread <a href="#object-spread" id="object-spread"></a>

Handy for merging objects or for respecting immutability.

```javascript
const user = {
    firstName: 'Foo',
    lastName: 'BAR',
    email: 'invalid@wishtack.com'
};
​
const newUser = {
    ...user,
    email: 'foo.bar@wishtack.com',
    phoneNumber: '+6 12 34 56 78'
};
​
console.log(newUser);
// {
//    firstName: 'Foo',
//    lastName: 'BAR',
//    email: 'foo.bar@wishtack.com',
//    phoneNumber: '+6 12 34 56 78'
//}
```


# Destructuring

## Array Destructuring

Useful for unit-tests.

```javascript
const userList = [
    {firstName: 'Foo'},
    {firstName: 'John'}
];

const [user1, user2, user3, user4 = null] = userList;

console.log(user1); // { firstName: 'Foo' }
console.log(user2); // { firstName: 'John' }
console.log(user3); // undefined
console.log(user4); // null
```

## Object Destructuring

```javascript
const user = {
    firstName: 'Foo',
    lastName: 'BAR',
    email: 'foo.bar@wishtack.com'
};

const {firstName, lastName, phoneNumber} = user;

console.log(firstName); // Foo
console.log(lastName); // BAR
console.log(phoneNumber); // undefined
```


# Rest

## Array Rest

Rest parameters are the equivalent for variadic parameters in some other languages.

The `add` function below can take any number of parameters which will end up in the `valueList` `Array`.

```javascript
const add = (...valueList) => {
    return valueList.reduce((total, value) => total + value, 0);
};

add(0, 1, 2, 3); // 6
```

{% hint style="warning" %}
It is better to avoid the usage of "rest" parameters.\
It reduces the extensibility of the function. It is better to use one parameter of type `Array` that contains all the values.

```typescript
const add = (valueList) => {
    return valueList.reduce((total, value) => total + value, 0);
};

add([1, 2, 3]); // 6
```

{% endhint %}

## Object Rest

The same syntax can be used with the [destructuring](/ecmascript/syntactic-sugar/destructuring#object-destructuring) of an object.

```javascript
const user = {
    firstName: 'Foo',
    lastName: 'BAR',
    email: 'foo.bar@wishtack.com',
    phoneNumber: '123'
};

const { firstName, lastName, ...remainingProperties } = user;

console.log(remainingProperties); // { email: 'foo.bar@wishtack.com', phoneNumber: '123' }

```


# Object Literal Property Value Shorthand

It is common to create JavaScript objects using some local variables with the same names as the object properties ending up with something redundant like this:&#x20;

```javascript
const firstName = 'Foo';
const lastName = 'BAR';
​
const user = {
    firstName: firstName,
    lastName: lastName,
    email: 'foo.bar@wishtack.com'
};
```

... but thanks to the Object Literal Property Value Shorthand, it can be written in a shorter manner:

```javascript
const firstName = 'Foo';
const lastName = 'BAR';
​
const user = {
    firstName,
    lastName,
    email: 'foo.bar@wishtack.com'
};
```

{% hint style="info" %}
You should define your style guide concerning this syntax.

If the JavaScript ecosystem is quite new for the team, it is better to avoid this syntax which can be misleading.
{% endhint %}

{% hint style="warning" %}
Beware of IDEs that can't refactor Object Literal Property Value Shortands.

At Wishtack, we didn't use them until the refactoring was possible with IntelliJ / WebStorm.

{% endhint %}

![Refactoring with IntellJ](https://3339142615-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LLu79csN7rNhazzx-Mu%2F-LLvFHG4ZV7TilW2mAv3%2F-LLvK1j384Ys5ahifddB%2Fintellij-shorthanded-properties.gif?alt=media\&token=e906f1b6-8a11-4105-bcb0-00bf16484ff0)

![Refactoring with VSCode](https://3339142615-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LLu79csN7rNhazzx-Mu%2F-LLvFHG4ZV7TilW2mAv3%2F-LLvK_r3pyoWbAYAg0WM%2Fvscode-shorthanded-properties.gif?alt=media\&token=aee7b484-8d88-4b48-9652-ce309bf1287c)


# Named Parameters

Ordered parameters can make the code harder to read and refactor.

```javascript
class Customer {
    constructor(firstName, lastName, email, phoneNumber) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.phoneNumber = phoneNumber;
    }
}
​
new Customer('Foo', null, null, '123');
```

Unluckily, named parameters do not exist in JavaScript but there is a native workaround thanks to destructuring.

## Named Parameters with one parameter

```javascript
class Customer {
    constructor(args) {
        this.firstName = args.firstName;
        this.lastName = args.lastName;
        this.email = args.email;
        this.phoneNumber = args.phoneNumber;
    }
}
​
new Customer({
    firstName: 'Foo',
    phoneNumber: '123'
});
```

But this is not very IDE-friendly and without reading the content of the constructor, there's no way to know what are the expected parameters.

## Destructuring

The destructuring can be used in the constructor's *(or any other function)* parameters description.

```javascript
class Customer {
    constructor({firstName, lastName, email, phoneNumber = null} = {}) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.phoneNumber = phoneNumber;
    }
}
```

Which is a shorthand for:

```javascript
class Customer {
    constructor(args = {}) {
    
        const {firstName, lastName, email, phoneNumber = null} = args;
    
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.phoneNumber = phoneNumber;
    }
}
```

## Recycling

For simple objects, this constructor can be used as is without having to implement factories for handling copy or deserialization.

```javascript
const customer = new Customer({firstName: 'Foo'});
​
const customerFromJson = new Customer(JSON.parse(data));
​
const customerCopy = new Customer(customer);
```

## &#x20;


# Compatibility

How can we use the latest ECMAScript features and still be compatible with most browsers?

<https://kangax.github.io/compat-table/es6/>

{% embed url="<https://kangax.github.io/compat-table/es6/>" %}

## Transpilation

ECMAScript 5.1 is for modern ECMAScript what assembly is for C++.

We need a transpiler:

* Babel: <https://babeljs.io/>​
* TypeScript: <https://www.typescriptlang.org/>​

But this will not be enough as transpilers will only convert syntactic features but not new browser APIs and methods.

## Polyfills

We need to compensate the lack of some objects, functions or methods `customElements`, `fetch`, `Array.filter` on some browsers.

In order to fill the gap, we will use polyfill libraries. These libraries detect missing features and compensate them with **JavaScript implementations**.

Example:

```javascript
if (Array.prototype.first == null) {
    Array.prototype.first = function () {
        return this[0];
    };
}
​
const valueList = [1, 2, 3];
​
console.log(valueList.first()); // 1
```

One of the most famous polyfill libraries is core-js <https://github.com/zloirock/core-js>.

Or you can use a polyfill service like <https://polyfill.io>.


# Tools


# Node.js

<https://nodejs.org/en/>

{% embed url="<https://nodejs.org/en/>" %}


# NPM

**NPM&#x20;*****(Node Package Manager)***  is the official Node.js package manager.

It is automatically installed with Node.js and is used to handle JavaScript *(browser & Node.js)* dependencies.

> For those who knew [bower](https://bower.io/), well, it's dead.

NPM allows:

* Dependencies management *(just like apt, gem, maven, nugget, pip, yum...).*
* JavaScript modules creation and publishing.
* Download and install of dependencies depending on a module's dependencies description.
* Sharing entry point scripts with developers and machines *(e.g.: Continuous Integration)* like `build`, `debug`, `deploy`, `test` etc...

We will use NPM once, to install [Yarn](/tools/yarn)...

... because it's better *(Cf.* [*Yarn*](/tools/yarn)*)*.


# Yarn

<https://yarnpkg.com/en/>

{% embed url="<https://yarnpkg.com/en/>" %}


# Webpack

<https://webpack.js.org/>

{% embed url="<https://webpack.js.org/>" %}

<https://webpack.js.org/guides/getting-started/#basic-setup>

{% embed url="<https://webpack.js.org/guides/getting-started/#basic-setup>" %}


# WebStorm

<https://www.jetbrains.com/toolbox/app/>

{% embed url="<https://www.jetbrains.com/toolbox/app/>" %}

{% hint style="warning" %}
Once the toolbox is up and running, click on the cog icon next to WebStorm to install the latest version *(EAP or RC).*
{% endhint %}


# StackBlitz

<https://stackblitz.com/>

{% embed url="<https://stackblitz.com/>" %}


# DOM


# What Is It?

When an HTML page is loaded, the browser **parses** it and **generates the Document Object Model (DOM)**.

The DOM is a **tree-structure of nodes** where **each node is an element** *(like a form, an image or a simple `div` container)*.

DOM can be manipulated with JavaScript using the **standard DOM API**.

When the HTML page is loaded, the browser executes the JavaScript indicated using the `script` tag.

```markup
<script>
    alert('test');
</script>

<script src="/assets/script.js"></script>
```


# Element Selection

## Old School

### Selecting an element by id

```javascript
document.getElementById('login');
```

This code will return the first element having the given id.

```markup
<input id="login">
```

### Select using CSS class

```javascript
document.getElementsByClassName('blog-post');
```

This code will return the first element having the `blog-post-content` CSS class.

```markup
<section class="blog-post-content"></section>
```

### Select by HTML tag

```javascript
document.getElementsByTagName('header')
```

This code will return the first element having the `header` HTML tag.

```markup
<header>This is the header.</header>
```

## Modern Way

### Select using query selector

```javascript
document.querySelector('header');
document.querySelectorAll('div.blog-post-content');
```

The first call will return the first element with the header HTML tag.

The second call will return an iterable object with all the items with a `div` HTML tag and the `blog-post-content` CSS class.

{% hint style="success" %}
This is the easier and most modern way of selecting elements.
{% endhint %}

{% hint style="info" %}
`querySelector` and `querySelectorAll` methods are also available on every element in order to search for child elements.

```javascript
const firstNameInput = form.querySelector('input[name="firstName"]');
```

{% endhint %}


# Element Modification

Once you retrieve the reference to an element in the DOM, you can modify any of the element's properties.

### Modify content

```javascript
element.textContent = 'Hello 🌏';
```

{% hint style="warning" %}
HTML content can be controlled using `element.innerHTML` attribute but this approach is dangerous as it can lead to **XSS&#x20;*****(Cross-Site Scripting)*****&#x20;vulnerabilities**.

In addition to the security issues, updating the `innerHTML` forces the browser to parse the HTML then update the DOM content. This can have bad performance results.
{% endhint %}

### Modify properties

```javascript
/* Toggle `disabled` state. */
button.disabled = !button.disabled;

link.src = `https://wishtack.io`;
```

### Modify the structure

#### Create a DOM element

```javascript
const child = document.createElement('div');
```

#### Append an element

```javascript
parent.appendChild(child);
```

#### Remove an element

```javascript
parent.removeChild(child);
```

### CSSOM *(CSS Object Model)*

```javascript
/* Update some CSS style. */
element.style.backgroundColor = 'red';

/* Added a CSS class to an element. */
element.classList.add('blog-post-content');

/* Toggle a CSS class. */
element.classList.toggle('important');
```


# Events

Modern browsers can trigger **hundreds of types of events** *(\~500)*.

<https://developer.mozilla.org/en-US/docs/Web/Events>

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/Events>" %}

These event types can be of any kind:

* User interaction : click, input change, keypress, drag & drop etc...
* Geolocation,
* Device motion,
* Network status,
* ...

## Registering Event Listeners

These events can be intercepted by adding an **event listener** to the corresponding event type.

An event listener is a JavaScript function that **will be called whenever the event is triggered**.

In most cases, the listener function will take as first argument, **the event object** with different properties and data depending on the event type and the event itself.

### Listening to a click

```javascript
const button = document.querySelector('button');

let clickCount = 0;

/* Increment the counter on every click. */
button.addEventListener('click', () => clickCount++);
```

### Listening to keyboard

```javascript
document.addEventListener('keydown', event => {
    if (event.ctrlKey === true
        && event.key === 'x'
        /* This will show a confirmation dialog and return true if user confirms. */
        && confirm('Do you really want to remove the selected blog post?')) {
        removeSelectedItem();
    }
});
```

### Watching geolocation

```javascript
navigator.geolocation.watchPosition(position => {
    console.log(`
    Accuracy: ${position.coords.accuracy},
    Latitude: ${position.coords.latitude},
    Longitude: ${position.coords.longitude}
    `);
});
```

{% hint style="info" %}
Some functions like `watchPosition` will prompt the user for his consent before allowing access to geolocation.
{% endhint %}

## Removing Event Listeners

In order to avoid **side effects**, **dead code** and **memory leaks** it is important to think about clearing your event registrations by removing the listeners.

This can be done differently depending on the event type.

#### `removeEventListener`

```javascript
const listener = () => clickCount++;

button.addEventListener('click', listener);

button.removeEventListener('click', listener);
```

#### `clear...`

```javascript
const watchId = navigator.geolocation.watchPosition(...);
navigator.geolocation.clearWatch(watchId);

const interval = setInterval(() => console.log(clickCount), 1000);
clearInterval(interval);
```

## Events bubbling & capturing

<http://javascript.info/bubbling-and-capturing>

{% embed url="<http://javascript.info/bubbling-and-capturing>" %}


# Forms

## HTML5 Forms Specification

Luckily, HTML5 has a quite interesting forms specification.

<https://www.w3.org/TR/html5/sec-forms.html#sec-forms>

{% embed url="<https://www.w3.org/TR/html5/sec-forms.html#sec-forms>" %}


# The \<form> tag

## `<form>` tag attributes

The first step when implementing an HTML form is to add a `form` tag.

```markup
<form>
...
</form>
```

The form tag has three main attributes:

* **action**: that describes the URL where the data should be sent when the form is submitted.
* **enctype**: that specifies the encoding to use for sending data *(`application/x-www-form-urlencoded`, `multipart/form-data` and `text/plain`)*.&#x20;
* **method**: that controls the HTTP method that will be used to send data to server.

## Example

```markup
<form
    method="post"
    enctype="application/x-www-form-urlencoded"
    action="https://mylibrary.io/books">
</form>
```

## Intercepting `submit` event

In most cases in a JavaScript application, the content shouldn't be sent directly over the network to the backend but it **should be intercepted by the JavaScript** on submission.

When the user submits the form *(e.g.: presses enter or clicks on a `<button type="submit">` inside the form)*, the `form` element triggers a `submit` event.

The JavaScript can be intercepted by adding an event listener and the default behavior *(sending the form's data to the backend)* disabled calling the `preventDefault` method on the event.

```javascript
const form = document.querySelector('form');

form.addEventListener('submit', submitEvent => {
    submitEvent.preventDefault();
    ...
});
```


# Form elements

## `<fieldset>`, `<legend>` and `<label>`

```markup
<form>
    <fieldset>
      
        <legend>Book</legend>

        <div>
            <label for="title">Title</label>
            <input id="title" placeholder="title"     type="text">
        </div>

        <div>
            <label for="author-name">Author</label>
            <input id="author-name" placeholder="author"     type="text">
        </div>
      
    </fieldset>
</form>
```

<https://codepen.io/younes-jaaidi/pen/RYQMEM>

{% embed url="<https://codepen.io/younes-jaaidi/pen/RYQMEM>" %}

## `<datalist>`

```markup
<form>

    <datalist id="dataList">
        <option value="foo@bar.com" label="John Doe"></option>
        <option value="contact@wishtack.com" label="Wishtack"></option>
    </datalist>

    <input list="dataList" type="email">

</form>
```

<https://codepen.io/younes-jaaidi/pen/RYQMvM>

{% embed url="<https://codepen.io/younes-jaaidi/pen/RYQMvM>" %}


# Form validation

## Type

The `type` attribute of the `<input>` elements describes the behavior and validation constraints of the input.

<http://www.w3schools.com/html/html_form_input_types.asp>

{% embed url="<http://www.w3schools.com/html/html_form_input_types.asp>" %}

{% hint style="info" %}
On some devices, the virtual keyboard will be adapted to the type of the input.
{% endhint %}

## Validation

By default, a form **can not be submitted until all inputs are valid**.

It is possible to use additional attributes like `maxlength`, `minlength`, `pattern` or `required` to **apply some additional constraints**.

The `validity` property of the `<input>` element can be used in JavaScript to check input's validity and eventually, the invalidity reason.

```javascript
const input = document.querySelector('input');

input.validity.valid; // false
input.validity.valueMissing; // true
```

{% hint style="info" %}
It is possible to disable native validation using the form's `novalidate` attribute.

This can be used to validate the form manually or using a JavaScript library or framework.
{% endhint %}


# Networking

**Most data** you application will display to your users and let them interact with, **will come from remote network sources**.

Most of these sources will be [ReSTful APIs](https://blog.wishtack.com/rest-apis-best-practices-and-security/) or [GraphQL APIs](https://graphql.org).

<https://blog.wishtack.com/rest-apis-best-practices-and-security/>

{% embed url="<https://blog.wishtack.com/rest-apis-best-practices-and-security/>" %}

<https://graphql.org>

{% embed url="<https://graphql.org>" %}

<br>


# Fetch Web API

{% hint style="warning" %}
Luckily, thanks to the `fetch` Web API and without any external library, we will not need to use the old fashioned `XMLHttpRequest` object.

```javascript
const xmlHttpRequest = new XMLHttpRequest();

xmlHttpRequest.onreadystatechange = () => {
    if (xmlHttpRequest.readyState === 4 /* request is complete */
        && xmlHttpRequest.status === 200) {
        document.querySelector('.wt-wish-list').innerHTML = xmlHttpRequest.responseText;
    }
};

xmlHttpRequest.open('GET', '/users/123456/wishes/', true /* async */);

xmlHttpRequest.send();
```

{% endhint %}

## `fetch` usage

The `fetch()` function returns a `Promise<Response>` *(a promise that resolves to a `Response` object)*.

The `Response.json()` method returns a `Promise` that resolves the object produced by parsing the JSON content of the body.

```javascript
fetch('https://www.googleapis.com/books/v1/volumes?q=extreme%20programming')
    .then(response => response.json())
    .then(data => console.log(data));
```

Or using `async/await`:

```javascript
const response = await fetch('https://www.googleapis.com/books/v1/volumes?q=extreme%20programming');
const data = await response.json();
console.log(data);
```

## `fetch` options

The **second argument** for the `fetch` function is an **options object** that allows you for instance to send `POST` requests or to control additional stuff in the request like HTTP headers.

```javascript
const book = {
    id: 'BOOK_ID',
    title: 'eXtreme Programming explained'
};

fetch('https://api.mylibrary.io/books', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json; charset=utf-8'
    },
    body: JSON.stringify(book)
});
```

{% hint style="warning" %}
In order to avoid security issues like URL forgery, it is recommended to encode the dynamic parts of the URL when constructing it using the `encodeURIComponent` function.

```javascript
const uri = `https://api.mylibrary.io/books/${encodeURIComponent(bookId)}`;
```

{% endhint %}


# CSS

## Cascading Style Sheets, Why?

**HTML** has been designed to describe a **document's content but not it's display**.

{% hint style="danger" %}
Formatting tags (`<b>`, `<br>`, `<i>`) should not be used.&#x20;
{% endhint %}

{% hint style="success" %}
CSS should be used instead.

**Separation of Concerns:** CSS allows separation of content and design.
{% endhint %}

## CSS is quite powerful

<https://codepen.io/davidkpiano/pen/kkpGWj>

{% embed url="<https://codepen.io/davidkpiano/pen/kkpGWj>" %}

## How it works

### 1. Writing CSS

CSS syntax is basically composed of **selectors**, **properties** and **values**.

```css
selector {

    /* Comment your CSS! */
    property: value;
    ...

}
```

* The **selector**: allows you to select which elements in the page are concerned by this styling.
* The **property**: is the the styling property you want to control.
* The **value**: is the value you want to set on the property.

#### Example

```css
p {
    color: red;
    text-align: center;
}
```

### 2. Loading CSS

Except if you are using a framework, CSS is generally loaded using the HTML `<link>` tag.

```markup
<head>
    <link href="/assets/style.css" rel="stylesheet" type="text/css">
</head>
```


# Selectors

## CSS selector examples

```css
/* Tag. */
p { ... }

/* Id. */
#wt-wish-list { ... }

/* Class. */
.wt-wish { ... }

/* Multiple criteria: Tag with a specific class. */
p.wt-bold { ... }

/* Factorization: Apply same style to multiple selectors. */
p, #wt-wish-list, .wt-wish { ... }

/* Child element: Apply style to every button which is contained in an element with a "wt-button-container" class. */
.wt-button-container button { ... }

/* Direct child element. */
.wt-button-container > button { ... }

/* Pseudo-classes. */
.wt-button-container:hover { ... }

.wt-button-container:first-child { ... }
```

{% hint style="success" %}
Prefer using class-based selectors.
{% endhint %}

{% hint style="info" %}
To avoid collisions and improve readability, add a **prefix** to your CSS classes.

*Especially if you are not using a framework and that your CSS is global (and not specific to some component).*&#x20;
{% endhint %}

## Pseudo-classes

Pseudo-classes allow you to **customize the CSS depending on the context or state of the element** *(e.g.: is it the first element of a list, is it a checked checkbox etc...)*.

<https://www.w3.org/wiki/CSS/Selectors#Pseudo-classes>

{% embed url="<https://www.w3.org/wiki/CSS/Selectors#Pseudo-classes>" %}


# Transforms

## 2D transforms

2D transforms modify position, rotation and size of elements using CSS.

### Example - Rotating an element on hover

```css
.wt-demo-transform {
    border-style: solid;
    border-width: 1px;
    height: 20px;
    width: 100px;
    margin: auto;
}

.wt-demo-transform:hover {
    transform: rotate(180deg) scale(2);
}
```

<https://codepen.io/younes-jaaidi/pen/mGXpPz>

{% embed url="<https://codepen.io/younes-jaaidi/pen/mGXpPz>" %}

## 3D transforms

### Example - Rotating an element around the Y axis on hover with a perspective effect

```css
.wt-demo-transform {
    border-style: solid;
    border-width: 1px;
    width: 100px;
    margin: auto;
    padding: 10px;
}

.wt-demo-transform:hover {
    transform: perspective(100px) rotateX(10deg) rotateY(45deg);
}
```

<https://codepen.io/younes-jaaidi/pen/XPZVgg>

{% embed url="<https://codepen.io/younes-jaaidi/pen/XPZVgg>" %}

### Detailed post concerning perspective

<https://css-tricks.com/almanac/properties/p/perspective/>

{% embed url="<https://css-tricks.com/almanac/properties/p/perspective/>" %}


# Transitions

Transforms are a bit rough. They need some smoothness. Let's animate them!

```css
.wt-demo-transform {
    border-style: solid;
    border-width: 1px;
    margin: auto;
    padding: 10px;
    width: 100px;

    transition: transform .5s;
}

.wt-demo-transform:hover {
    transform: perspective(100px) rotateY(405deg);
}
```

<https://codepen.io/younes-jaaidi/pen/qMxpxY>

{% embed url="<https://codepen.io/younes-jaaidi/pen/qMxpxY>" %}

The `transition` property takes 4 parameters:

1. The property we want to animate.
2. Transition duration.
3. Timing function *(ease, linear, ease-in, ease-out, ease-in-out, cubic-bezier)*.
4. Delay to apply before starting the transition.

### Multiple transitions

It is possible to apply transitions on multiple properties with different parameters.

```css
.wt-demo-transition {
    border-style: solid;
    border-width: 1px;
    margin: auto;
    padding: 10px;

    height: 18px;
    width: 73px;

    transition: height 1s ease-in, width 1s ease-out 1s;
}

.wt-demo-transition:hover {
    height: 118px;
    width: 173px;
}
```

<https://codepen.io/younes-jaaidi/pen/aaqEKq>

{% embed url="<https://codepen.io/younes-jaaidi/pen/aaqEKq>" %}

{% hint style="success" %}
For better user experience, use short transitions *(less than 500ms)*.
{% endhint %}


# Animations

CSS animations describe a **chain of transition steps**.

Each step is called a **keyframe**.

```css
@keyframes demo-animation {

    0% {
        background-color: #ffffff;
        color: #000000;
        width: 73px;
    }

    33% {
        background-color: rgb(63,81,181);
        color: #ffffff;
        width: 73px;
    }

    66% {
        background-color: rgb(63,81,181);
        color: #ffffff;
        width: 173px;
    }

    100% {
        background-color: #ffffff;
        color: #000000;
        width: 173px;
    }

}

.wt-demo-animation {
  
    border-style: solid;
    border-width: 1px;
    text-align: center;
    width: 73px;
    margin: auto;
    padding: 10px;
  
}

.wt-demo-animation:hover {

    animation-name: demo-animation;
    animation-direction: alternate;
    animation-duration: 2s;
    animation-iteration-count: infinite;
    animation-timing-function: linear;

}
```

<https://codepen.io/younes-jaaidi/pen/eLVybG>

{% embed url="<https://codepen.io/younes-jaaidi/pen/eLVybG>" %}

## Animate.css

The **animate.css** module implements lots of interesting animations.

<https://daneden.github.io/animate.css/>

{% embed url="<https://daneden.github.io/animate.css/>" %}

[<br>](<https://daneden.github.io/animate.css/&#xA;>)


# Web Animations API

<https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API>

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API>" %}

<https://codepen.io/rachelnabors/pen/PNYGZQ?editors=0010>

{% embed url="<https://codepen.io/rachelnabors/pen/PNYGZQ?editors=0010>" %}


# Sass

Syntactically Awesome Style Sheets

Natively, CSS is **verbose**, has **factorization limitations** and can be **hard to maintain**.

These issues are solved using **preprocessors like SASS**.

<http://sass-lang.com/>

{% embed url="<http://sass-lang.com/>" %}

Preprocessors allow writing CSS in a language with the following features:

* Variables.
* Nesting.
* Mixins.
* Inheritance.

Preprocessors generate standard CSS.

```css
$wt-transition-duration: 0.5s;
$wt-user-list-background-color: blue;

.wt-user-list {

    background-color: $wt-user-list-background-color;

    >li {
        @include transition(transform @wt-transition-duration);
    }
        
}
```

Preprocessors can generate vendor prefixed CSS using modules like Bourbon.

​<http://bourbon.io/>

{% embed url="<http://bourbon.io/>" %}


# Responsive Web Design

Responsive Web Design is an approach aiming to **adapt application display depending on the device** used to access it.

Responsive Web Design **should mainly use HTML and CSS**.

## Think mobile first!

{% hint style="success" %}
Design should be defined for mobile devices first then exceptions should be added to handle larger screens.
{% endhint %}


# Viewport

Viewport is the web page's **area visible to the user**.

The `viewport` meta can control the **size and the zoom level** of the view.

```markup
<meta name="viewport" content="...">
```

To **enable responsive features**, we set the `viewport`'s width to the width of the screen.\
Initial zoom level should be set to 1.

```markup
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```


# Media Queries

## Media width

Media queries allow **CSS modification depending on the screen's size**.

```markup
<button
        class="wt-hide-gt-sm"
        data-role="wt-menu-button">Menu</button>

<div class="wt-show-gt-sm">
    <button>Action 1</button>
    <button>Action 2</button>
    <button>Action 3</button>
    <button>Action 4</button>
</div>
```

```css
@media (max-width: 599px) {
    .wt-show-gt-sm {
        display: none;
    }
}

@media (min-width: 600px) {
    .wt-hide-gt-sm {
        display: none;
    }
}
```

<https://codepen.io/younes-jaaidi/pen/LJdQQv>

{% embed url="<https://codepen.io/younes-jaaidi/pen/LJdQQv>" %}

## Media orientation

It is also possible to modify CSS depending on the **device's orientation**.

```css
@media (orientation: landscape) {
    ...
}
```


# Grid Layout

CSS Grid Layout allows item positioning in a grid based on columns and rows without having to struggle with floats, positioning or bootstrap's css classes.

```markup
<div class="wt-grid-container">
    <div class="wt-item-green">GREEN</div>
    <div class="wt-item-orange">ORANGE</div>
    <div class="wt-item-red">RED</div>
    <div class="wt-item-blue">BLUE</div>
</div>
```

```css
.wt-grid-container {
    display: grid;
    grid-template-columns: 1fr 1fr 2fr;
    grid-template-rows: 1fr 1fr 1fr;
}

.wt-item-green {
    background-color: green;
    grid-area: 1 / 1 / 1 / 3;
}

.wt-item-blue {
    background-color: blue;
    grid-column: 3;
    grid-row: 1;
}

.wt-item-orange {
    background-color: orange;
    grid-column: 1 / 2;
    grid-row: 2 / 4;
}

.wt-item-red {
    background-color: red;
    grid-area: 2 / 2 / 4 / 4;
}
```

<https://codepen.io/younes-jaaidi/pen/RYMQqW>

{% embed url="<https://codepen.io/younes-jaaidi/pen/RYMQqW>" %}

## More Links

<https://learncssgrid.com/>

{% embed url="<https://learncssgrid.com/>" %}


# Flex Layout

Flexbox layout dynamically modifies its child elements sizes to fill out the available area.

```markup
<div class="wt-flexbox-container">
    <div>Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
</div>
```

```css
.wt-flexbox-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
}

.wt-flexbox-container>div {

    border-style: solid;
    border-width: 1px;
    padding: 10px;
    text-align: center;

    flex: 1;
    min-width: 200px;

}
```

<https://codepen.io/younes-jaaidi/pen/KxooqG>

{% embed url="<https://codepen.io/younes-jaaidi/pen/KxooqG>" %}

## More Links

<https://css-tricks.com/snippets/css/a-guide-to-flexbox/>

{% embed url="<https://css-tricks.com/snippets/css/a-guide-to-flexbox/>" %}


# Frameworks & Libraries

{% hint style="warning" %}
Do not waste your energy by defining custom CSS classes to handle Responsive Web Design!
{% endhint %}

Use existing frameworks like Twitter's Bootstrap:

<http://getbootstrap.com/>&#x20;

{% embed url="<http://getbootstrap.com/>" %}

... or even better, go Material!

<https://www.google.com/design/spec/material-design/introduction.html>&#x20;

{% embed url="<https://www.google.com/design/spec/material-design/introduction.html>" %}

<https://material.angular.io>

{% embed url="<https://material.angular.io>" %}

<https://github.com/angular/flex-layout>

{% embed url="<https://github.com/angular/flex-layout>" %}

<https://zingchart.github.io/zingtouch/>

{% embed url="<https://zingchart.github.io/zingtouch/>" %}


# Web APIs

<https://developer.mozilla.org/en-US/docs/Web/API>

{% embed url="<https://developer.mozilla.org/en-US/docs/Web/API>" %}


# Testing


# Unit Testing

{% hint style="warning" %}
Unit-testing is **not optional** if you care about quality and your personal health.
{% endhint %}

{% hint style="success" %}
Unit testing improves teams **efficiency**, applications **quality** and **human lifespan**.
{% endhint %}

**Without automated tests:**

* every change is a challenge,&#x20;
* updating dependencies is too risky,
* refactoring is inacceptable,
* deployment is chaos,
* ...

{% hint style="success" %}
Modularity is unit testing's best friend.
{% endhint %}

## JavaScript Unit-Test Frameworks

### Jasmine

<https://jasmine.github.io/>

{% embed url="<https://jasmine.github.io/>" %}

### Mocha

<https://mochajs.org/>

{% embed url="<https://mochajs.org/>" %}

### Jest

<https://jestjs.io/>

{% embed url="<https://jestjs.io/>" %}

## Jasmine

### Example

```javascript
describe('priceScrapper', () => {

    let priceScrapper;
    
    beforeEach(() => priceScrapper = new PriceScrapper());

    it('should scrap prices without currency', () => {

        expect(priceScrapper.scrap('10.01')).toEqual({
            coefficient: 1001,
            currency: null,
            exponent: -2
        });

    });

    it('should scrap prices with currency', () => {

        expect(priceScrapper.scrap('$10.01')).toEqual({
            coefficient: 1001,
            currency: 'USD',
            exponent: -2
        });

    });

});
```

### Spies

Jasmine spies are mocks.

```javascript
describe('SearchEngine', () => {

    it('should pass locale to third party api', () => {

        /* Spying on `thirdPartySearchApi.search` and faking result. */
        spyOn(thirdPartySearchApi, 'search').and.returnValue([
            {
                title: 'Wishtack - Making Your Wishes Come True',
                url: 'https://www.wishtack.com'
            }
        ]);

        /* Trigger search. */
        searchEngine.search({keywords: 'Wishtack'});

        /* Check spy's call count. */
        expect(thirdPartySearchApi.search.callCount).toBe(1);

        /* Check spy's call args. */
        expect(thirdPartySearchApi.search).toHaveBeenCalledWith({
            country: 'US',
            keywords: 'Wishtack',
            language: 'en'
        });

    });

});
```

### Fetch Mock

If you are using `fetch` for HTTP requests, you can use `fetch-mock` to mock these http requests.

<http://www.wheresrhys.co.uk/fetch-mock/quickstart>

{% embed url="<http://www.wheresrhys.co.uk/fetch-mock/quickstart>" %}


# End to End Testing

By definition, unit-tests **don't test interactions between modules** and some side-effects.

The whole application **must also be tested automatically**.

## Protractor

Protractor is an e2e *(end-to-end)* testing framework developed by the AngularJS team.

It can test AngularJS or Angular web applications but also **non-AngularJS web applications**.

Protractor uses the Selenium webdriver to communicate with browsers and control them.

Protractor tests are written in **JavaScript&#x20;*****(or TypeScript)*****&#x20;with Jasmine**.

```javascript
describe('angularjs homepage todo list', () => {

    it('should add a todo', () => {
    
        browser.get('https://angularjs.org');

        /* Add an element. */
        element(by.model('todoList.todoText')).sendKeys('write first protractor test');
        element(by.css('[value="add"]')).click();

        /* Check todo list content. */
        const todoList = element.all(by.repeater('todo in todoList.todos'));
        expect(todoList.count()).toEqual(1);
        expect(todoList.get(0).getText()).toEqual('write first protractor test');

    });

});
```

{% hint style="success" %}
**Page objects:**

Factorize each view's *(or page)* logic in a dedicated and **reusable class** *(separation of concerns)*.
{% endhint %}

```javascript
import { PageTodo } from './pages/page-todo';

describe('angularjs homepage todo list', () => {

    it('should add a todo', () => {

        const pageTodo = new PageTodo();
    
        browser.get(pageTodo.pageUrl());

        /* Add an element. */
        pageTodo.addTodo({title: 'write first protractor test'});

        /* Check todo list content. */
        const todoElementList = pageTodo.todoElementList();

        expect(todoElementList.count()).toEqual(1);
        expect(todoElementList.get(0).getText()).toEqual('write first protractor test');

    });

});
```

## Cross-Browser & Cross-Device Test Automation with Browserstack

Browserstack is a cloud service with a large set of remotely controllable devices and browsers.

With Browserstack, you can run your Protractor tests on mobile and desktop.

<https://www.browserstack.com>

{% embed url="<https://www.browserstack.com>" %}

Browserstack records logs, captures screenshots and records testing videos.

{% hint style="info" %}
Apps can also be tested manually on Browserstack.
{% endhint %}

{% hint style="info" %}
You can open a tunnel with Browserstack to test locally hosted applications.
{% endhint %}

## Cypress

Cypress is another JavaScript End to End Testing Framework.

{% hint style="warning" %}
It doesn't use Selenium so it's not cross-browser.
{% endhint %}

With Cypress, it is easier to have a Test-Driven Development approach as tests can be re-run automatically on every change without having to respawn a browser.

<https://www.cypress.io/>

{% embed url="<https://www.cypress.io/>" %}

## Takeaways

### Cross-Browser & Cross-Device E2E Testing Automation Blog Post

<https://blog.wishtack.com/2015/05/07/cross-browser-testing-test-automation-with-protractor-and-browserstack/>

{% embed url="<https://blog.wishtack.com/2015/05/07/cross-browser-testing-test-automation-with-protractor-and-browserstack/>" %}

### Boilerplate to run your first protractor tests

<https://github.com/wishtack/wt-protractor-boilerplate>

{% embed url="<https://github.com/wishtack/wt-protractor-boilerplate>" %}

### Useful modules

<https://github.com/wishtack/wt-protractor-runner>

{% embed url="<https://github.com/wishtack/wt-protractor-runner>" %}

<https://github.com/wishtack/wt-protractor-utils>

{% embed url="<https://github.com/wishtack/wt-protractor-utils>" %}


# Security


# Injection

Web applications are mainly exposed to **HTML and JavaScript code injection**.

There are multiple entry points:

* Some part of the URL,
* Parameters,
* Data coming from an "unsafe" API.

{% hint style="info" %}
Third-party *(user, partner etc...)* data should not be trusted and never executed or used as an HTML template.
{% endhint %}

{% hint style="danger" %}
Never use `eval().`
{% endhint %}

### Encode URI components

When constructing a URL, dynamic parts should be URI encoded.

```javascript
const url = `https://api.wishtack.com/users/${encodeURIComponent(userId)}`;
```


# DOM XSS

If a user can control the executed code or HTML, a malicious user can **send a crafted URL to a victim and control the executed code**.

### Vulnerable code examples

{% hint style="danger" %}

```javascript
eval(document.querySelector('input[name="expression"]').value);
```

{% endhint %}

{% hint style="danger" %}

```javascript
const firstName = document.querySelector('input[name="firstName"]').value;
document.querySelector('.wt-first-name').innerHTML = firstName;
```

{% endhint %}

#### ECMAScript Template String

ECMAScript template strings should not be used for HTML templating.

{% hint style="danger" %}

```javascript
element.innerHTML = `<div>Hi, ${firstName}</div>`;
```

{% endhint %}

Where `firstName` might be controlled by a malicious user.

{% hint style="danger" %}
Except the application's code, every external source should be considered harmful.
{% endhint %}

{% hint style="success" %}
User your frameworks escaping features.
{% endhint %}


# Insecure Direct Object Reference

API resources' identifiers should be unpredictable.

> For instance, MongoDB identifiers are not unpredictable and can be guessed.

{% hint style="warning" %}
An unpredictable identifier is not enough to secure the access to the resources.
{% endhint %}

{% hint style="success" %}
The API should verify access permissions for each resource.
{% endhint %}


# Cross-Site Request Forgery

The access to a URL should not trigger implicit actions.

An attacker could craft a URL and maliciously **trigger the request from the victim's browser using implicitly the victim's credentials.**

This can be done using an `<img src="...">` tag on a malicious web site.

### Example

A URL like this `/hotels/123456/book?startDate=...` should not trigger booking...

**...** except if the URL contains a complex and unpredictable token which is verified by the backend.


# Client vs API Validation

All the data exchanged with API should be validated by the API itself.

Malicious users can easily bypass client-side validation.


# API Unauthorized Access and Data Leak

The API should verify the permissions on the every resource and field.

```
POST /users/123456/
{ firstName: 'Foo', isAdmin: true }
```

The API should not leak confidential data. This often happens when using generic code.

```
GET /users/123456/
{ firstName: 'Foo', bankCard: { number: '...', ... } }
```


# More Links

## W3Schools

<https://www.w3schools.com/>

{% embed url="<https://www.w3schools.com/>" %}

## Mozilla Docs

<https://developer.mozilla.org/en-US/docs/Web>

{% embed url="<https://developer.mozilla.org/en-US/docs/Web>" %}

## CSS Tricks

<https://css-tricks.com/>

{% embed url="<https://css-tricks.com/>" %}

## Newsletters

<https://javascriptweekly.com/>

{% embed url="<https://javascriptweekly.com/>" %}

<https://nodeweekly.com/>

{% embed url="<https://nodeweekly.com/>" %}


