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

What's hot (20)

Обзор фреймворка Twisted
Обзор фреймворка Twisted
Maxim Kulsha
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
Visual Engineering
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
Denis Ristic
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
Visual Engineering
 
06 jQuery #burningkeyboards
06 jQuery #burningkeyboards
Denis Ristic
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Mobivery
 
ClojurianからみたElixir
ClojurianからみたElixir
Kent Ohashi
 
201104 iphone navigation-based apps
201104 iphone navigation-based apps
Javier Gonzalez-Sanchez
 
Specs2
Specs2
Piyush Mishra
 
Why ruby
Why ruby
rstankov
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
Eyal Vardi
 
Testing your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 
Ruby/Rails
Ruby/Rails
rstankov
 
Backbone js
Backbone js
rstankov
 
To Err Is Human
To Err Is Human
Alex Liu
 
Metaprogramming in ES6
Metaprogramming in ES6
Héctor Pablos López
 
JavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your Modules
Odoo
 
AngularJS: what is underneath the hood
AngularJS: what is underneath the hood
DA-14
 
안드로이드 세미나 2
안드로이드 세미나 2
ang0123dev
 
Обзор фреймворка Twisted
Обзор фреймворка Twisted
Maxim Kulsha
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
Visual Engineering
 
05 JavaScript #burningkeyboards
05 JavaScript #burningkeyboards
Denis Ristic
 
06 jQuery #burningkeyboards
06 jQuery #burningkeyboards
Denis Ristic
 
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Formacion en movilidad: Conceptos de desarrollo en iOS (IV)
Mobivery
 
ClojurianからみたElixir
ClojurianからみたElixir
Kent Ohashi
 
Component lifecycle hooks in Angular 2.0
Component lifecycle hooks in Angular 2.0
Eyal Vardi
 
Testing your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 
Ruby/Rails
Ruby/Rails
rstankov
 
Backbone js
Backbone js
rstankov
 
To Err Is Human
To Err Is Human
Alex Liu
 
JavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
Impact of the New ORM on Your Modules
Impact of the New ORM on Your Modules
Odoo
 
AngularJS: what is underneath the hood
AngularJS: what is underneath the hood
DA-14
 
안드로이드 세미나 2
안드로이드 세미나 2
ang0123dev
 

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

HTML Forms: The HTML element represents a document section containing interac...
HTML Forms: The HTML element represents a document section containing interac...
BINJAD1
 
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
BHSJangir
 
Web design - Working with forms in HTML
Web design - Working with forms in HTML
Mustafa Kamel Mohammadi
 
20-html-forms.ppt
20-html-forms.ppt
KarenCato1
 
11-html-forms.ppt
11-html-forms.ppt
karansingh4126
 
05 html-forms
05 html-forms
Palakshya
 
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
SooryaPrashanth1
 
html forms
html forms
ikram niaz
 
Html,Css and Javascript Forms using different tags
Html,Css and Javascript Forms using different tags
JeirahTigas
 
Html Forms.ppt
Html Forms.ppt
MAHASWETAMANDAL1
 
Html Forms for lecture BSIT SSC HCI LECTURE
Html Forms for lecture BSIT SSC HCI LECTURE
ChristopherYSabado
 
20 html-forms
20 html-forms
Kumar
 
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
RoselAAliganga
 
HTML FORMS.pptx
HTML FORMS.pptx
Sierranaijamusic
 
2. HTML forms
2. HTML forms
Pavle Đorđević
 
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
zhqysf
 
Html class-04
Html class-04
Md Ali Hossain
 
HtmlForms- basic HTML forms description.
HtmlForms- basic HTML forms description.
MohammadRafsunIslam
 
Web I - 04 - Forms
Web I - 04 - Forms
Randy Connolly
 
JavaScript
JavaScript
Bharti Gupta
 
HTML Forms: The HTML element represents a document section containing interac...
HTML Forms: The HTML element represents a document section containing interac...
BINJAD1
 
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
8741aad2f359a5ee62afdf4cc4341440 (1) (1) (1).pdf
BHSJangir
 
20-html-forms.ppt
20-html-forms.ppt
KarenCato1
 
05 html-forms
05 html-forms
Palakshya
 
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
11-html-forms.pptydy6rfyf6rrydyf6r6ryfydydyff
SooryaPrashanth1
 
Html,Css and Javascript Forms using different tags
Html,Css and Javascript Forms using different tags
JeirahTigas
 
Html Forms for lecture BSIT SSC HCI LECTURE
Html Forms for lecture BSIT SSC HCI LECTURE
ChristopherYSabado
 
