Practical JavaScript Programming Session 6 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 11. ● What’s RegExp? ● Special Characters ● RegExp Flags ● Common Usage Regular Expression Chapter 12. Single Page Application ● What’s SPA? ● Build a Simple SPA ● Demo Chapter 13. RESTful Web Services ● What’s RESTful API? ● Build RESTful APIs ● Demo ● Testing Tools
Chapter 11. Regular Expression 5
What’s RegExp? 6
What’s Regular Expression? 7 A regular expression is, in theoretical computer science and formal language theory, a sequence of characters that define a search pattern. Usually this pattern is then used by string searching algorithms for "find" or "find and replace" operations on strings. – Wiki Regular Expression /^(([^<>()[].,;:s@"]+(.[^<>()[ ].,;:s@"]+)*)|(".+"))@(([[0-9]{1,3 }.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}] )|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/
Example Scenarios ● Test for a pattern within a string You can test an input string to see if a telephone number pattern or a credit card number pattern occurs within the string. ● Replace text You can use a regular expression to identify specific text in a document and either remove it completely or replace it with other text. ● Extract a substring from a string based upon a pattern match You can find specific text within a document or input value 8 What’s RegExp?
Working with Regular Expressions 9 What’s RegExp? Method Description regex.exec Executes a search for a match in a string. It returns an array of information or null on a mismatch. regex.test Tests for a match in a string. It returns true or false. string.match Executes a search for a match in a string. It returns an array of information or null on a mismatch. string.search Tests for a match in a string. It returns the index of the match, or -1 if the search fails. string.replace Executes a search for a match in a string, and replaces the matched substring with a replacement substring. string.split Uses a regular expression or a fixed string to break a string into an array of substrings.
Creating a RegExp Object With Ordinary Characters 1. /* Using a regular expression literal */ 2. var pattern1 = /earn/; 3. 4. /* Calling the RegExp constructor function */ 5. var pattern2 = new RegExp('ear'); 6. 7. pattern1.test('learn'); // true 8. pattern1.exec('learn'); // ['earn', index: 1, input: 'learn'] 9. 'learn'.search(pattern2); // 1 10. 'learn'.match(pattern2); // ['ear', index: 1, input: 'learn'] 11. 'learn'.split(pattern2); // (2) ['l', 'n'] 12. 'learn'.replace(pattern2, 'io'); // 'lion' 10
Special Characters 11
Alternation 12 1. /cat|dog/.test('cat'); // true 2. /cat|dog/.test('dog'); // true 3. /cat|dog/.test('two cats'); // true 4. /cat|dog/.test('xyz'); // false 5. /0|1|2|3|4|5|6|7|8|9/.test('3'); // true 6. /0|1|2|3|4|5|6|7|8|9/.test('12345'); // true 7. /0|1|2|3|4|5|6|7|8|9/.test('I’m 18.'); // true
Lists of Matching Characters 13 1. /[0123456789]/.test('5'); // true 2. /[0-9]/.test('5'); // true 3. /[0-9]/.test('Give me 5'); // true 4. /b[aeiou]t/.test('bot'); // true 5. 6. /[^13579]/.test('5'); // false 7. /[^13579]/.test('2'); // true 8. /[^13579]/.test('52'); // true 9. /[^13579]/.exec('52')[0]; // '2'
Metacharacters 14 Special Characters Metacharacter Meaning d Matches a digit character. Equivalent to [0-9]. D Matches a non-digit character. Equivalent to [^0-9]. w Matches any of the following characters: A-Z, a-z, 0-9, and underscore. Equivalent to [A-Za-z0-9_]. W Matches any character except A-Z, a-z, 0-9, and underscore. Equivalent to [^A-Za-z0-9_]. s Matches a single white space character, including space, tab, form feed, line feed. S Matches a single character other than white space. . Matches any single character except the newline character n.
Quantifiers 15 Special Characters Character Meaning {n} Matches exactly n times. n must be a positive integer. {n,} Matches at least n times. n must be a positive integer. {n,m} Matches at least n and at most m times. n and m must be positive integers, where n <= m. * Matches the preceding character or subexpression zero or more times. Equivalent to {0,}. + Matches the preceding character or subexpression one or more times. Equivalent to {1,}. ? Matches the preceding character or subexpression zero or one time. Equivalent to {0,1}.
Quantifiers 16 1. /[0-9]{5}/.test('123'); // false 2. /[0-9]{5}/.test('12345'); // true 3. /[0-9]{5}/.test('123456789'); // true 4. /[0-9]{5}/.exec('123456789')[0]; // '12345' 5. 6. /[0-9]{5,}/.test('123456789'); // true 7. /[0-9]{5,}/.exec('123456789')[0]; // '123456789' 8. 9. /[0-9]{3,5}/.test('12345'); // true 10. /[0-9]{3,5}/.test('123456789'); // true 11. /[0-9]{3,5}/.exec('123')[0]; // '123' 12. /[0-9]{3,5}/.exec('123456789')[0]; // '12345'
Quantifiers 17 1. /1000*/.test('10'); // false 2. /1000*/.test('100'); // true 3. /1000*/.test('100000'); // true 4. /1000*/.exec('100000')[0]; // '100000' 5. 6. /oh+!/.test('oh!'); // true 7. /oh+!/.test('ohhhh!'); // true 8. /oh+!/.exec('ohhhh!')[0]; // 'ohhhh!' 9. 10. /colou?r/.test('color'); // true 11. /colou?r/.test('colour'); // true
Anchors 18 1. /[a-z][a-z0-9]{3}/.test('0101moris'); // true 2. /^[a-z][a-z0-9]{3}/.test('0101moris'); // false 3. /^[a-z][a-z0-9]{3}/.test('liz'); // false 4. 5. /[A-Z]+!/.test('OMG! XXXX'); // true 6. /[A-Z]+!$/.test('OMG! XXXX'); // false 7. /[A-Z]+!$/.test('OMG!'); // true 8. 9. /^[A-Z][0-9]?$/.test('A'); // true 10. /^[A-Z][0-9]?$/.test('A2'); // true 11. /^[A-Z][0-9]?$/.test('A22'); // false
Anchors 19 1. /is/.test('Chris was a RD.'); // true 2. /bis/.test('Chris was a RD.'); // false 3. /bis/.test('a big issue'); // true 4. /bisb/.test('Chris is a VS.'); // true 5. 6. /Boo/.test('moon'); // true 7. /Boo/.exec('moon')[0]; // 'oo' 8. /Boo/.test('oops'); // false 9. /ooB/.test('oops'); // true 10. /o+B/.exec('ooooops')[0]; // 'ooooo'
Marking the Next Character as a Special Character 20 1. /d+/.test('3+'); // true 2. /^d+$/.test('3+'); // false 3. /^d+$/.test('3+'); // true 4. /^[d+]$/.test('[2]'); // false 5. /^[d+]$/.test('[2]'); // true 6. /[^^]/.test('^'); // false 7. //.test(''); // true
Using Parenthesized Substring Matches 21 1. var string = 'wowwwwww'; 2. var pattern = /wow(w*)/; 3. pattern.test(string); // true 4. pattern.exec(string)[0]; // 'wowwwwww' 5. pattern.exec(string)[1]; // 'wwwww'
RegExp Flags 22
Global Search 23 1. var string = 'book hook moon'; 2. var pattern1 = /w*oow*/; 3. var pattern2 = /w*oow*/g; 4. 5. string.match(pattern1); 6. // ['book', index: 0, input: 'book hook moon'] 7. 8. string.match(pattern2); 9. // (3) ['book', 'hook', 'moon']
Case-insensitive Search 24 1. var string = 'A123456789'; 2. var pattern1 = /[a-z]w{9}/; 3. var pattern2 = /[a-z]w{9}/i; 4. 5. pattern1.test(string); // false 6. pattern2.test(string); // true
Multi-line Search 25 1. var string = '#, Namern1, Sccotrn2, Rita'; 2. var pattern1 = /^d+,s*w+/g; 3. var pattern2 = /^d+,s*w+/m; 4. var pattern3 = /^d+,s*w+/gm; 5. 6. string.match(pattern1); // null 7. string.match(pattern2); 8. // ['1, Sccot', index: 9, input: '#, Name↵1, Sccot↵2, Rita] 9. string.match(pattern3); 10. // (2) ['1, Sccot', '2, Rita']
Do not use RegExp.$n on production. 26
Using $n with string.replace 27 1. var pattern = /(w+)s(w+)/; 2. var string = 'Pokemon GO'; 3. 4. /* This feature is non-standard */ 5. string.replace(pattern, '$2, $1!'); 6. // 'GO, Pokemon!' 7. 8. string.replace(pattern, (match, $1, $2) => `${$2}, ${$1}!`); 9. // 'GO, Pokemon!'
A JavaScript RegExp object is stateful. 28
A Javascript Regexp Object Is Stateful 29 1. var string = 'abc'; 2. var pattern = /w/g; 3. pattern.exec(string); // ['a', index: 0, input: 'abc'] 4. pattern.lastIndex; // 1 5. pattern.exec(string); // ['b', index: 1, input: 'abc'] 6. pattern.lastIndex; // 2 7. pattern.exec('xyz'); // ['z', index: 2, input: 'xyz'] 8. pattern.lastIndex; // 3 9. pattern.exec(string); // null 10. pattern.lastIndex; // 0
Specifies the Index at Which to Start the Next Match 30 1. var string = '#1 Doran#2 Alexn#3 Ray'; 2. var pattern = /#d+sw+/g; 3. pattern.lastIndex = string.lastIndexOf('n'); 4. pattern.exec(string); 5. // ['#3 Ray', index: 16, input: '#1 Dora↵#2 Alex↵#3 Ray']
regexp.exec VS. string.match 31 1. var string = '#1 Doran#2 Alex'; 2. var pattern1 = /#d+ (w+)/; 3. var pattern2 = /#d+ (w+)/g; 4. 5. pattern1.exec(string); // (2) ['#1 Dora', 'Dora'] 6. string.match(pattern1); // (2) ['#1 Dora', 'Dora'] 7. 8. pattern2.exec(string); // (2) ['#1 Dora', 'Dora'] 9. string.match(pattern2); // (2) ['#1 Dora', '#2 Alex']
Common Usage 32
Verifying User Inputs 33 1. var input = document.querySelector('input#id'); 2. var message = document.querySelector('div#message'); 3. var pattern = /^[a-z]d{9}$/i; 4. input.addEventListener('change', function (e) { 5. if (!pattern.test(e.value)) { 6. input.classList.add('invalid'); 7. message.textContent = 'Invalid format'; 8. } 9. });
Changing Date Format 34 1. var date = '07/26/2017'; 2. var pattern = /(dd)/(dd)/(dddd)/; 3. date.replace(pattern, (match, month, date, year) => { 4. return `${year}-${month}-${date}`; 5. }); 6. // '2017-07-26'
Extracting Substrings 35 1. var styles = '.btn { color: #222; background: #fff; }'; 2. var pattern = /([^s:]+)s*:s*([^;]+)/; 3. styles.match(new RegExp(pattern, 'g')).map((decl) => { 4. var [match, prop, value] = pattern.exec(decl); 5. return { prop, value }; 6. }); 7. // (2) [{ prop: 'color', value: '#222'}, { prop: 'background', value: '#fff'}]
Splitting a String Into an Array 36 1. var string = 'web html, css; js'; 2. var pattern = /[,;s]+/; 3. keywords.split(string); // (4) ['web', 'html', 'css', 'js']
Some people, when confronted with a problem, think "I know, I’ll use regular expressions." Now they have two problems. - Jamie Zawinski 37
Chapter 12. Single-page Application 38
What’s SPA? 39
What’s SPA? 40 Single-page Application A single-page application, or SPA for short, is a web application that fits on a single web page with the goal of providing a user experience similar to that of a desktop application. In an SPA, either all necessary code – HTML, JavaScript, and CSS – is retrieved with a single page load, or the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions. – Wiki
Why SPA? 41 What’s SPA? ✓ Speeds up the loading of secondary pages ✓ Reduced number of resource requests ✓ Better mobile device experience ✓ Oriented on the apps with a big amount of interactive client-side code ✓ Easier state tracking ✗ Speed of initial load can be slow ✗ Complexity of navigation ✗ Not as SEO-friendly as desired ✗ An SPA model breaks the browser's design for page history navigation ✗ An SPA will have to call a function to update the analytics package Pros Cons
Technical Approaches 42 What’s SPA? AJAX WebSocket Server-sent Event JavaScript MeteorAngularJS Vue.js JavaScript Frameworks …React
The onhashchange Event 43 1. var view = document.querySelector('#view'); 2. function render (page) { 3. ajax('get', `/views/${page}.html`).then(html => { 4. view.innerHTML = html; 5. }); 6. } 7. window.addEventListener('hashchange', function (e) { 8. render(location.hash.slice(2)); 9. }); 10. location.hash = '/home'; 11. console.log(location.hash); // '#/home'
Using UI Router for URL Routing 44 1. const router = require('3rd-party-ui-router'); 2. router 3. .when('/home', () => { /* Displays home page. */ }) 4. .when('/posts', () => { /* Displays posts. */ }) 5. .when('/posts/:id', () => { /* Displays a post detail. */ }) 6. .otherwise('/home');
Build a Simple SPA 45
AngularJS 46 Data Binding Eases Testing MVVM Dependency Injection Routing Validations https://angularjs.org/
SPA URL Design 47 Build a Simple SPA Todos Create Detail Edit Title Notes Create porro tepa Title laboriosam mollitia et enim quasi adipisci quia Notes Save porro tepa laboriosam mollitia et enim quasi adipisci quia provident illum /todos/:id/edit/todos/:id/todos/create/todos
Project Structure 48 Build a Simple SPA Project components todos index.js index.html create.html detail.html edit.html app.js styles.css index.html Displays todo list Displays a form for creating a new todo Displays a todo detail Displays a form for editing a todo Todo list module Entry point Main page
/index.html 49 1. <!DOCTYPE html> 2. <html ng-app="app"> 3. <head> 4. <link rel="stylesheet" href="styles.css"> 5. <title>Build a Simple SPA</title> 6. </head> 7. <body> 8. <div ng-view class="view"></div> 9. <script src="https://cdnjs.com/angular.js"></script> 10. <script src="https://cdnjs.com/angular-route.js"></script> 11. <script src="components/todos/index.js"></script> 12. <script src="app.js"></script> 13. </body> 14. </html>
/components/todos/index.js - module.config 50 1. var todos = angular.module('todos', ['ngRoute']); 2. todos.config(function ($routeProvider) { 3. $routeProvider.when('/todos', { 4. templateUrl: 'components/todos/index.html', 5. controller: 'TodosCtrl', 6. resolve: { 7. todolist: (todos) => todos.init() 8. } 9. }) 10. .otherwise('/todos'); 11. });
/components/todos/index.js - module.service 51 1. todos.service('todos', function ($q, $timeout) { 2. this.data = []; 3. this.loaded = false; 4. this.query = function () { 5. let defer = $q.defer(); 6. $timeout(() => { 7. this.data = [{ id: 1, title: 'delectus', … }, … ]; 8. defer.resolve(this.data); 9. }, 1000); 10. return defer.promise; 11. }; 12. });
/components/todos/index.js - module.controller 52 1. todos.controller('TodosCreateCtrl', function ($scope, $location, todos) { 2. $scope.todos = todos; 3. $scope.starred = false; 4. $scope.create = function () { 5. todos.create({ 6. title: $scope.title, 7. notes: $scope.notes, 8. starred: $scope.starred 9. }) 10. .then(() => $location.path('#!/')); 11. }; 12. });
/components/todos/index.html 53 1. <h2 class="title"> 2. Todos <a class="btn" href="#!/todos/create">&#x271b;</a> 3. </h2> 4. <ul class="tasks"> 5. <li ng-repeat="todo in todos.data" 6. ng-class="{done:todo.done}"> 7. <input type="checkbox" ng-checked="todo.done" 8. ng-model="todo.done"> 9. <span class="star" 10. ng-class="{starred:todo.starred}">&#x2605;</span> 11. <a ng-bind="todo.title" ng-href="#!/todos/{{todo.id}}"></a> 12. </li> 13. </ul>
/app.js 54 1. angular.module('app', [ 2. 'todos' 3. ]);
Demo https://spa-wilson-su.c9users.io/ 55
Chapter 13. RESTful Web Services 56
What’s RESTful API? 57
What’s RESTful API? 58 Representational state transfer or RESTful web services is a way of providing interoperability between computer systems on the Internet. REST-compliant Web services allow requesting systems to access and manipulate textual representations of Web resources using a uniform and predefined set of stateless operations. – Wiki RESTful Web Services
Architectural Constraints 59 What’s RESTful API? Client-Server Statelessness Cacheable Uniform interface Layered system Code-on-demand (optional)
Relationship Between URL and HTTP Methods 60 What’s RESTful API? Collection, such as https://api.data.com/items/ Element, such as https://api.data.com/items/1 GET List the URIs and perhaps other details of the collection's members. Retrieve a representation of the addressed member of the collection, expressed in an appropriate Internet media type. POST Create a new entry in the collection. The new entry's URI is assigned automatically and is usually returned by the operation Not generally used. Treat the addressed member as a collection in its own right and create a new entry within it. PUT Replace the entire collection with another collection. Replace the addressed member of the collection, or if it does not exist, create it. DELETE Delete the entire collection. Delete the addressed member of the collection.
Testing Online REST API Using jQuery 1. var host = 'https://jsonplaceholder.typicode.com'; 2. var data = { userId: 2, title: 'Aloha' }; 3. 4. $.get(`${host}/todos/1`).then((response) => { 5. console.log(response); 6. // {userId: 1, id: 1, title: "delecus au", completed: false} 7. }); 8. 9. $.post(`${host}/todos`, data).then((response) => { 10. console.log(response); 11. // {userId: 2, title: "Aloha", id: 201} 12. }); 61
Build RESTful APIs 62
63 Node.js https://nodejs.org/
Installing Node.js on Debian and Ubuntu 64 $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - $ sudo apt-get install -y nodejs
RESTful API 65 Build RESTful APIs GET https://api-wilson-su.c9users.io/api/todos/ POST https://api-wilson-su.c9users.io/api/todos/ GET https://api-wilson-su.c9users.io/api/todos/:id PUT https://api-wilson-su.c9users.io/api/todos/:id
Creating a Project Folder 66 $ mkdir spa $ cd spa $ touch server.js $ npm init
Creating a Server 67 1. var http = require('http'); 2. http.createServer(function (request, response) { 3. response.writeHead(200, { 'Content-Type': 'text/plain' }); 4. response.write('Hello Node.js!'); 5. response.end(); 6. }) 7. .listen(8080, function () { 8. console.log('Listening on port 8080'); 9. });
Running the Server 68 $ node server.js Listening on 8080
Handling Requests 69 1. var http = require('http'); 2. var url = require('url'); 3. http.createServer(function (request, response) { 4. var pathname = url.parse(request.url, true).pathname; 5. if (//todos/.test(pathname)) { … } 6. else if (//todos/d+/.test(pathname)) { … } 7. else { … } 8. }) 9. .listen(8080);
70 Express http://expressjs.com/
Using Express Web Framework 71 1. /* Install Express in `api` directory: 2. `npm install express --save` */ 3. var express = require('express'); 4. var app = express(); 5. var port = 8080; 6. app.get('/', function (request, response) {}); 7. app.get('/todos', function (request, response) {}); 8. app.post('/todos', function (request, response) {}); 9. app.listen(port, function (err) { 10. console.log('Listening on port ' + port); 11. });
Using Express Router - /routes/todos.js 72 1. var express = require('express'); 2. var router = express.Router(); 3. router.get('/todos', function (req, res) {}); 4. router.post('/todos', function (req, res) {}); 5. router.get('/todos/:id', function (req, res) {}); 6. router.put('/todos/:id', function (req, res) {}); 7. module.exports = router;
Mounting the Specified Middleware 73 1. var express = require('express'); 2. var bodyParser = require('body-parser'); 3. var app = express(); 4. var port = 8080; 5. app.use(function (req, res, next) { 6. res.setHeader('Access-Control-Allow-Origin', '*'); 7. next(); 8. }); 9. app.use(bodyParser.json()); 10. app.use('/', require('./routes/todos')); 11. app.listen(port, function (err) { 12. console.log('Listening on port ' + port); 13. });
Handling Response - GET /todos/:id 74 1. var file = path.resolve(__dirname, '../data/todos.json'); 2. router.get('/todos/:id', function(req, res) { 3. fs.readFile(file, (err, text) => { 4. if (err) { throw err; } 5. var todos = JSON.parse(text); 6. var id = Number(req.params.id); 7. var todo = todos.find(v => v.id === id); 8. if (!todo) { return res.status(404).json(null); } 9. res.status(200).json(todo); 10. }); 11. });
/data/todos.json 75 1. [{ 2. "id": 1, 3. "title": "delectus aut autem", 4. "notes": "", 5. "done": false, 6. "starred": false 7. }, { 8. "id": 2, 9. "title": "quis ut nam facilis et officia qui", 10. "notes": "quo adipisci enim quam ut ab", 11. "done": true, 12. "starred": true 13. }]
Demo 76
Testing Tools 77
Testing APIs Using cURL 78 $ curl "http://localhost/api/todos" $ curl "http://localhost/api/todos/1" $ curl -d "title=Water" "http://localhost/api/todos"
79 jQuery https://jquery.com/
80 Postman https://www.getpostman.com/
81 Postman https://www.getpostman.com/
Sample Codes 82 Practical JavaScript Programming SPA API https://github.com/sweekson/tm-etp-spa https://github.com/sweekson/tm-etp-api
Reference 83 ● Regular expression - Wikipedia ● Regular Expressions - JavaScript | MDN ● Representational state transfer - Wikipedia ● Single-page application - Wikipedia ● Uses for Regular Expressions | MSDN Practical JavaScript Programming
Questions? 84
THANKS

Practical JavaScript Programming - Session 6/8

  • 1.
  • 2.
  • 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 Chapter11. ● What’s RegExp? ● Special Characters ● RegExp Flags ● Common Usage Regular Expression Chapter 12. Single Page Application ● What’s SPA? ● Build a Simple SPA ● Demo Chapter 13. RESTful Web Services ● What’s RESTful API? ● Build RESTful APIs ● Demo ● Testing Tools
  • 5.
  • 6.
  • 7.
    What’s Regular Expression? 7 Aregular expression is, in theoretical computer science and formal language theory, a sequence of characters that define a search pattern. Usually this pattern is then used by string searching algorithms for "find" or "find and replace" operations on strings. – Wiki Regular Expression /^(([^<>()[].,;:s@"]+(.[^<>()[ ].,;:s@"]+)*)|(".+"))@(([[0-9]{1,3 }.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}] )|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/
  • 8.
    Example Scenarios ● Testfor a pattern within a string You can test an input string to see if a telephone number pattern or a credit card number pattern occurs within the string. ● Replace text You can use a regular expression to identify specific text in a document and either remove it completely or replace it with other text. ● Extract a substring from a string based upon a pattern match You can find specific text within a document or input value 8 What’s RegExp?
  • 9.
    Working with RegularExpressions 9 What’s RegExp? Method Description regex.exec Executes a search for a match in a string. It returns an array of information or null on a mismatch. regex.test Tests for a match in a string. It returns true or false. string.match Executes a search for a match in a string. It returns an array of information or null on a mismatch. string.search Tests for a match in a string. It returns the index of the match, or -1 if the search fails. string.replace Executes a search for a match in a string, and replaces the matched substring with a replacement substring. string.split Uses a regular expression or a fixed string to break a string into an array of substrings.
  • 10.
    Creating a RegExpObject With Ordinary Characters 1. /* Using a regular expression literal */ 2. var pattern1 = /earn/; 3. 4. /* Calling the RegExp constructor function */ 5. var pattern2 = new RegExp('ear'); 6. 7. pattern1.test('learn'); // true 8. pattern1.exec('learn'); // ['earn', index: 1, input: 'learn'] 9. 'learn'.search(pattern2); // 1 10. 'learn'.match(pattern2); // ['ear', index: 1, input: 'learn'] 11. 'learn'.split(pattern2); // (2) ['l', 'n'] 12. 'learn'.replace(pattern2, 'io'); // 'lion' 10
  • 11.
  • 12.
    Alternation 12 1. /cat|dog/.test('cat'); //true 2. /cat|dog/.test('dog'); // true 3. /cat|dog/.test('two cats'); // true 4. /cat|dog/.test('xyz'); // false 5. /0|1|2|3|4|5|6|7|8|9/.test('3'); // true 6. /0|1|2|3|4|5|6|7|8|9/.test('12345'); // true 7. /0|1|2|3|4|5|6|7|8|9/.test('I’m 18.'); // true
  • 13.
    Lists of MatchingCharacters 13 1. /[0123456789]/.test('5'); // true 2. /[0-9]/.test('5'); // true 3. /[0-9]/.test('Give me 5'); // true 4. /b[aeiou]t/.test('bot'); // true 5. 6. /[^13579]/.test('5'); // false 7. /[^13579]/.test('2'); // true 8. /[^13579]/.test('52'); // true 9. /[^13579]/.exec('52')[0]; // '2'
  • 14.
    Metacharacters 14 Special Characters Metacharacter Meaning dMatches a digit character. Equivalent to [0-9]. D Matches a non-digit character. Equivalent to [^0-9]. w Matches any of the following characters: A-Z, a-z, 0-9, and underscore. Equivalent to [A-Za-z0-9_]. W Matches any character except A-Z, a-z, 0-9, and underscore. Equivalent to [^A-Za-z0-9_]. s Matches a single white space character, including space, tab, form feed, line feed. S Matches a single character other than white space. . Matches any single character except the newline character n.
  • 15.
    Quantifiers 15 Special Characters Character Meaning {n}Matches exactly n times. n must be a positive integer. {n,} Matches at least n times. n must be a positive integer. {n,m} Matches at least n and at most m times. n and m must be positive integers, where n <= m. * Matches the preceding character or subexpression zero or more times. Equivalent to {0,}. + Matches the preceding character or subexpression one or more times. Equivalent to {1,}. ? Matches the preceding character or subexpression zero or one time. Equivalent to {0,1}.
  • 16.
    Quantifiers 16 1. /[0-9]{5}/.test('123'); //false 2. /[0-9]{5}/.test('12345'); // true 3. /[0-9]{5}/.test('123456789'); // true 4. /[0-9]{5}/.exec('123456789')[0]; // '12345' 5. 6. /[0-9]{5,}/.test('123456789'); // true 7. /[0-9]{5,}/.exec('123456789')[0]; // '123456789' 8. 9. /[0-9]{3,5}/.test('12345'); // true 10. /[0-9]{3,5}/.test('123456789'); // true 11. /[0-9]{3,5}/.exec('123')[0]; // '123' 12. /[0-9]{3,5}/.exec('123456789')[0]; // '12345'
  • 17.
    Quantifiers 17 1. /1000*/.test('10'); //false 2. /1000*/.test('100'); // true 3. /1000*/.test('100000'); // true 4. /1000*/.exec('100000')[0]; // '100000' 5. 6. /oh+!/.test('oh!'); // true 7. /oh+!/.test('ohhhh!'); // true 8. /oh+!/.exec('ohhhh!')[0]; // 'ohhhh!' 9. 10. /colou?r/.test('color'); // true 11. /colou?r/.test('colour'); // true
  • 18.
    Anchors 18 1. /[a-z][a-z0-9]{3}/.test('0101moris'); //true 2. /^[a-z][a-z0-9]{3}/.test('0101moris'); // false 3. /^[a-z][a-z0-9]{3}/.test('liz'); // false 4. 5. /[A-Z]+!/.test('OMG! XXXX'); // true 6. /[A-Z]+!$/.test('OMG! XXXX'); // false 7. /[A-Z]+!$/.test('OMG!'); // true 8. 9. /^[A-Z][0-9]?$/.test('A'); // true 10. /^[A-Z][0-9]?$/.test('A2'); // true 11. /^[A-Z][0-9]?$/.test('A22'); // false
  • 19.
    Anchors 19 1. /is/.test('Chris wasa RD.'); // true 2. /bis/.test('Chris was a RD.'); // false 3. /bis/.test('a big issue'); // true 4. /bisb/.test('Chris is a VS.'); // true 5. 6. /Boo/.test('moon'); // true 7. /Boo/.exec('moon')[0]; // 'oo' 8. /Boo/.test('oops'); // false 9. /ooB/.test('oops'); // true 10. /o+B/.exec('ooooops')[0]; // 'ooooo'
  • 20.
    Marking the NextCharacter as a Special Character 20 1. /d+/.test('3+'); // true 2. /^d+$/.test('3+'); // false 3. /^d+$/.test('3+'); // true 4. /^[d+]$/.test('[2]'); // false 5. /^[d+]$/.test('[2]'); // true 6. /[^^]/.test('^'); // false 7. //.test(''); // true
  • 21.
    Using Parenthesized SubstringMatches 21 1. var string = 'wowwwwww'; 2. var pattern = /wow(w*)/; 3. pattern.test(string); // true 4. pattern.exec(string)[0]; // 'wowwwwww' 5. pattern.exec(string)[1]; // 'wwwww'
  • 22.
  • 23.
    Global Search 23 1. varstring = 'book hook moon'; 2. var pattern1 = /w*oow*/; 3. var pattern2 = /w*oow*/g; 4. 5. string.match(pattern1); 6. // ['book', index: 0, input: 'book hook moon'] 7. 8. string.match(pattern2); 9. // (3) ['book', 'hook', 'moon']
  • 24.
    Case-insensitive Search 24 1. varstring = 'A123456789'; 2. var pattern1 = /[a-z]w{9}/; 3. var pattern2 = /[a-z]w{9}/i; 4. 5. pattern1.test(string); // false 6. pattern2.test(string); // true
  • 25.
    Multi-line Search 25 1. varstring = '#, Namern1, Sccotrn2, Rita'; 2. var pattern1 = /^d+,s*w+/g; 3. var pattern2 = /^d+,s*w+/m; 4. var pattern3 = /^d+,s*w+/gm; 5. 6. string.match(pattern1); // null 7. string.match(pattern2); 8. // ['1, Sccot', index: 9, input: '#, Name↵1, Sccot↵2, Rita] 9. string.match(pattern3); 10. // (2) ['1, Sccot', '2, Rita']
  • 26.
    Do not useRegExp.$n on production. 26
  • 27.
    Using $n withstring.replace 27 1. var pattern = /(w+)s(w+)/; 2. var string = 'Pokemon GO'; 3. 4. /* This feature is non-standard */ 5. string.replace(pattern, '$2, $1!'); 6. // 'GO, Pokemon!' 7. 8. string.replace(pattern, (match, $1, $2) => `${$2}, ${$1}!`); 9. // 'GO, Pokemon!'
  • 28.
  • 29.
    A Javascript RegexpObject Is Stateful 29 1. var string = 'abc'; 2. var pattern = /w/g; 3. pattern.exec(string); // ['a', index: 0, input: 'abc'] 4. pattern.lastIndex; // 1 5. pattern.exec(string); // ['b', index: 1, input: 'abc'] 6. pattern.lastIndex; // 2 7. pattern.exec('xyz'); // ['z', index: 2, input: 'xyz'] 8. pattern.lastIndex; // 3 9. pattern.exec(string); // null 10. pattern.lastIndex; // 0
  • 30.
    Specifies the Indexat Which to Start the Next Match 30 1. var string = '#1 Doran#2 Alexn#3 Ray'; 2. var pattern = /#d+sw+/g; 3. pattern.lastIndex = string.lastIndexOf('n'); 4. pattern.exec(string); 5. // ['#3 Ray', index: 16, input: '#1 Dora↵#2 Alex↵#3 Ray']
  • 31.
    regexp.exec VS. string.match 31 1.var string = '#1 Doran#2 Alex'; 2. var pattern1 = /#d+ (w+)/; 3. var pattern2 = /#d+ (w+)/g; 4. 5. pattern1.exec(string); // (2) ['#1 Dora', 'Dora'] 6. string.match(pattern1); // (2) ['#1 Dora', 'Dora'] 7. 8. pattern2.exec(string); // (2) ['#1 Dora', 'Dora'] 9. string.match(pattern2); // (2) ['#1 Dora', '#2 Alex']
  • 32.
  • 33.
    Verifying User Inputs 33 1.var input = document.querySelector('input#id'); 2. var message = document.querySelector('div#message'); 3. var pattern = /^[a-z]d{9}$/i; 4. input.addEventListener('change', function (e) { 5. if (!pattern.test(e.value)) { 6. input.classList.add('invalid'); 7. message.textContent = 'Invalid format'; 8. } 9. });
  • 34.
    Changing Date Format 34 1.var date = '07/26/2017'; 2. var pattern = /(dd)/(dd)/(dddd)/; 3. date.replace(pattern, (match, month, date, year) => { 4. return `${year}-${month}-${date}`; 5. }); 6. // '2017-07-26'
  • 35.
    Extracting Substrings 35 1. varstyles = '.btn { color: #222; background: #fff; }'; 2. var pattern = /([^s:]+)s*:s*([^;]+)/; 3. styles.match(new RegExp(pattern, 'g')).map((decl) => { 4. var [match, prop, value] = pattern.exec(decl); 5. return { prop, value }; 6. }); 7. // (2) [{ prop: 'color', value: '#222'}, { prop: 'background', value: '#fff'}]
  • 36.
    Splitting a StringInto an Array 36 1. var string = 'web html, css; js'; 2. var pattern = /[,;s]+/; 3. keywords.split(string); // (4) ['web', 'html', 'css', 'js']
  • 37.
    Some people, whenconfronted with a problem, think "I know, I’ll use regular expressions." Now they have two problems. - Jamie Zawinski 37
  • 38.
  • 39.
  • 40.
    What’s SPA? 40 Single-page Application Asingle-page application, or SPA for short, is a web application that fits on a single web page with the goal of providing a user experience similar to that of a desktop application. In an SPA, either all necessary code – HTML, JavaScript, and CSS – is retrieved with a single page load, or the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions. – Wiki
  • 41.
    Why SPA? 41 What’s SPA? ✓Speeds up the loading of secondary pages ✓ Reduced number of resource requests ✓ Better mobile device experience ✓ Oriented on the apps with a big amount of interactive client-side code ✓ Easier state tracking ✗ Speed of initial load can be slow ✗ Complexity of navigation ✗ Not as SEO-friendly as desired ✗ An SPA model breaks the browser's design for page history navigation ✗ An SPA will have to call a function to update the analytics package Pros Cons
  • 42.
    Technical Approaches 42 What’s SPA? AJAXWebSocket Server-sent Event JavaScript MeteorAngularJS Vue.js JavaScript Frameworks …React
  • 43.
    The onhashchange Event 43 1.var view = document.querySelector('#view'); 2. function render (page) { 3. ajax('get', `/views/${page}.html`).then(html => { 4. view.innerHTML = html; 5. }); 6. } 7. window.addEventListener('hashchange', function (e) { 8. render(location.hash.slice(2)); 9. }); 10. location.hash = '/home'; 11. console.log(location.hash); // '#/home'
  • 44.
    Using UI Routerfor URL Routing 44 1. const router = require('3rd-party-ui-router'); 2. router 3. .when('/home', () => { /* Displays home page. */ }) 4. .when('/posts', () => { /* Displays posts. */ }) 5. .when('/posts/:id', () => { /* Displays a post detail. */ }) 6. .otherwise('/home');
  • 45.
  • 46.
    AngularJS 46 Data Binding Eases Testing MVVM DependencyInjection Routing Validations https://angularjs.org/
  • 47.
    SPA URL Design 47 Builda Simple SPA Todos Create Detail Edit Title Notes Create porro tepa Title laboriosam mollitia et enim quasi adipisci quia Notes Save porro tepa laboriosam mollitia et enim quasi adipisci quia provident illum /todos/:id/edit/todos/:id/todos/create/todos
  • 48.
    Project Structure 48 Build aSimple SPA Project components todos index.js index.html create.html detail.html edit.html app.js styles.css index.html Displays todo list Displays a form for creating a new todo Displays a todo detail Displays a form for editing a todo Todo list module Entry point Main page
  • 49.
    /index.html 49 1. <!DOCTYPE html> 2.<html ng-app="app"> 3. <head> 4. <link rel="stylesheet" href="styles.css"> 5. <title>Build a Simple SPA</title> 6. </head> 7. <body> 8. <div ng-view class="view"></div> 9. <script src="https://cdnjs.com/angular.js"></script> 10. <script src="https://cdnjs.com/angular-route.js"></script> 11. <script src="components/todos/index.js"></script> 12. <script src="app.js"></script> 13. </body> 14. </html>
  • 50.
    /components/todos/index.js - module.config 50 1.var todos = angular.module('todos', ['ngRoute']); 2. todos.config(function ($routeProvider) { 3. $routeProvider.when('/todos', { 4. templateUrl: 'components/todos/index.html', 5. controller: 'TodosCtrl', 6. resolve: { 7. todolist: (todos) => todos.init() 8. } 9. }) 10. .otherwise('/todos'); 11. });
  • 51.
    /components/todos/index.js - module.service 51 1.todos.service('todos', function ($q, $timeout) { 2. this.data = []; 3. this.loaded = false; 4. this.query = function () { 5. let defer = $q.defer(); 6. $timeout(() => { 7. this.data = [{ id: 1, title: 'delectus', … }, … ]; 8. defer.resolve(this.data); 9. }, 1000); 10. return defer.promise; 11. }; 12. });
  • 52.
    /components/todos/index.js - module.controller 52 1.todos.controller('TodosCreateCtrl', function ($scope, $location, todos) { 2. $scope.todos = todos; 3. $scope.starred = false; 4. $scope.create = function () { 5. todos.create({ 6. title: $scope.title, 7. notes: $scope.notes, 8. starred: $scope.starred 9. }) 10. .then(() => $location.path('#!/')); 11. }; 12. });
  • 53.
    /components/todos/index.html 53 1. <h2 class="title"> 2.Todos <a class="btn" href="#!/todos/create">&#x271b;</a> 3. </h2> 4. <ul class="tasks"> 5. <li ng-repeat="todo in todos.data" 6. ng-class="{done:todo.done}"> 7. <input type="checkbox" ng-checked="todo.done" 8. ng-model="todo.done"> 9. <span class="star" 10. ng-class="{starred:todo.starred}">&#x2605;</span> 11. <a ng-bind="todo.title" ng-href="#!/todos/{{todo.id}}"></a> 12. </li> 13. </ul>
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
    What’s RESTful API? 58 Representationalstate transfer or RESTful web services is a way of providing interoperability between computer systems on the Internet. REST-compliant Web services allow requesting systems to access and manipulate textual representations of Web resources using a uniform and predefined set of stateless operations. – Wiki RESTful Web Services
  • 59.
    Architectural Constraints 59 What’s RESTfulAPI? Client-Server Statelessness Cacheable Uniform interface Layered system Code-on-demand (optional)
  • 60.
    Relationship Between URLand HTTP Methods 60 What’s RESTful API? Collection, such as https://api.data.com/items/ Element, such as https://api.data.com/items/1 GET List the URIs and perhaps other details of the collection's members. Retrieve a representation of the addressed member of the collection, expressed in an appropriate Internet media type. POST Create a new entry in the collection. The new entry's URI is assigned automatically and is usually returned by the operation Not generally used. Treat the addressed member as a collection in its own right and create a new entry within it. PUT Replace the entire collection with another collection. Replace the addressed member of the collection, or if it does not exist, create it. DELETE Delete the entire collection. Delete the addressed member of the collection.
  • 61.
    Testing Online RESTAPI Using jQuery 1. var host = 'https://jsonplaceholder.typicode.com'; 2. var data = { userId: 2, title: 'Aloha' }; 3. 4. $.get(`${host}/todos/1`).then((response) => { 5. console.log(response); 6. // {userId: 1, id: 1, title: "delecus au", completed: false} 7. }); 8. 9. $.post(`${host}/todos`, data).then((response) => { 10. console.log(response); 11. // {userId: 2, title: "Aloha", id: 201} 12. }); 61
  • 62.
  • 63.
  • 64.
    Installing Node.js onDebian and Ubuntu 64 $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - $ sudo apt-get install -y nodejs
  • 65.
    RESTful API 65 Build RESTfulAPIs GET https://api-wilson-su.c9users.io/api/todos/ POST https://api-wilson-su.c9users.io/api/todos/ GET https://api-wilson-su.c9users.io/api/todos/:id PUT https://api-wilson-su.c9users.io/api/todos/:id
  • 66.
    Creating a ProjectFolder 66 $ mkdir spa $ cd spa $ touch server.js $ npm init
  • 67.
    Creating a Server 67 1.var http = require('http'); 2. http.createServer(function (request, response) { 3. response.writeHead(200, { 'Content-Type': 'text/plain' }); 4. response.write('Hello Node.js!'); 5. response.end(); 6. }) 7. .listen(8080, function () { 8. console.log('Listening on port 8080'); 9. });
  • 68.
    Running the Server 68 $node server.js Listening on 8080
  • 69.
    Handling Requests 69 1. varhttp = require('http'); 2. var url = require('url'); 3. http.createServer(function (request, response) { 4. var pathname = url.parse(request.url, true).pathname; 5. if (//todos/.test(pathname)) { … } 6. else if (//todos/d+/.test(pathname)) { … } 7. else { … } 8. }) 9. .listen(8080);
  • 70.
  • 71.
    Using Express WebFramework 71 1. /* Install Express in `api` directory: 2. `npm install express --save` */ 3. var express = require('express'); 4. var app = express(); 5. var port = 8080; 6. app.get('/', function (request, response) {}); 7. app.get('/todos', function (request, response) {}); 8. app.post('/todos', function (request, response) {}); 9. app.listen(port, function (err) { 10. console.log('Listening on port ' + port); 11. });
  • 72.
    Using Express Router- /routes/todos.js 72 1. var express = require('express'); 2. var router = express.Router(); 3. router.get('/todos', function (req, res) {}); 4. router.post('/todos', function (req, res) {}); 5. router.get('/todos/:id', function (req, res) {}); 6. router.put('/todos/:id', function (req, res) {}); 7. module.exports = router;
  • 73.
    Mounting the SpecifiedMiddleware 73 1. var express = require('express'); 2. var bodyParser = require('body-parser'); 3. var app = express(); 4. var port = 8080; 5. app.use(function (req, res, next) { 6. res.setHeader('Access-Control-Allow-Origin', '*'); 7. next(); 8. }); 9. app.use(bodyParser.json()); 10. app.use('/', require('./routes/todos')); 11. app.listen(port, function (err) { 12. console.log('Listening on port ' + port); 13. });
  • 74.
    Handling Response -GET /todos/:id 74 1. var file = path.resolve(__dirname, '../data/todos.json'); 2. router.get('/todos/:id', function(req, res) { 3. fs.readFile(file, (err, text) => { 4. if (err) { throw err; } 5. var todos = JSON.parse(text); 6. var id = Number(req.params.id); 7. var todo = todos.find(v => v.id === id); 8. if (!todo) { return res.status(404).json(null); } 9. res.status(200).json(todo); 10. }); 11. });
  • 75.
    /data/todos.json 75 1. [{ 2. "id":1, 3. "title": "delectus aut autem", 4. "notes": "", 5. "done": false, 6. "starred": false 7. }, { 8. "id": 2, 9. "title": "quis ut nam facilis et officia qui", 10. "notes": "quo adipisci enim quam ut ab", 11. "done": true, 12. "starred": true 13. }]
  • 76.
  • 77.
  • 78.
    Testing APIs UsingcURL 78 $ curl "http://localhost/api/todos" $ curl "http://localhost/api/todos/1" $ curl -d "title=Water" "http://localhost/api/todos"
  • 79.
  • 80.
  • 81.
  • 82.
    Sample Codes 82 Practical JavaScriptProgramming SPA API https://github.com/sweekson/tm-etp-spa https://github.com/sweekson/tm-etp-api
  • 83.
    Reference 83 ● Regular expression- Wikipedia ● Regular Expressions - JavaScript | MDN ● Representational state transfer - Wikipedia ● Single-page application - Wikipedia ● Uses for Regular Expressions | MSDN Practical JavaScript Programming
  • 84.
  • 85.