Building HTML5 and JS Applications

Bilal Çınarlı Frontend Architect Software Engineer @Adidas

@bcinarli github.com/bcinarli

bcinarli.com

HTML5 - JS Applications

• What is HTML5 and Applications? • JavaScript Design Patterns • You Might Not Need JavaScript • Rest APIs and its advantages • JavaScript Packages and Dependency Management Content • Gulp, WebPack task managers and module bundlers • Modern JavaScript Coding & ES6 • ReactJS

What is HTML5?

• Giving meaning to structure, semantics are front and center with HTML5.

• A richer set of tags, along with RDFa, microdata, and microformats, are enabling a more useful, data driven web for both programs and your users.

• CSS3 delivers a wide range of stylization and effects, enhancing the web app without sacrificing your semantic structure or performance.

• Additionally Web Open Font Format (WOFF) provides typographic flexibility and control far beyond anything the web has offered before.

• Audio and video are first class citizens in the HTML5 web, living in harmony with your apps and sites .

• Between SVG, Canvas, WebGL, and CSS3 3D features, you're sure to amaze your users with stunning visuals natively rendered in the browser.

• Web Apps can start faster and work even if there is no internet connection.

• The HTML5 App Cache, as well as the Local Storage, Indexed DB, and the File API specifications support storing Web Apps data in client .

• Beginning with the Geolocation API, Web Applications can present rich, device-aware features and experiences.

• Incredible device access innovations are being developed and implemented, from audio/video input access to microphones and cameras, to local data such as contacts & events, and even tilt orientation.

• More efficient connectivity means more real-time chats, faster games, and better communication.

• Web Sockets and Server-Sent Events are pushing data between client and server more efficiently than ever before.

• Make your Web Apps and dynamic web content faster with a variety of techniques and technologies such as Web Workers and XMLHttpRequest 2.

JavaScript Design Patterns

• a design pattern is a general repeatable solution to a commonly occurring problem in software design

• a design pattern isn't a finished design that can be transformed directly into code.

• a design pattern is a description or template for how to solve a problem that can be used in many different situations.

Module Design Pattern

var HTMLChanger

( function () {

var contents

'contents' ;

var changeHTML

function () {

var element

document. getElementById ( 'attribute-to-change' ); element.innerHTML

contents ; }

return { callChangeHTML: function () {

changeHTML() ; console. log ( contents ); } }; })(); HTMLChanger. callChangeHTML ();
// Outputs: 'contents'

console. log (HTMLChanger.contents);
// undefined

Revealing Module Design Pattern

var Exposer

( function () {

var privateVariable

10 ;

var privateMethod

function () { console. log ( 'Inside a private method!' ); privateVariable ++ ; }

var methodToExpose

function () { console. log ( 'This is a method I want to expose!' ); }

var otherMethodIWantToExpose

function () {

privateMethod (); }

return { first: methodToExpose , second: otherMethodIWantToExpose

}; })(); Exposer. first ();
// Output: This is a method I want to expose!

Exposer. second ();
// Output: Inside a private method!

Exposer. methodToExpose (); // undefined

Prototype Design Pattern

var TeslaModelS

function () {

this .numWheels

4 ;

this .manufacturer

'Tesla' ;

this .make

'Model S' ; } TeslaModelS.prototype.go

function () {

// Rotate wheels

} TeslaModelS.prototype.stop

function () {

// Apply brake pads

}

Observer Design Pattern

var Subject

function () {

this .observers

[];

return { subscribeObserver: function (observer) {

this .observers. push (observer); },

unsubscribeObserver: 

function (observer) {

var index

this .observers. indexOf (observer);

if (index

1 ) {

this .observers. splice (index, 1 ); } },

notifyObserver: 

function (observer) {

var index

this .observers. indexOf (observer);

if (index

1 ) {

this .observers[index]. notify (index); } },

notifyAllObservers: 

function () {

for ( var i

0 ; i < this .observers.length; i ++ ){

this .observers[i]. notify (i); }; } }; };

