Warsztaty JavaScript

JavaScript Developer @ Evojam
@RobertDuraj
rduraj@gmail.com
Robert Duraj


http://bit.ly/js-lingua-franca
Cel: Facebook 2.0
- Teoria vs Praktyka
- Iteracyjne zdobywanie wiedzy
- Ciągły refactoring
- Prosto do działającego projektu!
Agenda
- Sekcja #1:
- API (server, przeglądarka)
- Środowisko testowe (projekt startowy)
- Twoje pierwsze "Hello World"
- QnA
- TODO
Agenda
- Sekcja #2:
- Idea komponentu (CDD)
- zmienne, stałe
- funkcje
- QnA
- TODO
Agenda
- Sekcja #3:
- instrukcje warunkowe
- obiekty i tablice
- pętle
- QnA
- TODO
Agenda
- Sekcja #4:
- zdarzenia
- nasłuchiwanie na zdarzenia
- QnA
- TODO
Agenda
- Sekcja #5:
- EcmaScript 5 - 2018
- QnA
- TODO
Agenda
- Sekcja #6:
- LocalStorage
- SessionStorage
- Cookies
- QnA
- TODO
Agenda
- Sekcja #7:
- Komunikacja z API aplikacji
- Callbacks
- Promises
- QnA
- TODO
Agenda
- Sekcja #8:
- Konteksty
- Prototypy
- QnA
- TODO

Sekcja #1
API
Application Programming Interface
- przeglądarki
- aplikacji
- klasy
- urządzenia
- etc.

Projekt startowy:
- http://bit.ly/js-workshop-template
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./styles/app.css" />
</head>
<body>
<header>
<h1>My FB</h1>
</header>
<main>
<p>FB content</p>
</main>
<footer>© JS workshops 2018</footer>
</body>
</html>
Jak zacząć pracę z JS?
Jak zacząć pracę z JS?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./styles/app.css" />
</head>
<body>
<header>
<h1>My FB</h1>
</header>
<main>
<p>FB content</p>
</main>
<footer>© JS workshops 2018</footer>
<script src="./scripts/app.js" />
</body>
</html>
<script src="./scripts/app.js" /><script>
// JS code here
</script>Praca z API Twojej przeglądarki
// ./scripts/app.js
window.alert("Hello Bielsko!")// ./scripts/app.js
console.log(window);Dev tools API
// ./scripts/app.js
window.console.log(window);QnA
TODO:
- Stwórz w projekcie plik ./scripts/app.js
- Załaduj w index.html, przed zakończeniem taga <body> skrypt JS: ./scripts/app.js
- Napisz prosty skrypt (w dołączonym wcześniej pliku), wyświetlający Twoje imię w przeglądarce, korzystając z metody alert(...)
- Zamień metodę alert() na prompt() i zobacz, czym różnią się obie te metody.
Sekcja #2
CDD
Component
Driven
Development