20 html-forms
20 html-forms
Kumar
 
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
HYPERTEXT MARK UP LANGUAGES (HTML) FORMS
RoselAAliganga
 
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
New Perspectives on HTML and CSS Comprehensive 6th Edition Carey Test Bank
zhqysf
 
HtmlForms- basic HTML forms description.
HtmlForms- basic HTML forms description.
MohammadRafsunIslam
 
Ad

More from Wilson Su (7)

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

Recently uploaded (20)

Structural Design for Residential-to-Restaurant Conversion
Structural Design for Residential-to-Restaurant Conversion
DanielRoman285499
 
TEA2016AAT 160 W TV application design example
TEA2016AAT 160 W TV application design example
ssuser1be9ce
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Universal Human Values and professional ethics Quantum AKTU BVE401
Universal Human Values and professional ethics Quantum AKTU BVE401
Unknown
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
First Come First Serve Scheduling in real time operating system.pptx
First Come First Serve Scheduling in real time operating system.pptx
KavitaBagewadi2
 
Flow Chart Proses Bisnis prosscesss.docx
Flow Chart Proses Bisnis prosscesss.docx
rifka575530
 
David Boutry - Mentors Junior Developers
David Boutry - Mentors Junior Developers
David Boutry
 
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
Taqyea
 
Pavement and its types, Application of rigid and Flexible Pavements
Pavement and its types, Application of rigid and Flexible Pavements
Sakthivel M
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 
Understanding Amplitude Modulation : A Guide
Understanding Amplitude Modulation : A Guide
CircuitDigest
 
chemistry investigatory project for class 12
chemistry investigatory project for class 12
Susis10
 
Blood bank management system project report.pdf
Blood bank management system project report.pdf
Kamal Acharya
 
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Alexandra N. Martinez
 
How Binning Affects LED Performance & Consistency.pdf
How Binning Affects LED Performance & Consistency.pdf
Mina Anis
 
Engineering Mechanics Introduction and its Application
Engineering Mechanics Introduction and its Application
Sakthivel M
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
djiceramil
 
社内勉強会資料_Chain of Thought .
社内勉強会資料_Chain of Thought .
NABLAS株式会社
 
Structural Design for Residential-to-Restaurant Conversion
Structural Design for Residential-to-Restaurant Conversion
DanielRoman285499
 
TEA2016AAT 160 W TV application design example
TEA2016AAT 160 W TV application design example
ssuser1be9ce
 
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
Decoding Kotlin - Your Guide to Solving the Mysterious in Kotlin - Devoxx PL ...
João Esperancinha
 
Universal Human Values and professional ethics Quantum AKTU BVE401
Universal Human Values and professional ethics Quantum AKTU BVE401
Unknown
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-ABB Furse.pdf
djiceramil
 
First Come First Serve Scheduling in real time operating system.pptx
First Come First Serve Scheduling in real time operating system.pptx
KavitaBagewadi2
 
Flow Chart Proses Bisnis prosscesss.docx
Flow Chart Proses Bisnis prosscesss.docx
rifka575530
 
David Boutry - Mentors Junior Developers
David Boutry - Mentors Junior Developers
David Boutry
 
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
Center Enamel can Provide Aluminum Dome Roofs for diesel tank.docx
CenterEnamel
 
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
最新版美国圣莫尼卡学院毕业证(SMC毕业证书)原版定制
Taqyea
 
Pavement and its types, Application of rigid and Flexible Pavements
Pavement and its types, Application of rigid and Flexible Pavements
Sakthivel M
 
NALCO Green Anode Plant,Compositions of CPC,Pitch
NALCO Green Anode Plant,Compositions of CPC,Pitch
arpitprachi123
 
Understanding Amplitude Modulation : A Guide
Understanding Amplitude Modulation : A Guide
CircuitDigest
 
chemistry investigatory project for class 12
chemistry investigatory project for class 12
Susis10
 
Blood bank management system project report.pdf
Blood bank management system project report.pdf
Kamal Acharya
 
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Montreal Dreamin' 25 - Introduction to the MuleSoft AI Chain (MAC) Project
Alexandra N. Martinez
 
How Binning Affects LED Performance & Consistency.pdf
How Binning Affects LED Performance & Consistency.pdf
Mina Anis
 
Engineering Mechanics Introduction and its Application
Engineering Mechanics Introduction and its Application
Sakthivel M
 
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
362 Alec Data Center Solutions-Slysium Data Center-AUH-Adaptaflex.pdf
djiceramil
 
社内勉強会資料_Chain of Thought .
社内勉強会資料_Chain of Thought .
NABLAS株式会社
 

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 [email protected]
  • 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