var Observer

function () {

return { notify: function (index) { console. log ( "Observer "

index +

" is notified!" ); } } } var subject

new

Subject (); var observer1

new

Observer (); var observer2

new

Observer (); var observer3

new

Observer (); var observer4

new

Observer (); subject. subscribeObserver (observer1); subject. subscribeObserver (observer2); subject. subscribeObserver (observer3); subject. subscribeObserver (observer4); subject. notifyObserver (observer2); // Observer 2 is notified!

subject. notifyAllObservers (); // Observer 1 is notified! // Observer 2 is notified! // Observer 3 is notified! // Observer 4 is notified!

Singleton Design Pattern

var printer = ( function () {

var printerInstance;

function create () {

function

print () {

// underlying printer mechanics

} 

function

turnOn () {

// warm up, check for paper

} 

return {

  print: 

print , turnOn: turnOn

}; 

}

return { getInstance: function () {

if (!printerInstance) { printerInstance = create (); }

return printerInstance; } };

function Singleton () {

if (!printerInstance) { printerInstance = initialize (); } }; })();

You Might Not Need jQuery

Selecting Elements

// with jQuery var $element = $ ( '.my-class' ); // without jQuery var $element = document. querySelectorAll ( '.my-class' ) ;

Finding Elements

// with jQuery $ ( '.my-class' ). find ( child-element ); // without jQuery var $element = document. querySelector ( '.my-class' ) ; $element. querySelectorAll ( child-element )

Add/Remove Classes

// with jQuery var $element

$ ( '.my-class' ); $element. addClass ( 'new-class' ); $element. removeClass ( 'old-class' ); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element.classList. add ( 'new-class' ); $element.classList. remove ( 'old-class' );

Get/Set Content

// with jQuery var $element

$ ( '.my-class' ); $element. html (); $ ( '<div>' ). append ($element. clone ()). html (); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element.innerHTML; $element.outerHTML;

// with jQuery var $element

$ ( '.my-class' ); $element. html ( string ); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element.innerHTML

string ;

Get/Set Text

// with jQuery var $element

$ ( '.my-class' ); $element. text (); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element.textContent;

// with jQuery var $element

$ ( '.my-class' ); $element. text ( string ); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element.textContent = string ;

Event Bindings

// with jQuery var $element

$ ( '.my-class' ); $element. on ( eventName , eventHandler ); $element. off ( eventName , eventHandler ); // without jQuery var $element

document. querySelector ( '.my-class' ) ; $element. addEventListener ( eventName , eventHandler ); $element. removeEventListener ( eventName , eventHandler );

Rest API with JSON

• Primary architectural approach for distributed systems. • REST stands for Representational State Transfer.

• It relies on a stateless , client-server , cacheable communications.

• In most cases it is used with the HTTP protocol .

• RESTful applications use HTTP requests to POST (create), PUT

(create and/or update), GET (e.g., make queries), and DELETE data.

Features

• each HTTP contains all the necessary information to run it

• the client can run the same response for identical requests in the future.

• Objects in REST are always manipulated from the URI.

• Uniform interface

The advantages of REST for development

• Separation between the client and the server

• Visibility, reliability and scalability

• The REST API is always independent of the type of platform or languages

{ " data ": [{ " type ": " articles ", " id ": " 1 ", " attributes ": { " title ": " JSON API paints my bikeshed! ", " body ": " The shortest article. Ever. ", " created ": " 2015-05-22T14:56:29.000Z ", " updated ": " 2015-05-22T14:56:28.000Z " }, " relationships ": { " author ": { " data ": {" id ": " 42 ", " type ": " people "} } } }], " included ": [ { " type ": " people ", " id ": " 42 ", " attributes ": { " name ": " John ", " age ": 80 , " gender ": " male " } } ] }

Single Responsibility Principle

• Every module or class should have responsibility over a single part of the functionality provided by the software . • That responsibility should be entirely encapsulated by the class.

• All its services should be narrowly aligned with that responsibility.

Single Page Application Development