HTML-based templates
<div class="card">
<h5><time>17.05.2018</time> - Bob Dylan</h5>
<p>Knockin' On Heaven's Door...</p>
</div><script type="text/template" id="message-template">
<div class="card">
<h5><time>{{date}}</time> - {{author}}</h5>
<p>{{message}}</p>
</div>
</script><script type="text/template" id="message-template">
<div class="card">
<h5><time>17.05.2018</time> - Bob Dylan</h5>
<p>Knockin' On Heaven's Door...</p>
</div>
</script>Jak pracować z szablonem?
// ./scripts/app.js
window.document.getElementById('message-template');// ./scripts/app.js
console.log(window.document.getElementById('message-template').innerHTML);Przypisanie do zmiennej
// ./scripts/app.js
const templateElement = window.document.getElementById('message-template');
console.log(templateElement.innerHTML);// ./scripts/app.js
const getTemplateById = window.document.getElementById;
console.log(getTemplateById('message-template').innerHTML);Operatory przypisania i typy
// ./scripts/app.js
let A = 'jakiś string';
//...
A = 4;
console.log(A); // 4// ./scripts/app.js
const A = 'jakiś string';
const B = ' z dopiskiem';
const C = 5;
console.log(A + B); // 'jakiś string z dopiskiem';
console.log(A + B + C); // 'jakiś string z dopiskiem5';Operatory przypisania i typy
// ./scripts/app.js
let A = 'Hello ';
A += 'World'; // A = A + 'World';// ./scripts/app.js
const A = 'jakiś string';
const B = ' z dopiskiem';
console.log(B - A); // NaN
const C = '2';
const D = '1';
console.log(C - D); // 1
Tworzenie funkcji - function, return
// ./scripts/app.js
const templateElement = window.document.getElementById('message-template');
console.log(templateElement.innerHTML);// ./scripts/app.js
function getTemplateByName(name) {
var templateId = name + '-template';
var templateElement = window.document.getElementById(templateId);
return templateElement.innerHTML;
}
const template = getTemplateByName('message');// ./scripts/app.js
const getTemplateByName = function(name) {
return window.document.getElementById(name + '-template').innerHTML;
}
const template = getTemplateByName('message');Czym jest zasięg widoczności zmiennej?
const A = 'stała o zasięgu globalnym';
function test() {
console.log(A); // stała o zasięgu globalnym
const B = 'stała o zasięgu funkcji';
var C = 'zmienna var o zasięgu funkcji';
if (true === true) {
console.log(A); // stała o zasięgu globalnym
console.log(B); // stała o zasięgu funkcji
console.log(C); // 'zmienna var o zasięgu funkcji'
let D = 'zmienna let o zasięgu klamry';
}
console.log(B); // stała o zasięgu funkcji
console.log(C); // 'zmienna var o zasięgu funkcji'
console.log(D); // udefined
}
test();
console.log(A); // stała o zasięgu globalnym
console.log(B); // udefined
console.log(C); // udefined
console.log(D); // udefined
var, let, const - zatem kiedy?!
CONST

QnA
TODO:
- Stwórz template dla pojedynczej wiadomości w pliku index.html
- W pliku ./scripts/app.js stwórz metodę getTemplateByName do pobierania template'ów po nazwie, przetestuj na szablonie wiadomości z #1
- Skorzystaj z utworzonej funkcji getTemplateByName i dodaj pobrany szablon do obiektu #list korzystając z metod getElementById i właściwości innerHTML
Sekcja #3
Instrukcje warunkowe - If, else, switch
// ./scripts/app.js
if (...warunek) {
// then
} else {
// then
} // ./scripts/app.js
if ('5' === 5) {
console.log('A')
} else {
console.log('B');
} // ./scripts/app.js
switch (letter) {
case 'A':
console.log('A jak Ala!');
break;
case 'B':
console.log('B jak BMW!');
break;
default:
console.log('Każda inna litera też jest fajna!');
}Obiekty i tablice

