SlideShare a Scribd company logo
Practical JavaScript Programming
Session 5
Wilson Su
2
https://www.slideshare.net/sweekson/
3
Wilson Su
Front-end Developer, HIE
● 6 years in web design
● Specialize in JavaScript /
CSS / HTML / OOP / Git
● Familiar with PHP / Design
Pattern
● Interested in UI & Ix Design
wilson_su@trend.com.tw
Outline
4
Practical JavaScript Programming
Chapter 9.
● Form Elements
● Form Events
● Access Form Data
● Validations
● Custom Components
Forms
Chapter 10.
AJAX
● What’s AJAX?
● Handle Request
● Security
● Practices
● Promise
● Server-sent Events
● WebSocket
Chapter 9.
Forms
5
Form Elements
6
HTML Form Elements
7
1. <input type="text" value="initial value"/>
2. <input type="password"/>
3. <input type="checkbox" value="abc" checked/>
4. <input type="radio" value="xyz" checked/>
5. <input type="file" multiple/>
6. <input type="hidden"/>
7. <select multiple>
8. <option value="1">1</option>
9. <option value="2" selected>2</option>
10. <option value="3">3</option>
11. </select>
12. <textarea cols="30" rows="5">initial value</textarea>
HTML Buttons
8
1. <input type="button" value="Action"/>
2. <input type="submit" value="Submit"/>
3. <input type="reset" value="Reset"/>
4. <button type="button">Action</button>
5. <button type="submit">Submit</button>
6. <button type="reset">Reset</button>
HTML <form> Element With GET Method
9
1. <form action="/search" method="get">
2. <input name="query" type="text" value="keywords"/>
3. <button type="submit">Search</button>
4. </form>
5. <!-- When the form is submitted, the URL will be generated as
'/search?query=keywords' -->
HTML <form> Element With POST Method
10
1. <form action="/login" method="post">
2. <label for="user">Username:</label>
3. <input id="user" name="user" type="text" value="guest"/>
4. <label for="pass">Password:</label>
5. <input id="pass" name="pass" type="password" value="12345"/>
6. <button type="submit">Sign In</button>
7. </form>
8. <!-- When the form is submitted, the request body be generated
as 'user=guest&pass=12345' -->
Compare GET VS. POST
11
Form Elements
GET POST
Requests data from a specified
resource
Submits data to be processed
to a specified resource
Can be bookmarked Cannot be bookmarkedBookmarked
Can be cached Not cachedCached
Data is visible to everyone in the URL Data is not displayed in the URLVisibility
Harmless Data will be re-submittedBACK button / Reload
The length of a URL is limited No restrictionsMax URL length
Form Events
12
Event Delegator
13
1. function delegator (elem) {
2. return function (type, selectors, fn, capture) {
3. function matches (target) {
4. return selectors.some(v => target.matches(v));
5. }
6. function listener (e) {
7. matches(e.target) && fn.call(e.target, e);
8. }
9. selectors = selectors.split(/,s*/g);
10. elem.addEventListener(type, listener, capture);
11. return listener;
12. };
13. }
HTML <input> Events
14
1. var query = document.querySelector('input#query');
2. var logger = function (e) { console.log(e.type); }
3. query.addEventListener('focus', logger);
4. query.addEventListener('input', logger);
5. query.addEventListener('blur', logger);
6. query.addEventListener('change', logger);
7. query.addEventListener('keydown', logger);
8. query.addEventListener('keypress', logger);
9. query.addEventListener('keyup', logger);
10. /* When the input has focus, and user typed one letter */
11. // 'focus', 'keydown', 'keypress', 'input', 'keyup'
12. /* When the input has lost focus */
13. // 'change', 'blur'
Focus Events
15
1. <input id="name" type="text"/>
2. <script>
3. var name = document.querySelector('#name');
4. name.addEventListener('focus', (e) => console.log(e.type));
5. name.addEventListener('blur', (e) => console.log(e.type));
6. name.addEventListener('focusin', (e) => console.log(e.type));
7. name.addEventListener('focusout', (e) => console.log(e.type));
8. /* When the input has focus */
9. // 'focus', 'focusin'
10. /* When the input has lost focus */
11. // 'blur', 'focusout'
12. </script>
The input focus and blur event
does not bubble.
16
The focus and blur Event Does Not Bubble
17
1. <form id="edit"><input id="address" type="text"/></form>
2. <script>
3. var edit = document.querySelector('#edit');
4. var name = document.querySelector('#address');
5. var onFocus = function (e) {
6. console.log(e.currentTarget.tagName, e.type);
7. };
8. edit.addEventListener('focus', onFocus);
9. edit.addEventListener('blur', onFocus);
10. name.addEventListener('focus', onFocus);
11. name.addEventListener('blur', onFocus);
12. // 'INPUT' 'focus', 'INPUT' 'blur'
13. </script>
Selecting Text on Focus
18
1. <input type="text" value="Hello"/>
2. <textarea cols="30" rows="5">Aloha</textarea>
3. <script>
4. var body = document.body;
5. var selectors = 'input[type="text"], textarea';
6. var onFocus = function (e) { e.target.select(); };
7. delegator(body)('focusin', selectors, onFocus);
8. delegator(body)('focus', selectors, onFocus, true);
9. </script>
Filtering a List Using input Event
19
1. <input id="filter" type="text"/>
2. <div id="output"></div>
3. <script>
4. var filter = document.querySelector('#filter');
5. var output = document.querySelector('#output');
6. var items = ['JS', 'JAVA', 'PHP', 'NODEJS'];
7. filter.addEventListener('input', function (e) {
8. output.textContent = items.filter(item => {
9. return item.indexOf(e.target.value) > -1;
10. });
11. });
12. </script>
HTML Form submit and reset Events
20
1. <form id="atm" action="/transfer">
2. <input id="pass" type="password"/>
3. <button type="submit">Enter</button>
4. <button type="reset">Clear</button>
5. </form>
6. <script>
7. var atm = document.querySelector('#atm');
8. var logger = function (e) { console.log(e.type); };
9. atm.addEventListener('submit', logger);
10. atm.addEventListener('reset', logger);
11. // 'reset', 'submit'
12. </script>
Access Form Data
21
Assigning Default Values
22
1. <form action="/order" method="post">
2. Amount: <input id="amount" type="text"/>
3. <input id="dm" type="checkbox"/> Send me DM
4. <button type="submit">Save</button>
5. <button type="reset">Reset</button>
6. </form>
7. <script>
8. document.querySelector('#amount').value = 0;
9. document.querySelector('#dm').checked = true;
10. /* The input.value will be reset to empty after the Reset
button has been clicked. Use input.defaultValue to assign a
default value. Use input.defaultChecked for checkbox and radio
*/
11. </script>
Getting and Setting Values of Input Text and Textarea
23
1. <input id="name" type="text" value="Ben"/>
2. <textarea id="intro" cols="10" rows="5">Ben is a RD</textarea>
3. <script>
4. var name = document.querySelector('#name');
5. var intro = document.querySelector('#intro');
6. console.log(name.value); // 'Ben'
7. console.log(intro.value); // 'Ben is a RD'
8. name.value = 'Vicky';
9. intro.value = 'Vicky is a VD';
10. </script>
Getting Values of Checked Checkboxes
24
1. <input name="order" id="1" type="checkbox" value="50" checked>
2. <label for="1">French fries</label>
3. <input name="order" id="2" type="checkbox" value="30" checked>
4. <label for="2">Sprite</label>
5. <script>
6. var selector = '[name="order"]:checked';
7. var selected = document.querySelectorAll(selector);
8. var values = [...selected].map(elem => elem.value);
9. var total = values.reduce((a, b) => +a + +b);
10. console.log(total); // 80
11. </script>
Setting checked to a Checkbox
25
1. <input id="enabled" type="checkbox" checked/>
2. <script>
3. var enabled = document.querySelector('#enabled');
4. console.log(enabled.value); // 'on'
5. console.log(enabled.hasAttribute('checked')); // true
6. console.log(enabled.checked); // true
7.
8. enabled.checked = false;
9. console.log(enabled.hasAttribute('checked')); // true
10. console.log(enabled.getAttribute('checked')); // ''
11. </script>
Getting and Setting Value of Radio Button Group
26
1. <form name="profile">
2. <input name="gender" type="radio" value="M" checked/> Male
3. <input name="gender" type="radio" value="F"/> Female
4. </form>
5. <script>
6. var selector = '[name="gender"]:checked';
7. var selected = document.querySelector(selector);
8. console.log(selected.value); // 'M'
9. console.log(document.forms.profile.gender.value); // 'M'
10. document.forms.profile.gender.value = 'F';
11. </script>
Getting Selected Value of a Select
27
1. <select id="lang">
2. <option value="en-US">English</option>
3. <option value="zh-TW" selected>繁體中文</option>
4. </select>
5. <script>
6. var lang = document.querySelector('#lang');
7. var options = lang.options;
8. console.log(lang.value); // 'zh-TW'
9. console.log(lang.selectedIndex); // 1
10. console.log(options[lang.selectedIndex].text); // '繁體中文'
11. lang.value = 'en-US';
12. console.log(options[1].selected); // false
13. </script>
Getting Selected Values of a Multiple Select
28
1. <select id="beverage" multiple>
2. <option value="tea" selected>Tea</option>
3. <option value="soda">Soda</option>
4. <option value="coffee" selected>Coffee</option>
5. </select>
6. <script>
7. var beverage = document.querySelector('#beverage');
8. var options = drink.options;
9. var selected = [...options].filter(o => o.selected);
10. var values = selected.map(o => o.value);
11. console.log(values); // (2) ['tea', 'coffee']
12. </script>
Serializing Form Data - Snippet 1/2
29
1. <form id="edit">
2. <input type="text" name="text" value="1"/>
3. <input type="checkbox" name="checkbox" value="2" checked/>
4. <input type="checkbox" name="checkbox" value="3" checked/>
5. <input type="radio" name="radio" value="4"/>
6. <input type="radio" name="radio" value="5" checked/>
7. <select name="select">
8. <option value="6">6</option>
9. <option value="7" selected>7</option>
10. </select>
11. <textarea name="textarea" cols="30" rows="5">8</textarea>
12. <button type="submit">Submit</button>
13. </form>
Serializing Form Data - Snippet 2/2
30
1. function serialize (form) {
2. var key, val, output = [...form.elements].map(elem => {
3. key = elem.name, val = elem.value;
4. if (elem.type === 'checkbox' || elem.type === 'radio') {
5. val = elem.checked ? val : null;
6. }
7. if (!key || val === null) { return false; }
8. return `${key}=${val}`;
9. });
10. return output.filter(v => v).join('&');
11. }
12. console.log(serialize(document.querySelector('#edit')));
13. // 'text=1&checkbox=2&checkbox=3&radio=5&select=7&textarea=8'
Validations
31
Disable browser default
validations.
32
HTML <form> novalidate Attribute
33
1. <form action="/login" method="post" novalidate>
2. Username: <input name="user" type="text" required/>
3. Password: <input name="pass" type="password" required/>
4. <button type="submit">Sign In</button>
5. </form>
Checking Required Fields
34
1. <form id="login" action="/login" method="post" novalidate>
2. Username: <input name="user" type="text" required/>
3. Password: <input name="pass" type="password" required/>
4. <button type="submit">Sign In</button>
5. </form>
6. <script>
7. var login = document.querySelector('#login'), required;
8. login.addEventListener('submit', function (e) {
9. required = document.querySelectorAll(':required');
10. if ([...required].filter(el => !el.value).length) {
11. e.preventDefault();
12. }
13. });
14. </script>
Preventing User From Typing Non-numeric Values
35
1. <input id="phone" type="text"/>
2. <script>
3. var phone = document.querySelector('#phone');
4. phone.addEventListener('keypress', function (e) {
5. if (e.key && !/^[0-9]+$/.test(e.key)) {
6. e.preventDefault();
7. }
8. });
9. </script>
Preventing Form Submission Using onsubmit Attribute
36
1. <form action="/login" onsubmit="return onSignin(event);">
2. Username: <input id="user" type="text"/>
3. Password: <input id="pass" type="password"/>
4. <button type="submit">Sign In</button>
5. </form>
6. <script>
7. var user = document.querySelector('#user');
8. var pass = document.querySelector('#pass');
9. function onSignin (e) {
10. return !!user.value && !!pass.value;
11. }
12. </script>
Preventing Form Submission Using Event Handler
37
1. <form id="login" action="/login">
2. Username: <input id="user" type="text"/>
3. Password: <input id="pass" type="password"/>
4. <button type="submit">Sign In</button>
5. </form>
6. <script>
7. var login = document.querySelector('#login');
8. var user = document.querySelector('#user');
9. var pass = document.querySelector('#pass');
10. login.addEventListener('submit', function onSignin (e) {
11. (!user.value || !pass.value) && e.preventDefault();
12. });
13. </script>
Custom Components
38
Combo Box
39
Custom Components
A combo box allows the user to type in a
single-line input to limit the search, and select
an item from a list of matched options.
Combo box interaction specs ( incomplete ) :
● Click the caret button to open options
● Type keywords to filter options
● Arrow buttons to highlight an option
● Press enter to set value with the
highlighted option
● Click cancel button to clear search
40
Date Picker
The date picker contains the date input field
and the calendar view. Users can either use
the input field to type a date or by selecting a
date in the calendar.
Date picker interaction specs ( incomplete ) :
● Focus input to open a canlendar
● Press keyboard arrows to switch year,
month, and date
● Click arrows to switch months
● Click a date to set value
Custom Components
Chapter 10.
AJAX
41
What’s AJAX?
42
AJAX
43
● AJAX is an acronym for Asynchronous
JavaScript and XML
● It is a web technique that allows for more
interactivity by making web pages that
fetch data in the background and alter
themselves without reloading the entire
page.
● A user can continue to use the
application while the client program
requests information from the server in
the background.
What’s AJAX?
A Traditional Web Application
44
What’s AJAX?
Client Server
User Interface Web Server
Data Beckend
HTTP Request
HTML + CSS + JS
An AJAX Web Application
45
What’s AJAX?
User Interface Web Server
Data BeckendAJAX Engine
Client Server
HTTP Request
JS Call Data
Data
(XML / TEXT / HTML / JSON)
Handle Request
46
Making an AJAX Request
47
1. var xhr = new XMLHttpRequest();
2. xhr.onreadystatechange = function () {
3. if (xhr.readyState === xhr.DONE && xhr.status === 200) {
4. console.log(xhr.responseText);
5. // <button id="{{id}}" type="button">{{action}}</button>
6. }
7. };
8. xhr.open('get', '/templates/button.html', true);
9. xhr.send();
Making a Synchronous Request
48
1. var xhr = new XMLHttpRequest();
2. xhr.open('GET', '/data/cars.json', false);
3. xhr.send();
4. console.log(xhr.responseText);
5. // '["audi","benz","bmw"]'
Synchronous XMLHttpRequest
makes the JavaScript stop
executing until the server
response is ready. If the server
is busy or slow, the application
will hang or stop.
49
Wrapping XMLHttpRequest
50
1. function request (method, url, callback) {
2. var xhr = new XMLHttpRequest();
3. xhr.onreadystatechange = function () {
4. if (xhr.readyState === xhr.DONE && xhr.status === 200) {
5. callback instanceof Function && callback(this);
6. }
7. };
8. xhr.open(method, url, true);
9. return xhr;
10. }
11. /* Usage */
12. // request('get', '/data/cars.json', (xhr) => { … }).send();
Handling the Server Response
51
1. request('get', '/data/numbers.json', function (xhr) {
2. console.log(xhr.status); // 200
3. console.log(xhr.statusText); // 'OK'
4. console.log(xhr.responseText); // '[100,200,300]'
5. console.log(xhr.getResponseHeader('Content-type'));
6. // 'application/json'
7. })
8. .send();
Working with XML Data
52
1. /* Given a XML file 'food.xml' as follows:
2. <?xml version="1.0" encoding="UTF-8"?>
3. <root><food>Pizza</food><food>Bread</food></root>
4. */
5. request('get', '/data/food.xml', function (xhr) {
6. var nodes = xhr.responseXML.getElementsByTagName('food');
7. var data = [...nodes].map(node => node.textContent);
8. console.log(data); // (2) ['Pizza', 'Bread']
9. })
10. .send();
Using POST Method in XMLHTTPRequest
53
1. var item = 'item=iphone';
2. var amount = 'amount=99';
3. var params = [item, amount].join('&');
4. var contentType = 'application/x-www-form-urlencoded';
5. var xhr = request('post', '/order', function (xhr) {
6. console.log(xhr.responseText);
7. // '{"data":{"item":"iphone","amount":"99"}}'
8. });
9. xhr.setRequestHeader('Content-type', contentType);
10. xhr.send(params);
Encoding a URI Component
54
1. var hello = '你好';
2. var param = 'text=' + encodeURIComponent(hello);
3. var url = '/echo?' + param;
4. request('get', url, function (xhr) {
5. console.log(xhr.responseText); // '你好'
6. })
7. .send();
Uploading a File
55
1. <input id="file" type="file"/>
2. <script>
3. var file = document.querySelector('#file').files[0];
4. var data = new FormData();
5. var xhr = request('post', '/upload');
6. data.append('target', 'images');
7. data.append('file', file, 'sky.jpg');
8. xhr.send(data);
9. </script>
Monitoring Progress of a File Upload
56
1. var file = document.querySelector('#file').files[0];
2. var data = new FormData();
3. var xhr = request('post', '/upload');
4. data.append('file', file);
5. xhr.upload.addEventListener('progress', function (e) {
6. if (e.lengthComputable) {
7. console.log(Math.floor(e.loaded / e.total * 100));
8. }
9. });
10. xhr.send(data);
Security
57
AJAX requests
are forbidden by default
by the same-origin policy.
58
URL Outcome Reason
http://www.abc.com/about/contact.html Success Same protocol, host and port
http://www.abc.com/service/training.html Success Same protocol, host and port
https://www.abc.com/member/login.html Failure Different protocol
http://www.abc.com:8080/partners.html Failure Different port
http://abc.com/blog/tags.html Failure Different host
Same-origin Policy
59
The same-origin policy restricts how a document or script loaded from one
origin can interact with a resource from another origin.
The following table gives examples of origin comparisons to the URL
http://www.abc.com/about/index.html:
Security
Cross-Origin Resource Sharing
CORS is a system, consisting of transmitting HTTP headers, that
determines whether to block or fulfill requests for restricted resources on a
web page from another domain outside the domain from which the
resource originated.
To allow any resource to access your resource, you can specify:
Access-Control-Allow-Origin: *
To allow https://www.abc.com to access your resource, you can specify:
Access-Control-Allow-Origin: https://www.abc.com
60
Security
JSON with Padding
61
JSONP is used to request data from a server residing in a different domain
than the client.
JSONP
Client
Server
<script>function fn (data) { … }</script>
<script src="https://api.su.com/users/9?callback=fn"></script>
response.setHeader('Content-type', 'text/javascript');
response.send('fn({ "id": 9, "name": "Kyle" })');
Practices
62
Polling
63
1. function Polling (options) {
2. this.url = options.url;
3. this.method = options.method || 'get';
4. this.callback = options.callback || (() => {});
5. this.delay = options.delay || 1000;
6. this.start();
7. }
8. Polling.prototype.start = function () {
9. setTimeout(() => {
10. request(this.method, this.url, this.callback).send();
11. this.start();
12. }, this.delay);
13. };
Checking Username Availability
64
1. var account = document.querySelector('input#account');
2. var defer = function (fn) {
3. var timer;
4. return function (e) {
5. if (timer) { clearTimeout(timer); }
6. timer = setTimeout(() => fn.call(e.target, e), 300);
7. };
8. };
9. account.addEventListener('input', defer(function (e) {
10. request('get', '/api/users/check', () => {});
11. }));
You don’t need AJAX to
download a file.
65
Downloading a File
66
1. var url = 'https://locate/to/file';
2. /* Solution 1 */
3. location.assign(url);
4.
5. /* Solution 2 */
6. window.open(url, '_blank');
7.
8. /* Solution 3 (Better) */
9. var iframe = document.createElement('iframe');
10. iframe.style.display = 'none';
11. iframe.src = url;
12. document.appendChild(iframe);
Disable action buttons while
requesting to prevent user from
re-submitting the form.
67
Disabling Submit Button When Request Is In-progress
68
1. var profile = document.querySelector('form#profile');
2. var save = document.querySelector('[type="submit"]#save');
3. profile.addEventListener('submit', function (e) {
4. e.preventDefault();
5. request('post', 'submit', function (xhr) {
6. save.disabled = false;
7. }).send();
8. save.disabled = true;
9. });
Callback Hell
69
1. /* Suppose url1, url2, url3, and success are defined */
2. request('get', url1, function (xhr) {
3. request('get', url2, function (xhr) {
4. request('get', url3, function (xhr) {
5. success();
6. });
7. });
8. });
Using Named Functions
70
1. /* Suppose url1, url2, url3, and success are defined */
2. function doReq1 () {
3. request('get', url1, function () { doReq2(); });
4. }
5. function doReq2 () {
6. request('get', url2, function () { doReq3(); });
7. }
8. function doReq3 () {
9. request('get', url3, function () { success(); });
10. }
11. doReq1();
Promise
71
What’s a Promise?
72
A Promise is an object representing the eventual completion or failure of
an asynchronous operation. – MDN
Promise
Promise
.then(onFulfilled)
.catch(onRejected)
Promise …
pending
resolved
rejected
pending
return
Creating a Promise
73
1. new Promise(function (resolve, reject) {
2. setTimeout(() => resolve('Success!'), 1000);
3. })
4. .then(function (message) {
5. console.log(message); // 'Success!'
6. return { message };
7. })
8. .then(function (data) {
9. console.log(data); // {message: 'Success!'}
10. })
11. .catch(function (error) {
12. console.log(error);
13. });
Chaining after a catch
74
1. new Promise((resolve, reject) => {
2. console.log('initialized');
3. resolve();
4. })
5. .then(() => {
6. throw new Error('something failed');
7. console.log('success');
8. })
9. .catch((error) => console.log('failure'))
10. .then(() => console.log('Whatever happened before'));
11. // 'initialized', 'failure', 'Whatever happened before'
Wrapping AJAX Request with Promise
75
1. function ajax (method, url, data) {
2. return new Promise(function (resolve, reject) {
3. var xhr = new XMLHttpRequest();
4. xhr.onreadystatechange = function () {
5. if (xhr.readyState === xhr.DONE) {
6. if (xhr.status === 200) {
7. resolve(JSON.parse(xhr.responseText));
8. } else { reject(xhr.responseText); }
9. }
10. };
11. xhr.open(method, url, true);
12. xhr.send(data);
13. });
14. }
Making a Request With the Enhanced Request Function
76
1. ajax('post', '/api/order', { item: 'ipad', amount: 99 })
2. .then(function (data) {
3. console.log(data);
4. })
5. .catch(function (error) {
6. console.error(error);
7. });
Chaining Requests with Promises
77
1. /* Suppose url1, url2, url3, and success are defined */
2. function doReq1 () { return ajax('get', url1); }
3. function doReq2 () { return ajax('get', url2); }
4. function doReq3 () { return ajax('get', url3); }
5. doReq1().then(doReq2).then(doReq3).then(success);
The Promise.all() Method
78
1. Promise.all([
2. ajax('get', '/data/hosts.json'),
3. ajax('get', '/data/users.json')
4. ])
5. .then(function ([hosts, users]) {
6. console.log(hosts);
7. console.log(users);
8. })
9. .catch(function (error) {
10. console.error(error);
11. });
The fetch API
79
1. var data = new FormData();
2. data.append('action', 'cancel');
3.
4. fetch('/orders/1', { method: 'POST', body: data })
5. .then(function (response) {
6. // response.ok bool
7. // response.status number
8. // response.headers Headers
9. // response.json() Promise
10. })
11. .catch(function (error) {});
Server-sent Events
80
Server-sent Events
81
SSE is a technology where a browser receives automatic updates from a
server via HTTP connection. – Wiki
Request
Response
Request
Response
Handshake
Acknowledgement
Server push
Server push
CLIENT SERVER
Polling
CLIENT SERVER
Server-sent Event
VS.
Receiving Server-Sent Event Notifications
82
1. var es = new EventSource('http://localhost/stream');
2.
3. es.addEventListener('open', function (e) { … });
4. es.addEventListener('error', function (e) { … });
5. es.addEventListener('message', function (e) {
6. console.log(JSON.parse(e.data));
7. });
8. es.addEventListener('custom-event', function (e) {
9. console.log(JSON.parse(e.data));
10. });
WebSocket
83
WebSocket is a computer communications protocol, providing full-duplex
communication channels over a single TCP connection. – Wiki
What Is WebSocket?
84
WebSocket
Request
Response
Request
Response
Handshake
Acknowledgement
Bi-directional
messages
Connection end
CLIENT SERVER
HTTP
CLIENT SERVER
WebSocket
VS.
Connection lifecycle Connection lifecycle
Creating a WebSocket Object
85
1. var ws = new WebSocket('wss://localhost');
2.
3. ws.addEventListener('open', function (e) { … });
4. ws.addEventListener('error', function (e) { … });
5. ws.addEventListener('message', function (e) {
6. console.log(JSON.parse(e.data));
7. // { success: true, action: 'echo', data: 'Bye' }
8. ws.close();
9. };
10. ws.send(JSON.stringify({ action: 'echo', data: 'Bye' }));
Reference
86
● Ajax (programming) - Wikipedia
● CORS - Glossary | MDN
● Cross-origin resource sharing - Wikipedia
● GET vs POST - Difference and Comparison | Diffen
● JavaScript | MDN
● JSONP - Wikipedia
Practical JavaScript Programming
Reference
● Same-origin policy - Wikipedia
● Same-origin policy - Web security | MDN
● Server-sent events - Wikipedia
● WebSocket - Wikipedia
87
Practical JavaScript Programming
Questions?
88
THANKS

More Related Content

PDF
Practical JavaScript Programming - Session 7/8
PDF
Practical JavaScript Programming - Session 8/8
PDF
Practical JavaScript Programming - Session 4/8
PDF
Practical JavaScript Programming - Session 1/8
PDF
Practical JavaScript Programming - Session 6/8
PDF
Mirage For Beginners
PDF
Workshop 5: JavaScript testing
PPTX
JavaScript Proven Practises
Practical JavaScript Programming - Session 7/8
Practical JavaScript Programming - Session 8/8
Practical JavaScript Programming - Session 4/8
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 6/8
Mirage For Beginners
Workshop 5: JavaScript testing
JavaScript Proven Practises

What's hot (20)

PDF
Обзор фреймворка Twisted
PPTX
Workshop 1: Good practices in JavaScript
PDF
05 JavaScript #burningkeyboards
PDF
Workshop 10: ECMAScript 6
PDF
06 jQuery #burningkeyboards
PDF
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
PDF
ClojurianからみたElixir
PDF
201104 iphone navigation-based apps
PDF
KEY
Why ruby
PPTX
Component lifecycle hooks in Angular 2.0
PDF
Testing your javascript code with jasmine
KEY
Ruby/Rails
KEY
Backbone js
PDF
To Err Is Human
PPTX
Metaprogramming in ES6
PDF
JavaScript and the AST
PDF
Impact of the New ORM on Your Modules
PPTX
AngularJS: what is underneath the hood
KEY
안드로이드 세미나 2
Обзор фреймворка Twisted
Workshop 1: Good practices in JavaScript
05 JavaScript #burningkeyboards
Workshop 10: ECMAScript 6
06 jQuery #burningkeyboards
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
ClojurianからみたElixir
201104 iphone navigation-based apps
Why ruby
Component lifecycle hooks in Angular 2.0
Testing your javascript code with jasmine
Ruby/Rails
Backbone js
To Err Is Human
Metaprogramming in ES6
JavaScript and the AST
Impact of the New ORM on Your Modules
AngularJS: what is underneath the hood
안드로이드 세미나 2
Ad

Similar to Practical JavaScript Programming - Session 5/8 (20)

PPTX
HTML Forms: The HTML element represents a document section containing interac...
PDF
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
PPTX
Web design - Working with forms in HTML
PPT
20-html-forms.ppt
PPT
11-html-forms.ppt
PPT
05 html-forms
PPT
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
PPTX
html forms
PPT
Html,Css and Javascript Forms using different tags
PPT
Html Forms.ppt
PPT
Html Forms for creating frames and frameset
PPTX
Html Forms for lecture BSIT SSC HCI LECTURE
PPT
20 html-forms
PPTX
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
PPTX
HTML FORMS.pptx
PDF
2. HTML forms
PDF
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
PPT
Html class-04
PPT
HtmlForms- basic HTML forms description.
PDF
Web I - 04 - Forms
HTML Forms: The HTML element represents a document section containing interac...
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
Web design - Working with forms in HTML
20-html-forms.ppt
11-html-forms.ppt
05 html-forms
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
html forms
Html,Css and Javascript Forms using different tags
Html Forms.ppt
Html Forms for creating frames and frameset
Html Forms for lecture BSIT SSC HCI LECTURE
20 html-forms
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
HTML FORMS.pptx
2. HTML forms
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
Html class-04
HtmlForms- basic HTML forms description.
Web I - 04 - Forms
Ad

More from Wilson Su (7)

PDF
NestJS
PDF
The Jira How-To Guide
PDF
The Future of Web Development
PDF
Web Usability
PDF
Puppeteer - Headless Chrome Node API
PDF
Practical JavaScript Programming - Session 3/8
PDF
Practical JavaScript Programming - Session 2/8
NestJS
The Jira How-To Guide
The Future of Web Development
Web Usability
Puppeteer - Headless Chrome Node API
Practical JavaScript Programming - Session 3/8
Practical JavaScript Programming - Session 2/8

Recently uploaded (20)

PPTX
CH1 Production IntroductoryConcepts.pptx
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PPTX
CYBER-CRIMES AND SECURITY A guide to understanding
PPTX
web development for engineering and engineering
PDF
Automation-in-Manufacturing-Chapter-Introduction.pdf
PDF
Digital Logic Computer Design lecture notes
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PDF
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
PPTX
Welding lecture in detail for understanding
PDF
composite construction of structures.pdf
PPTX
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
PPTX
additive manufacturing of ss316l using mig welding
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PDF
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
PDF
Well-logging-methods_new................
PPTX
UNIT 4 Total Quality Management .pptx
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
CH1 Production IntroductoryConcepts.pptx
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
Foundation to blockchain - A guide to Blockchain Tech
CYBER-CRIMES AND SECURITY A guide to understanding
web development for engineering and engineering
Automation-in-Manufacturing-Chapter-Introduction.pdf
Digital Logic Computer Design lecture notes
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
Welding lecture in detail for understanding
composite construction of structures.pdf
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
additive manufacturing of ss316l using mig welding
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
UNIT-1 - COAL BASED THERMAL POWER PLANTS
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
Well-logging-methods_new................
UNIT 4 Total Quality Management .pptx
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...

Practical JavaScript Programming - Session 5/8

  • 3. 3 Wilson Su Front-end Developer, HIE ● 6 years in web design ● Specialize in JavaScript / CSS / HTML / OOP / Git ● Familiar with PHP / Design Pattern ● Interested in UI & Ix Design wilson_su@trend.com.tw
  • 4. Outline 4 Practical JavaScript Programming Chapter 9. ● Form Elements ● Form Events ● Access Form Data ● Validations ● Custom Components Forms Chapter 10. AJAX ● What’s AJAX? ● Handle Request ● Security ● Practices ● Promise ● Server-sent Events ● WebSocket
  • 7. HTML Form Elements 7 1. <input type="text" value="initial value"/> 2. <input type="password"/> 3. <input type="checkbox" value="abc" checked/> 4. <input type="radio" value="xyz" checked/> 5. <input type="file" multiple/> 6. <input type="hidden"/> 7. <select multiple> 8. <option value="1">1</option> 9. <option value="2" selected>2</option> 10. <option value="3">3</option> 11. </select> 12. <textarea cols="30" rows="5">initial value</textarea>
  • 8. HTML Buttons 8 1. <input type="button" value="Action"/> 2. <input type="submit" value="Submit"/> 3. <input type="reset" value="Reset"/> 4. <button type="button">Action</button> 5. <button type="submit">Submit</button> 6. <button type="reset">Reset</button>
  • 9. HTML <form> Element With GET Method 9 1. <form action="/search" method="get"> 2. <input name="query" type="text" value="keywords"/> 3. <button type="submit">Search</button> 4. </form> 5. <!-- When the form is submitted, the URL will be generated as '/search?query=keywords' -->
  • 10. HTML <form> Element With POST Method 10 1. <form action="/login" method="post"> 2. <label for="user">Username:</label> 3. <input id="user" name="user" type="text" value="guest"/> 4. <label for="pass">Password:</label> 5. <input id="pass" name="pass" type="password" value="12345"/> 6. <button type="submit">Sign In</button> 7. </form> 8. <!-- When the form is submitted, the request body be generated as 'user=guest&pass=12345' -->
  • 11. Compare GET VS. POST 11 Form Elements GET POST Requests data from a specified resource Submits data to be processed to a specified resource Can be bookmarked Cannot be bookmarkedBookmarked Can be cached Not cachedCached Data is visible to everyone in the URL Data is not displayed in the URLVisibility Harmless Data will be re-submittedBACK button / Reload The length of a URL is limited No restrictionsMax URL length
  • 13. Event Delegator 13 1. function delegator (elem) { 2. return function (type, selectors, fn, capture) { 3. function matches (target) { 4. return selectors.some(v => target.matches(v)); 5. } 6. function listener (e) { 7. matches(e.target) && fn.call(e.target, e); 8. } 9. selectors = selectors.split(/,s*/g); 10. elem.addEventListener(type, listener, capture); 11. return listener; 12. }; 13. }
  • 14. HTML <input> Events 14 1. var query = document.querySelector('input#query'); 2. var logger = function (e) { console.log(e.type); } 3. query.addEventListener('focus', logger); 4. query.addEventListener('input', logger); 5. query.addEventListener('blur', logger); 6. query.addEventListener('change', logger); 7. query.addEventListener('keydown', logger); 8. query.addEventListener('keypress', logger); 9. query.addEventListener('keyup', logger); 10. /* When the input has focus, and user typed one letter */ 11. // 'focus', 'keydown', 'keypress', 'input', 'keyup' 12. /* When the input has lost focus */ 13. // 'change', 'blur'
  • 15. Focus Events 15 1. <input id="name" type="text"/> 2. <script> 3. var name = document.querySelector('#name'); 4. name.addEventListener('focus', (e) => console.log(e.type)); 5. name.addEventListener('blur', (e) => console.log(e.type)); 6. name.addEventListener('focusin', (e) => console.log(e.type)); 7. name.addEventListener('focusout', (e) => console.log(e.type)); 8. /* When the input has focus */ 9. // 'focus', 'focusin' 10. /* When the input has lost focus */ 11. // 'blur', 'focusout' 12. </script>
  • 16. The input focus and blur event does not bubble. 16
  • 17. The focus and blur Event Does Not Bubble 17 1. <form id="edit"><input id="address" type="text"/></form> 2. <script> 3. var edit = document.querySelector('#edit'); 4. var name = document.querySelector('#address'); 5. var onFocus = function (e) { 6. console.log(e.currentTarget.tagName, e.type); 7. }; 8. edit.addEventListener('focus', onFocus); 9. edit.addEventListener('blur', onFocus); 10. name.addEventListener('focus', onFocus); 11. name.addEventListener('blur', onFocus); 12. // 'INPUT' 'focus', 'INPUT' 'blur' 13. </script>
  • 18. Selecting Text on Focus 18 1. <input type="text" value="Hello"/> 2. <textarea cols="30" rows="5">Aloha</textarea> 3. <script> 4. var body = document.body; 5. var selectors = 'input[type="text"], textarea'; 6. var onFocus = function (e) { e.target.select(); }; 7. delegator(body)('focusin', selectors, onFocus); 8. delegator(body)('focus', selectors, onFocus, true); 9. </script>
  • 19. Filtering a List Using input Event 19 1. <input id="filter" type="text"/> 2. <div id="output"></div> 3. <script> 4. var filter = document.querySelector('#filter'); 5. var output = document.querySelector('#output'); 6. var items = ['JS', 'JAVA', 'PHP', 'NODEJS']; 7. filter.addEventListener('input', function (e) { 8. output.textContent = items.filter(item => { 9. return item.indexOf(e.target.value) > -1; 10. }); 11. }); 12. </script>
  • 20. HTML Form submit and reset Events 20 1. <form id="atm" action="/transfer"> 2. <input id="pass" type="password"/> 3. <button type="submit">Enter</button> 4. <button type="reset">Clear</button> 5. </form> 6. <script> 7. var atm = document.querySelector('#atm'); 8. var logger = function (e) { console.log(e.type); }; 9. atm.addEventListener('submit', logger); 10. atm.addEventListener('reset', logger); 11. // 'reset', 'submit' 12. </script>
  • 22. Assigning Default Values 22 1. <form action="/order" method="post"> 2. Amount: <input id="amount" type="text"/> 3. <input id="dm" type="checkbox"/> Send me DM 4. <button type="submit">Save</button> 5. <button type="reset">Reset</button> 6. </form> 7. <script> 8. document.querySelector('#amount').value = 0; 9. document.querySelector('#dm').checked = true; 10. /* The input.value will be reset to empty after the Reset button has been clicked. Use input.defaultValue to assign a default value. Use input.defaultChecked for checkbox and radio */ 11. </script>
  • 23. Getting and Setting Values of Input Text and Textarea 23 1. <input id="name" type="text" value="Ben"/> 2. <textarea id="intro" cols="10" rows="5">Ben is a RD</textarea> 3. <script> 4. var name = document.querySelector('#name'); 5. var intro = document.querySelector('#intro'); 6. console.log(name.value); // 'Ben' 7. console.log(intro.value); // 'Ben is a RD' 8. name.value = 'Vicky'; 9. intro.value = 'Vicky is a VD'; 10. </script>
  • 24. Getting Values of Checked Checkboxes 24 1. <input name="order" id="1" type="checkbox" value="50" checked> 2. <label for="1">French fries</label> 3. <input name="order" id="2" type="checkbox" value="30" checked> 4. <label for="2">Sprite</label> 5. <script> 6. var selector = '[name="order"]:checked'; 7. var selected = document.querySelectorAll(selector); 8. var values = [...selected].map(elem => elem.value); 9. var total = values.reduce((a, b) => +a + +b); 10. console.log(total); // 80 11. </script>
  • 25. Setting checked to a Checkbox 25 1. <input id="enabled" type="checkbox" checked/> 2. <script> 3. var enabled = document.querySelector('#enabled'); 4. console.log(enabled.value); // 'on' 5. console.log(enabled.hasAttribute('checked')); // true 6. console.log(enabled.checked); // true 7. 8. enabled.checked = false; 9. console.log(enabled.hasAttribute('checked')); // true 10. console.log(enabled.getAttribute('checked')); // '' 11. </script>
  • 26. Getting and Setting Value of Radio Button Group 26 1. <form name="profile"> 2. <input name="gender" type="radio" value="M" checked/> Male 3. <input name="gender" type="radio" value="F"/> Female 4. </form> 5. <script> 6. var selector = '[name="gender"]:checked'; 7. var selected = document.querySelector(selector); 8. console.log(selected.value); // 'M' 9. console.log(document.forms.profile.gender.value); // 'M' 10. document.forms.profile.gender.value = 'F'; 11. </script>
  • 27. Getting Selected Value of a Select 27 1. <select id="lang"> 2. <option value="en-US">English</option> 3. <option value="zh-TW" selected>繁體中文</option> 4. </select> 5. <script> 6. var lang = document.querySelector('#lang'); 7. var options = lang.options; 8. console.log(lang.value); // 'zh-TW' 9. console.log(lang.selectedIndex); // 1 10. console.log(options[lang.selectedIndex].text); // '繁體中文' 11. lang.value = 'en-US'; 12. console.log(options[1].selected); // false 13. </script>
  • 28. Getting Selected Values of a Multiple Select 28 1. <select id="beverage" multiple> 2. <option value="tea" selected>Tea</option> 3. <option value="soda">Soda</option> 4. <option value="coffee" selected>Coffee</option> 5. </select> 6. <script> 7. var beverage = document.querySelector('#beverage'); 8. var options = drink.options; 9. var selected = [...options].filter(o => o.selected); 10. var values = selected.map(o => o.value); 11. console.log(values); // (2) ['tea', 'coffee'] 12. </script>
  • 29. Serializing Form Data - Snippet 1/2 29 1. <form id="edit"> 2. <input type="text" name="text" value="1"/> 3. <input type="checkbox" name="checkbox" value="2" checked/> 4. <input type="checkbox" name="checkbox" value="3" checked/> 5. <input type="radio" name="radio" value="4"/> 6. <input type="radio" name="radio" value="5" checked/> 7. <select name="select"> 8. <option value="6">6</option> 9. <option value="7" selected>7</option> 10. </select> 11. <textarea name="textarea" cols="30" rows="5">8</textarea> 12. <button type="submit">Submit</button> 13. </form>
  • 30. Serializing Form Data - Snippet 2/2 30 1. function serialize (form) { 2. var key, val, output = [...form.elements].map(elem => { 3. key = elem.name, val = elem.value; 4. if (elem.type === 'checkbox' || elem.type === 'radio') { 5. val = elem.checked ? val : null; 6. } 7. if (!key || val === null) { return false; } 8. return `${key}=${val}`; 9. }); 10. return output.filter(v => v).join('&'); 11. } 12. console.log(serialize(document.querySelector('#edit'))); 13. // 'text=1&checkbox=2&checkbox=3&radio=5&select=7&textarea=8'
  • 33. HTML <form> novalidate Attribute 33 1. <form action="/login" method="post" novalidate> 2. Username: <input name="user" type="text" required/> 3. Password: <input name="pass" type="password" required/> 4. <button type="submit">Sign In</button> 5. </form>
  • 34. Checking Required Fields 34 1. <form id="login" action="/login" method="post" novalidate> 2. Username: <input name="user" type="text" required/> 3. Password: <input name="pass" type="password" required/> 4. <button type="submit">Sign In</button> 5. </form> 6. <script> 7. var login = document.querySelector('#login'), required; 8. login.addEventListener('submit', function (e) { 9. required = document.querySelectorAll(':required'); 10. if ([...required].filter(el => !el.value).length) { 11. e.preventDefault(); 12. } 13. }); 14. </script>
  • 35. Preventing User From Typing Non-numeric Values 35 1. <input id="phone" type="text"/> 2. <script> 3. var phone = document.querySelector('#phone'); 4. phone.addEventListener('keypress', function (e) { 5. if (e.key && !/^[0-9]+$/.test(e.key)) { 6. e.preventDefault(); 7. } 8. }); 9. </script>
  • 36. Preventing Form Submission Using onsubmit Attribute 36 1. <form action="/login" onsubmit="return onSignin(event);"> 2. Username: <input id="user" type="text"/> 3. Password: <input id="pass" type="password"/> 4. <button type="submit">Sign In</button> 5. </form> 6. <script> 7. var user = document.querySelector('#user'); 8. var pass = document.querySelector('#pass'); 9. function onSignin (e) { 10. return !!user.value && !!pass.value; 11. } 12. </script>
  • 37. Preventing Form Submission Using Event Handler 37 1. <form id="login" action="/login"> 2. Username: <input id="user" type="text"/> 3. Password: <input id="pass" type="password"/> 4. <button type="submit">Sign In</button> 5. </form> 6. <script> 7. var login = document.querySelector('#login'); 8. var user = document.querySelector('#user'); 9. var pass = document.querySelector('#pass'); 10. login.addEventListener('submit', function onSignin (e) { 11. (!user.value || !pass.value) && e.preventDefault(); 12. }); 13. </script>
  • 39. Combo Box 39 Custom Components A combo box allows the user to type in a single-line input to limit the search, and select an item from a list of matched options. Combo box interaction specs ( incomplete ) : ● Click the caret button to open options ● Type keywords to filter options ● Arrow buttons to highlight an option ● Press enter to set value with the highlighted option ● Click cancel button to clear search
  • 40. 40 Date Picker The date picker contains the date input field and the calendar view. Users can either use the input field to type a date or by selecting a date in the calendar. Date picker interaction specs ( incomplete ) : ● Focus input to open a canlendar ● Press keyboard arrows to switch year, month, and date ● Click arrows to switch months ● Click a date to set value Custom Components
  • 43. AJAX 43 ● AJAX is an acronym for Asynchronous JavaScript and XML ● It is a web technique that allows for more interactivity by making web pages that fetch data in the background and alter themselves without reloading the entire page. ● A user can continue to use the application while the client program requests information from the server in the background. What’s AJAX?
  • 44. A Traditional Web Application 44 What’s AJAX? Client Server User Interface Web Server Data Beckend HTTP Request HTML + CSS + JS
  • 45. An AJAX Web Application 45 What’s AJAX? User Interface Web Server Data BeckendAJAX Engine Client Server HTTP Request JS Call Data Data (XML / TEXT / HTML / JSON)
  • 47. Making an AJAX Request 47 1. var xhr = new XMLHttpRequest(); 2. xhr.onreadystatechange = function () { 3. if (xhr.readyState === xhr.DONE && xhr.status === 200) { 4. console.log(xhr.responseText); 5. // <button id="{{id}}" type="button">{{action}}</button> 6. } 7. }; 8. xhr.open('get', '/templates/button.html', true); 9. xhr.send();
  • 48. Making a Synchronous Request 48 1. var xhr = new XMLHttpRequest(); 2. xhr.open('GET', '/data/cars.json', false); 3. xhr.send(); 4. console.log(xhr.responseText); 5. // '["audi","benz","bmw"]'
  • 49. Synchronous XMLHttpRequest makes the JavaScript stop executing until the server response is ready. If the server is busy or slow, the application will hang or stop. 49
  • 50. Wrapping XMLHttpRequest 50 1. function request (method, url, callback) { 2. var xhr = new XMLHttpRequest(); 3. xhr.onreadystatechange = function () { 4. if (xhr.readyState === xhr.DONE && xhr.status === 200) { 5. callback instanceof Function && callback(this); 6. } 7. }; 8. xhr.open(method, url, true); 9. return xhr; 10. } 11. /* Usage */ 12. // request('get', '/data/cars.json', (xhr) => { … }).send();
  • 51. Handling the Server Response 51 1. request('get', '/data/numbers.json', function (xhr) { 2. console.log(xhr.status); // 200 3. console.log(xhr.statusText); // 'OK' 4. console.log(xhr.responseText); // '[100,200,300]' 5. console.log(xhr.getResponseHeader('Content-type')); 6. // 'application/json' 7. }) 8. .send();
  • 52. Working with XML Data 52 1. /* Given a XML file 'food.xml' as follows: 2. <?xml version="1.0" encoding="UTF-8"?> 3. <root><food>Pizza</food><food>Bread</food></root> 4. */ 5. request('get', '/data/food.xml', function (xhr) { 6. var nodes = xhr.responseXML.getElementsByTagName('food'); 7. var data = [...nodes].map(node => node.textContent); 8. console.log(data); // (2) ['Pizza', 'Bread'] 9. }) 10. .send();
  • 53. Using POST Method in XMLHTTPRequest 53 1. var item = 'item=iphone'; 2. var amount = 'amount=99'; 3. var params = [item, amount].join('&'); 4. var contentType = 'application/x-www-form-urlencoded'; 5. var xhr = request('post', '/order', function (xhr) { 6. console.log(xhr.responseText); 7. // '{"data":{"item":"iphone","amount":"99"}}' 8. }); 9. xhr.setRequestHeader('Content-type', contentType); 10. xhr.send(params);
  • 54. Encoding a URI Component 54 1. var hello = '你好'; 2. var param = 'text=' + encodeURIComponent(hello); 3. var url = '/echo?' + param; 4. request('get', url, function (xhr) { 5. console.log(xhr.responseText); // '你好' 6. }) 7. .send();
  • 55. Uploading a File 55 1. <input id="file" type="file"/> 2. <script> 3. var file = document.querySelector('#file').files[0]; 4. var data = new FormData(); 5. var xhr = request('post', '/upload'); 6. data.append('target', 'images'); 7. data.append('file', file, 'sky.jpg'); 8. xhr.send(data); 9. </script>
  • 56. Monitoring Progress of a File Upload 56 1. var file = document.querySelector('#file').files[0]; 2. var data = new FormData(); 3. var xhr = request('post', '/upload'); 4. data.append('file', file); 5. xhr.upload.addEventListener('progress', function (e) { 6. if (e.lengthComputable) { 7. console.log(Math.floor(e.loaded / e.total * 100)); 8. } 9. }); 10. xhr.send(data);
  • 58. AJAX requests are forbidden by default by the same-origin policy. 58
  • 59. URL Outcome Reason http://www.abc.com/about/contact.html Success Same protocol, host and port http://www.abc.com/service/training.html Success Same protocol, host and port https://www.abc.com/member/login.html Failure Different protocol http://www.abc.com:8080/partners.html Failure Different port http://abc.com/blog/tags.html Failure Different host Same-origin Policy 59 The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. The following table gives examples of origin comparisons to the URL http://www.abc.com/about/index.html: Security
  • 60. Cross-Origin Resource Sharing CORS is a system, consisting of transmitting HTTP headers, that determines whether to block or fulfill requests for restricted resources on a web page from another domain outside the domain from which the resource originated. To allow any resource to access your resource, you can specify: Access-Control-Allow-Origin: * To allow https://www.abc.com to access your resource, you can specify: Access-Control-Allow-Origin: https://www.abc.com 60 Security
  • 61. JSON with Padding 61 JSONP is used to request data from a server residing in a different domain than the client. JSONP Client Server <script>function fn (data) { … }</script> <script src="https://api.su.com/users/9?callback=fn"></script> response.setHeader('Content-type', 'text/javascript'); response.send('fn({ "id": 9, "name": "Kyle" })');
  • 63. Polling 63 1. function Polling (options) { 2. this.url = options.url; 3. this.method = options.method || 'get'; 4. this.callback = options.callback || (() => {}); 5. this.delay = options.delay || 1000; 6. this.start(); 7. } 8. Polling.prototype.start = function () { 9. setTimeout(() => { 10. request(this.method, this.url, this.callback).send(); 11. this.start(); 12. }, this.delay); 13. };
  • 64. Checking Username Availability 64 1. var account = document.querySelector('input#account'); 2. var defer = function (fn) { 3. var timer; 4. return function (e) { 5. if (timer) { clearTimeout(timer); } 6. timer = setTimeout(() => fn.call(e.target, e), 300); 7. }; 8. }; 9. account.addEventListener('input', defer(function (e) { 10. request('get', '/api/users/check', () => {}); 11. }));
  • 65. You don’t need AJAX to download a file. 65
  • 66. Downloading a File 66 1. var url = 'https://locate/to/file'; 2. /* Solution 1 */ 3. location.assign(url); 4. 5. /* Solution 2 */ 6. window.open(url, '_blank'); 7. 8. /* Solution 3 (Better) */ 9. var iframe = document.createElement('iframe'); 10. iframe.style.display = 'none'; 11. iframe.src = url; 12. document.appendChild(iframe);
  • 67. Disable action buttons while requesting to prevent user from re-submitting the form. 67
  • 68. Disabling Submit Button When Request Is In-progress 68 1. var profile = document.querySelector('form#profile'); 2. var save = document.querySelector('[type="submit"]#save'); 3. profile.addEventListener('submit', function (e) { 4. e.preventDefault(); 5. request('post', 'submit', function (xhr) { 6. save.disabled = false; 7. }).send(); 8. save.disabled = true; 9. });
  • 69. Callback Hell 69 1. /* Suppose url1, url2, url3, and success are defined */ 2. request('get', url1, function (xhr) { 3. request('get', url2, function (xhr) { 4. request('get', url3, function (xhr) { 5. success(); 6. }); 7. }); 8. });
  • 70. Using Named Functions 70 1. /* Suppose url1, url2, url3, and success are defined */ 2. function doReq1 () { 3. request('get', url1, function () { doReq2(); }); 4. } 5. function doReq2 () { 6. request('get', url2, function () { doReq3(); }); 7. } 8. function doReq3 () { 9. request('get', url3, function () { success(); }); 10. } 11. doReq1();
  • 72. What’s a Promise? 72 A Promise is an object representing the eventual completion or failure of an asynchronous operation. – MDN Promise Promise .then(onFulfilled) .catch(onRejected) Promise … pending resolved rejected pending return
  • 73. Creating a Promise 73 1. new Promise(function (resolve, reject) { 2. setTimeout(() => resolve('Success!'), 1000); 3. }) 4. .then(function (message) { 5. console.log(message); // 'Success!' 6. return { message }; 7. }) 8. .then(function (data) { 9. console.log(data); // {message: 'Success!'} 10. }) 11. .catch(function (error) { 12. console.log(error); 13. });
  • 74. Chaining after a catch 74 1. new Promise((resolve, reject) => { 2. console.log('initialized'); 3. resolve(); 4. }) 5. .then(() => { 6. throw new Error('something failed'); 7. console.log('success'); 8. }) 9. .catch((error) => console.log('failure')) 10. .then(() => console.log('Whatever happened before')); 11. // 'initialized', 'failure', 'Whatever happened before'
  • 75. Wrapping AJAX Request with Promise 75 1. function ajax (method, url, data) { 2. return new Promise(function (resolve, reject) { 3. var xhr = new XMLHttpRequest(); 4. xhr.onreadystatechange = function () { 5. if (xhr.readyState === xhr.DONE) { 6. if (xhr.status === 200) { 7. resolve(JSON.parse(xhr.responseText)); 8. } else { reject(xhr.responseText); } 9. } 10. }; 11. xhr.open(method, url, true); 12. xhr.send(data); 13. }); 14. }
  • 76. Making a Request With the Enhanced Request Function 76 1. ajax('post', '/api/order', { item: 'ipad', amount: 99 }) 2. .then(function (data) { 3. console.log(data); 4. }) 5. .catch(function (error) { 6. console.error(error); 7. });
  • 77. Chaining Requests with Promises 77 1. /* Suppose url1, url2, url3, and success are defined */ 2. function doReq1 () { return ajax('get', url1); } 3. function doReq2 () { return ajax('get', url2); } 4. function doReq3 () { return ajax('get', url3); } 5. doReq1().then(doReq2).then(doReq3).then(success);
  • 78. The Promise.all() Method 78 1. Promise.all([ 2. ajax('get', '/data/hosts.json'), 3. ajax('get', '/data/users.json') 4. ]) 5. .then(function ([hosts, users]) { 6. console.log(hosts); 7. console.log(users); 8. }) 9. .catch(function (error) { 10. console.error(error); 11. });
  • 79. The fetch API 79 1. var data = new FormData(); 2. data.append('action', 'cancel'); 3. 4. fetch('/orders/1', { method: 'POST', body: data }) 5. .then(function (response) { 6. // response.ok bool 7. // response.status number 8. // response.headers Headers 9. // response.json() Promise 10. }) 11. .catch(function (error) {});
  • 81. Server-sent Events 81 SSE is a technology where a browser receives automatic updates from a server via HTTP connection. – Wiki Request Response Request Response Handshake Acknowledgement Server push Server push CLIENT SERVER Polling CLIENT SERVER Server-sent Event VS.
  • 82. Receiving Server-Sent Event Notifications 82 1. var es = new EventSource('http://localhost/stream'); 2. 3. es.addEventListener('open', function (e) { … }); 4. es.addEventListener('error', function (e) { … }); 5. es.addEventListener('message', function (e) { 6. console.log(JSON.parse(e.data)); 7. }); 8. es.addEventListener('custom-event', function (e) { 9. console.log(JSON.parse(e.data)); 10. });
  • 84. WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection. – Wiki What Is WebSocket? 84 WebSocket Request Response Request Response Handshake Acknowledgement Bi-directional messages Connection end CLIENT SERVER HTTP CLIENT SERVER WebSocket VS. Connection lifecycle Connection lifecycle
  • 85. Creating a WebSocket Object 85 1. var ws = new WebSocket('wss://localhost'); 2. 3. ws.addEventListener('open', function (e) { … }); 4. ws.addEventListener('error', function (e) { … }); 5. ws.addEventListener('message', function (e) { 6. console.log(JSON.parse(e.data)); 7. // { success: true, action: 'echo', data: 'Bye' } 8. ws.close(); 9. }; 10. ws.send(JSON.stringify({ action: 'echo', data: 'Bye' }));
  • 86. Reference 86 ● Ajax (programming) - Wikipedia ● CORS - Glossary | MDN ● Cross-origin resource sharing - Wikipedia ● GET vs POST - Difference and Comparison | Diffen ● JavaScript | MDN ● JSONP - Wikipedia Practical JavaScript Programming
  • 87. Reference ● Same-origin policy - Wikipedia ● Same-origin policy - Web security | MDN ● Server-sent events - Wikipedia ● WebSocket - Wikipedia 87 Practical JavaScript Programming