JavaScript Packages & Dependencies

NodeJs

• Node.js is a platform built on Chrome's JavaScript runtime for easily building fast and scalable network applications

Packaging

{ " name ": " demo ", " version ": " 1.0.0 ", " description ": " Demo package.json ", " main ": " index.js ", " dependencies ": { " lodash ": " latest " }, " devDependencies ": {}, " scripts ": { " test ": " echo "Error: no test specified" && exit 1 " }, " author ": " Bilal Cinarli ", " license ": " MIT " }

NPM

• Node Package Manager • Default package manager in NodeJs

Yarn

• Yarn package manager • Deterministic Install with lockfiles

ES5 & ES6 KeyPoints

Variables

• let statement declares a block scope local variable, optionally initializing it to a value

• const cannot change through re-assignment, and it can't be redeclared

function varTest() {

var x

1;

if ( true ) {

var x

2;
// same variable!

console.

log ( x );
// 2 } console. log ( x );
// 2

} function letTest() {

let x

1;

if ( true ) {

let x

2;
// different variable

console.

log ( x );
// 2

} console. log ( x );
// 1

}

var list

document. getElementById ( 'list' ); for ( let i

1; i <= 5; i ++ ) {

let item

document. createElement ( 'li' ); item. appendChild (document. createTextNode ( 'Item '

i)); item.onclick

function ( ev ) { console. log ( 'Item '

i +

' is clicked.' ); }; list. appendChild ( item ); } // to achieve the same effect with 'var' // you have to create a different context // using a closure to preserve the value for ( var i

1; i <= 5; i ++ ) {

var item

document. createElement ( 'li' ); item. appendChild (document. createTextNode ( 'Item '

i)); ( function ( i ){ item.onclick

function ( ev ) { console. log ( 'Item '

i +

' is clicked.' ); }; })( i ); list. appendChild ( item ); }

// define MY_FAV as a constant and give it the value 7 const MY_FAV

7; // this will throw an error MY_FAV

20; // will print 7 console. log ( 'my favorite number is: '

MY_FAV); // trying to redeclare a constant throws an error const MY_FAV

20; // the name MY_FAV is reserved for constant above, so this will also fail var MY_FAV

20; // this throws an error also let MY_FAV

20;

Arrow Function

• An arrow function expression has a shorter syntax than a function expression.

• Does not bind its own this, arguments, super, or new.target.

• These function expressions are best suited for non-method functions, and they cannot be used as constructors.

// without variables const f

() => { return

this ; }; // without curly brackets var arguments

42; var arr

() =>

arguments ; arr (); // 42

// An empty arrow function returns undefined let empty

() => {}; (() =>

'foobar' )();
// Returns "foobar" // (this is an Immediately Invoked Function Expression
// see 'IIFE' in glossary) var simple

a => a

15 ? 15 : a;
simple (16); // 15 simple (10); // 10 let max

(a, b) => a

b ? a : b; // More concise promise chains promise. then (a => { // ... }). then (b => { // ... }); // Parameterless arrow functions that are visually easier to parse setTimeout ( () => { console. log ( 'I happen sooner' );