Obiekty
// ./scripts/app.js
const dog = {
name: 'Frodo',
bark: function () {
console.log('woof! woof!');
}
};
console.log(dog); // { name: 'Frodo', bark: f }
console.log(dog.name); // Frodo
console.log(dog.bark()); // woof! woof!// ./scripts/app.js
const oldHello = "Hello World";
const betterHello = oldHello.replace('World', 'Bielsko');
console.log(oldHello); // "Hello World"
console.log(betterHello); // "Hello Bielsko"
Tablice
// ./scripts/app.js
const messages = [];// ./scripts/app.js
const messages = [];
console.log(typeof messages); // "object"// ./scripts/app.js
const messages = [1, 2, 3, 4];
messages.push(5);
console.log(messages); // [1, 2, 3, 4, 5];
messages.pop();
console.log(messages); // [1, 2, 3, 4];
messages.shift();
console.log(messages); // [2, 3, 4];
Pętle
// ./scripts/app.js
const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];// ./scripts/app.js
for (let index = 0; index < messages.length; index++) {
console.log(messages[index]); // { name: ..., message: ... };
}// ./scripts/app.js
messages.forEach(function(message) {
console.log(message); // { name: ..., message: ... };
});
TODO:
Z podanej tablicy quotes, za pomocą pętli, stwórz listę bohaterów Władcy Pierścieni, pomijając osoby, które nie wystąpiły w książce...
const quotes = [
{
name: 'Lady Galadriel',
quote: 'Even the smallest person can change the course of history.',
},
{
name: 'Frodo',
quote: 'It is useless to meet revenge with revenge: it will heal nothing.',
},
{
name: 'Yoda',
quote: 'Do or do not. There is no try',
},
]map & filter
// ./scripts/app.js
const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];// ./scripts/app.js
const authors = messages.map(function(message) {
return message.name;
});
console.log(authors); // ['Bob Dylan', 'Batman'];// ./scripts/app.js
const batmanMessages = messages.filter(function(message) {
return message.name === 'Batman';
});
console.log(batmanMessages); // [{ name: 'Batman', message: 'I am Batman!' }];TODO:
Zamień poprzednio utworzoną pętlę na połączone metody filter i map, wykonując to samo zadanie:
const quotes = [
{
name: 'Lady Galadriel',
quote: 'Even the smallest person can change the course of history.',
},
{
name: 'Frodo',
quote: 'It is useless to meet revenge with revenge: it will heal nothing.',
},
{
name: 'Yoda',
quote: 'Do or do not. There is no try',
},
]reduce
const numbers = [1, 2, 3, 5, 7, 3];numbers.reduce(function(accumulate, current) {
return accumulate + current;
}, 0);
// 21const messages = [
{ name: 'Bob Dylan', message: 'Like a Rolling Stone...' },
{ name: 'Batman', message: 'I am Batman!' },
];
messages.reduce(function(acc, cur) {
return acc + cur.name + ' ';
}, '');messages
.map(function(message) {
return message.name;
})
.join(', ');QnA
TODO:
- Stwórz tablicę messages
- Dodaj do niej dwa obiekty, zawierające pola name oraz message
- Stwórz metodę createMessage, która będzie oczekiwać dwóch argumentów: name i message
- W metodzie createMessage pobierz szblon wcześniej utworzoną metodą (getTemplateByName) i korzystastając z metody (String).replace, zamień {{name}} i {{message}} na argumenty funkcji (name i message)
TODO:
- Zmapuj tablicę messages, tak, żeby zawierała szablony wiadomości stworzone przez createMessage
- Dodaj każdy kolejny element zmapowanej tablicy messages do obiektu #list wyświetlając wszystkie elementy na widoku.
Powtórka
Zmienne, stałe
const A = 'stała A'
const numberA = 5
let B = 'zmienna B'
let numberB = 5
console.log(A) // 'stała A'
console.log(numberA) // 5
console.log(B) // 'zmienna A'
console.log(numberB) // 5
B = 'zmienna zmieniona B'
console.log(B) // 'zmienna zmieniona B'Operatory arytmetyczne
console.log(5+5); // 10
const A = 5;
const B = 5;
console.log(A+B) // 10
console.log(A-B) // 0
console.log(A/B) // 1
console.log(A*B) // 25
console.log(A%B) // 0
const stringA = 'Ala ma ';
const stringB = 'kota';
console.log(stringA + stringB); // 'Ala ma kota'Funkcje
function nazwaFunkcji (argument1, argument2, argument3) {
console.log(argument1, argument2, argument3);
}
nazwaFunkcji('A', 'B', 5); // 'A' 'B' 5Obiekty
const jedi = {
imie: 'Yoda',
usePower: function () {
console.log('Mmmm, do or do not, there is no try');
}
}function Jedi () {
this.imie = 'Yoda';
this.useForce = function () {
console.log('Mmm. Do or do not, there is no try');
}
}
const Yoda = new Jedi();
Yoda.useForce();Tablice
const tablica = [];
tablica.push('A');
console.log(tablica); // ['A'];
tablica.push('B');
tablica.shift();
console.log(tablica) // ['B']
Pętla forEach
const tablica = ['Ala', 'ma', 'kota']
tablica.forEach(function(slowo) {
console.log(slowo.toUpperCase());
}) // 'ALA' 'MA' 'KOTA'http://bit.ly/js-workshop-template-2
Sekcja #4
Zdarzenia w DOM

Zdarzenie kliknięcia
<button onClick="alert('Hello World');">Przywitaj się!</button>// ./scripts/app.js
document.getElementById('hello-button').addEventListener('click', function() {
alert('Hello World!');
});<button id="hello-button">Przywitaj się!</button>Popularne eventy:
- onChange
- onClick
- onMouseOver
- onMouseOut
- onKeyDown
- onLoad
- focus
- blur
QnA
TODO:
- Dodaj ID do przycisku wyślij w formularzu wiadomości
- Przechwyć za pomocą listenera moment kliknięcia w button
- Pobierz wartość pola textarea za pomocą wartości .value na elemencie textarea i zapisz ją do zmiennej
- Utwórz wiadomość za pomocą createMessage i dodaj ją do listy.
Sekcja #5

Arrow functions
() => {}
/*
function() {}
*/
value => value
/*
function(value) { return value; }
*/
() => ({ field: 'value' })
/*
function() {
return {
field: 'value',
}
}
*/const getTemplateByName = name => window
.document
.getElementById(name + '-template')
.innerHTML;Destructuring objects
function logUser(user) {
console.log(user.firstName, user.lastName, user.email);
}function logUser({ firstName, lastName, email }) {
console.log(firstName, lastName, email);
}function logArray(array) {
console.log(array[0], array[1]);
}
logArray(['firstElement', 'secondElement']); // 'firstElement', 'secondElement'function logArray([firstElement, secondElement]) {
console.log(firstElement, secondElement);
}
logArray(['firstElement', 'secondElement']); // 'firstElement', 'secondElement'Spread operator / rest parameters (...)
function logArguments() {
console.log(arguments);
}
logArguments('A', 'B', 'C'); // Arguments: ['A', 'B', 'C']function logArguments(firstArgument, ...rest) {
console.log(firstArgument, rest);
}
logArguments('A', 'B', 'C'); // Arguments: 'A', ['B', 'C']class
class A {
constructor() {
this.AField = 'A';
}
showA() {
console.log(this.AField);
}
}
class B extends A {
constructor() {
super()
this.BField = 'B';
}
showAB() {
console.log(this.AField, this.BField);
}
}
const AB = new B();
AB.showAB();Default function parameters
function showMessage(message, author) {
if (author === undefined) {
author = 'Anonymous';
}
return '"'message + '" by ' + author;
}function showMessage(message, author = 'Anonymous') {
return '"'message + '" by ' + author;
}Template Literals
const owner = 'Ala';
const oldFashionTemplate = 'Mała ' + owner + ' ma kota';
const withTemplateLiterals = `Mała ${owner} ma kota`;function showMessage(message, author = 'Anonymous') {
return `"${message}" by ${author}`;
}QnA
TODO:
- Zrefaktoryzuj dotychczasowy kod, korzystając z możliwości jakie oferuje nowa specyfikacja EcmaScript
- Postaraj się wykorzystać jak najwięcej nowych elementów
- Wykorzystaj np. arrow functions do skrócenia zapisu .map
Sekcja #6

Dostęp do localStorage
window.localStorage.setItem('key', value);window.localStorage.getItem('key');window.localStorage.removeItem('key');Obiekty w localStorage
window.localStorage.setItem(
'messages',
JSON.stringify([{ message: 'text', author: 'Bob Dylan']),
);const messages = JSON.parse(localStorage.getItem('messages'));Dostęp do sessionStorage
window.sessionStorage.setItem('key', value);window.sessionStorage.getItem('key');window.sessionStorage.removeItem('key');Dostęp do cookies
document.cookie = "yummy_cookie=choco";
document.cookie = "tasty_cookie=strawberry";
console.log(document.cookie);
// logs "yummy_cookie=choco; tasty_cookie=strawberry"const d = new Date();
d.setTime(d.getTime() + 5*1000); // in milliseconds
document.cookie = 'foo=bar;path=/;expires='+d.toGMTString()+';';QnA
TODO:
- Zapisz każdą nową dodaną wiadomość do localStorage
- Po załadowaniu skryptu, odczytaj wszystkie wiadomości z localStorage i wyświetl na stronie
Sekcja #7
TBC
Sekcja #8
TBC
JS Workshops
By Robert
JS Workshops
- 340