setTimeout ( () => { // deeper code console. log ( 'I happen later' ); }, 1); }, 1);

Object.assign

• The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

• It will return the target object

// copying and object var obj

{ a: 1 }; var copy

Object. assign ({}, obj ); console. log ( copy ); // { a: 1 }

// merging objects var o1

{ a: 1 , b: 1 , c: 1 }; var o2

{ b: 2 , c: 2 }; var o3

{ c: 3 }; var obj

Object. assign ({}, o1 , o2 , o3 ); console. log ( obj ); // { a: 1, b: 2, c: 3 }

function test() {

'use strict' ;

let a

{ b: {c: 4 } , d: { e: {f: 1 } } };

let g

Object. assign ({}, a);

let h

JSON. parse (JSON. stringify (a));

console. log (JSON. stringify (g.d)); // { e: { f: 1 } }

g.d.e

32 ; console. log ( 'g.d.e set to 32.' ); // g.d.e set to 32.

console. log (JSON. stringify (g)); // { b: { c: 4 }, d: { e: 32 } }

console. log (JSON. stringify (a)); // { b: { c: 4 }, d: { e: 32 } }

console. log (JSON. stringify (h)); // { b: { c: 4 }, d: { e: { f: 1 } } }

h.d.e

54 ; console. log ( 'h.d.e set to 54.' ); // h.d.e set to 54.

console. log (JSON. stringify (g)); // { b: { c: 4 }, d: { e: 32 } }

console. log (JSON. stringify (a)); // { b: { c: 4 }, d: { e: 32 } }

console. log (JSON. stringify (h)); // { b: { c: 4 }, d: { e: 54 } }

} test ();

Array Methods: forEach

• The forEach() method executes a provided function once for each

array element.

var a

[ 'a' , 'b' , 'c' ]; a. forEach ( function ( element ) { console. log ( element ); }); // a // b // c

Array Methods: map

• The map() method creates a new array with the results of calling a provided function on every element in this array.

var numbers

[ 1 , 5 , 10 , 15 ]; var roots

numbers. map ( function ( x ) {

return x * 2 ; }); // roots is now [2, 10, 20, 30] // numbers is still [1, 5, 10, 15] var numbers

[ 1 , 4 , 9 ]; var roots

numbers. map (Math.sqrt); // roots is now [1, 2, 3] // numbers is still [1, 4, 9]

Array Methods: filter

• The filter() method creates a new array with all elements that pass the test implemented by the provided function.

var words

[ "spray" , "limit" , "elite" , "exuberant" , "destruction" , "present" ]; var longWords

words. filter ( function ( word ){

return word.length

6 ; });

// Filtered array longWords is ["exuberant", "destruction", "present"]

Array Methods: reduce

• The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value .

[ 0 , 1 , 2 , 3 , 4 ]. reduce ( (prev, curr) => prev + curr );

const pipe

(fns) => (x) => fns. reduce ((v, f) => f(v), x) const times2add1

pipe ([times2, add1]) times2add1 (5) // => 11

Import/Export

• The import statement is used to import functions, objects or primitives that have been exported from an external module, another script, etc.

// Import an entire module's contents. This inserts myModule into the current scope, containing all the exported bindings from the module identified by "my-module", often "my-module.js".

import

as myModule from

'my-module' ; // Import a single member of a module. This inserts myMember into the current scope. import {myMember} from

'my-module' ; // Import multiple members of a module. This inserts both foo and bar into the current scope. import {foo, bar} from

'my-module' ; // Import a member with a more convenient alias. This inserts shortName into the current scope. import {reallyReallyLongModuleMemberName as shortName}

from

'my-module' ; // Import an entire module for side effects only, without importing any bindings. import

'my-module' ; // Import multiple members of a module with convenient aliases. import { reallyReallyLongModuleMemberName as shortName, anotherLongModuleName as short } from

'my-module' ;

• The export statement is used to export functions, objects or primitives from a given file (or module).

// Named exports // exports a function declared earlier

export { myFunction };

// exports a constant export const foo = Math.sqrt(2); // Default exports (only one per script) export default function () {}

// or 'export default class {}' // there is no semi-colon here

Classes

• The class statement is simply a syntactic sugar for prototype inheritance.

• No new object-oriented class concept defined

// Basic class declaration

class

Vehicle {

constructor (type, wheels) {

this .type = type;

this .wheels = wheels; } } // The old way function

Vehicle (type, wheels) {

this .type = type;

this .wheels = wheels; }

• Prototype functions help to extend class methods • For class methods, no need to use function keyword

class

Vehicle {

constructor (type, wheels) {

this .type = type;

this .wheels = wheels; }

get

type (){

return

this .type: } }

Promises

• The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

.then() .catch() Promise pending fulfill reject return return pending Promise error handling .then(onRejection) .catch(onRejection) .then(onFulfillment) async actions