├── Ch18 ├── README.md └── examples │ ├── src │ ├── TodoHeader.css │ ├── TodoList.css │ ├── index.css │ ├── index.js │ ├── App.test.js │ ├── TodoList.js │ ├── App.css │ ├── App.js │ └── logo.svg │ ├── public │ ├── favicon.ico │ └── index.html │ ├── .bowerrc │ ├── .gitignore │ └── package.json ├── Ch13 └── README.md ├── javascript101-live ├── README.md ├── subtitle │ ├── 字幕.zip │ └── 字幕 │ │ ├── Unit2.txt │ │ └── VTT │ │ └── Unit2.vtt └── Unit01 │ └── examples │ ├── main.css │ ├── index.html │ └── main.js ├── .gitignore ├── Ch01 ├── examples │ ├── .babelrc │ ├── dist │ │ ├── img │ │ │ └── chart.png │ │ └── css │ │ │ └── main.css │ ├── src │ │ ├── images │ │ │ └── chart.png │ │ ├── styles │ │ │ └── main.scss │ │ └── scripts │ │ │ └── main.js │ ├── bower.json │ ├── package.json │ ├── index.html │ ├── create.html │ ├── gulpfile.babel.js │ ├── update.html │ └── README.md └── README.md ├── Ch02 ├── examples │ ├── .babelrc │ ├── dist │ │ ├── css │ │ │ └── main.css │ │ └── img │ │ │ └── chart.png │ ├── src │ │ ├── styles │ │ │ └── main.scss │ │ ├── images │ │ │ └── chart.png │ │ └── scripts │ │ │ └── main.js │ ├── bower.json │ ├── package.json │ ├── gulpfile.babel.js │ ├── update.html │ ├── README.md │ ├── index.html │ └── create.html └── README.md ├── Ch03 ├── examples2 │ ├── .babelrc │ ├── dist │ │ ├── img │ │ │ ├── poker.png │ │ │ ├── bulbasaur.png │ │ │ ├── charmander.png │ │ │ ├── chikorita.png │ │ │ ├── cyndaquil.png │ │ │ ├── pokemon-go.jpg │ │ │ ├── squirtle.png │ │ │ └── totodile.png │ │ ├── css │ │ │ └── main.css │ │ └── js │ │ │ └── bundle.js │ ├── src │ │ ├── images │ │ │ ├── squirtle.png │ │ │ ├── totodile.png │ │ │ ├── bulbasaur.png │ │ │ ├── charmander.png │ │ │ ├── chikorita.png │ │ │ ├── cyndaquil.png │ │ │ └── pokemon-go.jpg │ │ ├── styles │ │ │ └── main.scss │ │ └── scripts │ │ │ ├── Monster.js │ │ │ └── main.js │ ├── bower.json │ ├── package.json │ ├── gulpfile.babel.js │ ├── index.html │ └── README.md └── README.md ├── Ch07 └── README.md ├── Ch09 ├── examples │ ├── .babelrc │ ├── dist │ │ ├── css │ │ │ └── main.css │ │ └── js │ │ │ └── bundle.js │ ├── src │ │ ├── styles │ │ │ └── main.scss │ │ └── scripts │ │ │ └── main.js │ ├── bower.json │ ├── package.json │ ├── README.md │ ├── index.html │ └── gulpfile.babel.js └── README.md ├── Ch11 ├── examples │ ├── .babelrc │ ├── dist │ │ └── css │ │ │ └── main.css │ ├── src │ │ ├── styles │ │ │ └── main.scss │ │ └── scripts │ │ │ └── main.js │ ├── bower.json │ ├── package.json │ ├── gulpfile.babel.js │ ├── index.html │ ├── README.md │ ├── create.html │ └── update.html └── README.md ├── Ch12 ├── examples1 │ ├── .babelrc │ ├── dist.zip │ ├── dist │ │ ├── img │ │ │ ├── icon-16.png │ │ │ ├── icon-19.png │ │ │ ├── icon-38.png │ │ │ ├── icon-128.png │ │ │ └── icon-300.png │ │ ├── manifest.json │ │ ├── index.html │ │ ├── js │ │ │ └── bundle.js │ │ └── css │ │ │ └── main.css │ ├── src │ │ ├── images │ │ │ ├── icon-128.png │ │ │ ├── icon-16.png │ │ │ ├── icon-19.png │ │ │ ├── icon-300.png │ │ │ └── icon-38.png │ │ ├── manifest.json │ │ ├── index.html │ │ ├── scripts │ │ │ └── main.js │ │ └── styles │ │ │ └── main.scss │ ├── .bowerrc │ ├── bower.json │ ├── README.md │ ├── package.json │ └── gulpfile.babel.js ├── examples2 │ ├── .babelrc │ ├── .bowerrc │ ├── dist │ │ ├── css │ │ │ └── main.css │ │ ├── manifest.json │ │ ├── index.html │ │ ├── popup.html │ │ └── js │ │ │ └── bundle.js │ ├── src │ │ ├── styles │ │ │ └── main.scss │ │ ├── manifest.json │ │ ├── index.html │ │ ├── popup.html │ │ └── scripts │ │ │ └── main.js │ ├── bower.json │ ├── README.md │ ├── package.json │ └── gulpfile.babel.js └── README.md ├── Ch16 ├── examples │ ├── views │ │ ├── includes │ │ │ ├── footer.ejs │ │ │ └── head.ejs │ │ ├── error.ejs │ │ ├── index.ejs │ │ ├── edit.ejs │ │ └── todo.ejs │ ├── public │ │ └── stylesheets │ │ │ └── style.css │ ├── .bowerrc │ ├── models │ │ └── db.js │ ├── bower.json │ ├── package.json │ ├── routes │ │ └── index.js │ ├── app.js │ └── bin │ │ └── www └── README.md ├── Ch05 └── README.md ├── Ch04 └── README.md ├── Ch06 └── README.md ├── Ch10 └── README.md ├── Ch08 └── README.md ├── Ch14 ├── README.md ├── examples1 │ └── index.html └── examples2 │ └── index.html ├── Ch15 ├── examples │ ├── package.json │ ├── app.js │ └── result.json └── README.md ├── old.md └── README.md /Ch18/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Ch13/README.md: -------------------------------------------------------------------------------- 1 | # 前端開發面試常見問題研討 -------------------------------------------------------------------------------- /javascript101-live/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Ch18/examples/src/TodoHeader.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Ch18/examples/src/TodoList.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/ -------------------------------------------------------------------------------- /Ch01/examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch02/examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch03/examples2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch07/README.md: -------------------------------------------------------------------------------- 1 | # BOM & DOM 操作基礎 2 | 3 | - DOM 4 | - DOM -------------------------------------------------------------------------------- /Ch09/examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch11/examples/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch12/examples1/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch12/examples2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } -------------------------------------------------------------------------------- /Ch16/examples/views/includes/footer.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Ch02/README.md: -------------------------------------------------------------------------------- 1 | # CSS3 快速入門 2 | 3 | - 外觀樣式 4 | - 定位 5 | - bootstrap -------------------------------------------------------------------------------- /Ch16/README.md: -------------------------------------------------------------------------------- 1 | # NodeJS / Express / MongoDB 新手入門 JavaScript 後端開發 -------------------------------------------------------------------------------- /Ch09/README.md: -------------------------------------------------------------------------------- 1 | # Fetch / Ajax / JSON 2 | 3 | - Fetch 4 | - Ajax 5 | - JSON -------------------------------------------------------------------------------- /Ch02/examples/dist/css/main.css: -------------------------------------------------------------------------------- 1 | .chart-container { 2 | text-align: center; } 3 | -------------------------------------------------------------------------------- /Ch02/examples/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .chart-container { 2 | text-align: center; 3 | } -------------------------------------------------------------------------------- /Ch05/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 函數 Function 基礎 2 | 3 | - function 4 | - arrow function -------------------------------------------------------------------------------- /Ch04/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 流程控制 2 | 3 | - if..else 4 | - switch 5 | - while 6 | - do...while -------------------------------------------------------------------------------- /Ch01/README.md: -------------------------------------------------------------------------------- 1 | # 單元1 Web 程式設計概論與 HTML5 快速入門 2 | 3 | - 網路、瀏覽器歷史 4 | - Web 開發基本觀念 5 | - HTML5 6 | -------------------------------------------------------------------------------- /Ch06/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 物件 Object 基礎 2 | 3 | - object 4 | - class 5 | - this 6 | - prototype -------------------------------------------------------------------------------- /Ch12/examples1/dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist.zip -------------------------------------------------------------------------------- /Ch18/examples/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /Ch10/README.md: -------------------------------------------------------------------------------- 1 | # Cookie、LocalStorage 與 SessionStorage 本地端資料儲存 2 | 3 | - Cookie 4 | - LocalStorage 5 | - SessionStorage -------------------------------------------------------------------------------- /Ch01/examples/dist/img/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch01/examples/dist/img/chart.png -------------------------------------------------------------------------------- /Ch02/examples/dist/img/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch02/examples/dist/img/chart.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/poker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/poker.png -------------------------------------------------------------------------------- /Ch18/examples/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch18/examples/public/favicon.ico -------------------------------------------------------------------------------- /Ch01/examples/src/images/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch01/examples/src/images/chart.png -------------------------------------------------------------------------------- /Ch02/examples/src/images/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch02/examples/src/images/chart.png -------------------------------------------------------------------------------- /Ch08/README.md: -------------------------------------------------------------------------------- 1 | # 事件處理 Event Handle 2 | 3 | - getElementById 4 | - addEventListener/callback 5 | - querySelector 6 | - bubble -------------------------------------------------------------------------------- /Ch12/examples1/dist/img/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist/img/icon-16.png -------------------------------------------------------------------------------- /Ch12/examples1/dist/img/icon-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist/img/icon-19.png -------------------------------------------------------------------------------- /Ch12/examples1/dist/img/icon-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist/img/icon-38.png -------------------------------------------------------------------------------- /Ch16/examples/views/error.ejs: -------------------------------------------------------------------------------- 1 |

<%= message %>

2 |

<%= error.status %>

3 |
<%= error.stack %>
4 | -------------------------------------------------------------------------------- /javascript101-live/subtitle/字幕.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/javascript101-live/subtitle/字幕.zip -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/bulbasaur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/bulbasaur.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/charmander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/charmander.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/chikorita.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/chikorita.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/cyndaquil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/cyndaquil.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/pokemon-go.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/pokemon-go.jpg -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/squirtle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/squirtle.png -------------------------------------------------------------------------------- /Ch03/examples2/dist/img/totodile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/dist/img/totodile.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/squirtle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/squirtle.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/totodile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/totodile.png -------------------------------------------------------------------------------- /Ch12/examples1/dist/img/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist/img/icon-128.png -------------------------------------------------------------------------------- /Ch12/examples1/dist/img/icon-300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/dist/img/icon-300.png -------------------------------------------------------------------------------- /Ch12/examples1/src/images/icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/src/images/icon-128.png -------------------------------------------------------------------------------- /Ch12/examples1/src/images/icon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/src/images/icon-16.png -------------------------------------------------------------------------------- /Ch12/examples1/src/images/icon-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/src/images/icon-19.png -------------------------------------------------------------------------------- /Ch12/examples1/src/images/icon-300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/src/images/icon-300.png -------------------------------------------------------------------------------- /Ch12/examples1/src/images/icon-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch12/examples1/src/images/icon-38.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/bulbasaur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/bulbasaur.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/charmander.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/charmander.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/chikorita.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/chikorita.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/cyndaquil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/cyndaquil.png -------------------------------------------------------------------------------- /Ch03/examples2/src/images/pokemon-go.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdchang/javascript101/HEAD/Ch03/examples2/src/images/pokemon-go.jpg -------------------------------------------------------------------------------- /javascript101-live/Unit01/examples/main.css: -------------------------------------------------------------------------------- 1 | #start-btn { 2 | width: 200px; 3 | height: 50px; 4 | background-color: orange; 5 | border-radius: 5%; 6 | } -------------------------------------------------------------------------------- /Ch01/examples/dist/css/main.css: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; } 3 | 4 | .ellipsis { 5 | overflow: hidden; 6 | white-space: nowrap; 7 | text-overflow: ellipsis; } 8 | -------------------------------------------------------------------------------- /Ch01/examples/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; 3 | } 4 | 5 | .ellipsis { 6 | overflow:hidden; 7 | white-space: nowrap; 8 | text-overflow: ellipsis; 9 | } -------------------------------------------------------------------------------- /Ch09/examples/dist/css/main.css: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; } 3 | 4 | .ellipsis { 5 | overflow: hidden; 6 | white-space: nowrap; 7 | text-overflow: ellipsis; } 8 | -------------------------------------------------------------------------------- /Ch09/examples/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; 3 | } 4 | 5 | .ellipsis { 6 | overflow:hidden; 7 | white-space: nowrap; 8 | text-overflow: ellipsis; 9 | } -------------------------------------------------------------------------------- /Ch11/examples/dist/css/main.css: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; } 3 | 4 | .ellipsis { 5 | overflow: hidden; 6 | white-space: nowrap; 7 | text-overflow: ellipsis; } 8 | -------------------------------------------------------------------------------- /Ch11/examples/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .thumbnail-image { 2 | max-height: 200px; 3 | } 4 | 5 | .ellipsis { 6 | overflow:hidden; 7 | white-space: nowrap; 8 | text-overflow: ellipsis; 9 | } -------------------------------------------------------------------------------- /Ch16/examples/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Ch16/examples/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/bower_components/", 3 | "timeout": 120000, 4 | "registry": { 5 | "search": [ 6 | "https://bower.herokuapp.com" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /Ch18/examples/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "public/bower_components/", 3 | "timeout": 120000, 4 | "registry": { 5 | "search": [ 6 | "https://bower.herokuapp.com" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /Ch12/examples1/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "dist/bower_components/", 3 | "timeout": 120000, 4 | "registry": { 5 | "search": [ 6 | "https://bower.herokuapp.com" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Ch12/examples2/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "dist/bower_components/", 3 | "timeout": 120000, 4 | "registry": { 5 | "search": [ 6 | "https://bower.herokuapp.com" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Ch14/README.md: -------------------------------------------------------------------------------- 1 | # Google Map API / Facebook API 新手入門 2 | 3 | ## 參考文件 4 | 1. [script tag 屬性 async defer 差別](http://blog.xuite.net/vexed/tech/61308318-script+tag+%E5%B1%AC%E6%80%A7+async+defer+%E5%B7%AE%E5%88%A5) -------------------------------------------------------------------------------- /Ch12/examples2/dist/css/main.css: -------------------------------------------------------------------------------- 1 | .header { 2 | margin-top: 40px; 3 | font-size: 60px; } 4 | 5 | .countdown { 6 | font-size: 40px; } 7 | 8 | .popup-container { 9 | min-width: 200px; 10 | min-height: 100px; } 11 | -------------------------------------------------------------------------------- /Ch12/examples2/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | margin-top: 40px; 3 | font-size: 60px; 4 | } 5 | 6 | .countdown { 7 | font-size: 40px; 8 | } 9 | 10 | .popup-container { 11 | min-width: 200px; 12 | min-height: 100px; 13 | } -------------------------------------------------------------------------------- /Ch18/examples/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('root') 9 | ); 10 | -------------------------------------------------------------------------------- /Ch18/examples/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /Ch18/examples/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # production 10 | build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log 16 | -------------------------------------------------------------------------------- /Ch18/examples/src/TodoList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const TodoList = (props) => ( 4 | 11 | ) 12 | 13 | export default TodoList; -------------------------------------------------------------------------------- /Ch16/examples/views/includes/head.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= title %> 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Ch11/README.md: -------------------------------------------------------------------------------- 1 | # Firebase 雲端資料庫 2 | 3 | - Firebase 4 | - 記帳程式 5 | - Bootstrap 6 | - Chart 7 | 8 | # 延伸閱讀 9 | 1. [Add Firebase to your JavaScript Project](https://firebase.google.com/docs/web/setup) 10 | 2. [Read and Write Data on the Web](https://firebase.google.com/docs/database/web/read-and-write) -------------------------------------------------------------------------------- /Ch16/examples/models/db.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | mongoose.connect('mongodb://localhost/todoapp'); 3 | 4 | const TodoSchema = { 5 | title: String, 6 | date: { type: Date, default: Date.now() }, 7 | }; 8 | 9 | module.exports = mongoose.model('Todo', TodoSchema); 10 | 11 | 12 | -------------------------------------------------------------------------------- /javascript101-live/Unit01/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 寶可夢對戰遊戲! 4 | 5 | 6 | 7 |

寶可夢對戰遊戲

8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Ch15/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "kdchang", 10 | "license": "MIT", 11 | "dependencies": { 12 | "cheerio": "^0.22.0", 13 | "request": "^2.79.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Ch16/examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "description": "", 4 | "main": "", 5 | "authors": [ 6 | "kdchang " 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/kdchang/javascript101", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "public/bower_components/", 15 | "test", 16 | "tests" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Ch16/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.13.2", 10 | "cookie-parser": "~1.3.5", 11 | "debug": "~2.2.0", 12 | "ejs": "~2.3.3", 13 | "express": "~4.13.1", 14 | "mongoose": "^4.7.0", 15 | "morgan": "~1.6.1", 16 | "serve-favicon": "~2.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Ch09/examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iPet", 3 | "description": "iPet examples", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch01/examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bonus Tab", 3 | "description": "bonus extensions", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch02/examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bonus Tab", 3 | "description": "bonus extensions", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch03/examples2/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PokomenFight", 3 | "description": "PokomenFight", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch11/examples/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Bonus Tab", 3 | "description": "bonus extensions", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch18/examples/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /Ch12/examples1/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BeautyTab", 3 | "description": "BeautyTab extensions", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch12/examples2/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ByeByeFB", 3 | "description": "ByeByeFB extensions", 4 | "main": "index.js", 5 | "authors": [ 6 | "kdchang" 7 | ], 8 | "license": "MIT", 9 | "homepage": "", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "^3.1.1", 20 | "bootstrap": "^3.3.7" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Ch18/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "0.1.0", 4 | "private": true, 5 | "devDependencies": { 6 | "react-scripts": "0.7.0" 7 | }, 8 | "dependencies": { 9 | "react": "^15.4.1", 10 | "react-dom": "^15.4.1" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Ch12/README.md: -------------------------------------------------------------------------------- 1 | # Chrome Extension 應用程式實戰教學 2 | 3 | - Chrome Extension 簡介 4 | - Adblock 5 | - NewTab 6 | - Bookmark 7 | 8 | # What are extensions? 9 | Extensions are small software programs that can modify and enhance the functionality of the Chrome browser. You write them using web technologies such as HTML, JavaScript, and CSS. 10 | 11 | # 延伸閱讀 12 | 1. [What are extensions?](https://developer.chrome.com/extensions) 13 | 2. [大兜的 Chrome Extension 學習筆記](https://tonytonyjan.net/2012/05/25/get-start-with-chrome-extension/) 14 | -------------------------------------------------------------------------------- /Ch12/examples1/README.md: -------------------------------------------------------------------------------- 1 | # AdByeBye 廣告掰掰外掛 2 | 3 | # What are extensions? 4 | 5 | Extensions are small software programs that can modify and enhance the functionality of the Chrome browser. You write them using web technologies such as HTML, JavaScript, and CSS. 6 | 7 | # 延伸閱讀 8 | 1. [What are extensions?](https://developer.chrome.com/extensions) 9 | 2. [大兜的 Chrome Extension 學習筆記](https://tonytonyjan.net/2012/05/25/get-start-with-chrome-extension/) 10 | 3. [window.onload vs document.onload](http://stackoverflow.com/questions/588040/window-onload-vs-document-onload) -------------------------------------------------------------------------------- /Ch12/examples2/README.md: -------------------------------------------------------------------------------- 1 | # AdByeBye 廣告掰掰外掛 2 | 3 | # What are extensions? 4 | 5 | Extensions are small software programs that can modify and enhance the functionality of the Chrome browser. You write them using web technologies such as HTML, JavaScript, and CSS. 6 | 7 | # 延伸閱讀 8 | 1. [What are extensions?](https://developer.chrome.com/extensions) 9 | 2. [大兜的 Chrome Extension 學習筆記](https://tonytonyjan.net/2012/05/25/get-start-with-chrome-extension/) 10 | 3. [window.onload vs document.onload](http://stackoverflow.com/questions/588040/window-onload-vs-document-onload) -------------------------------------------------------------------------------- /Ch12/examples1/dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BeautyTab", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "BeautyTab", 6 | "short_name": "BeautyTab", 7 | "icons": { 8 | "16": "./img/icon-16.png", 9 | "19": "./img/icon-19.png", 10 | "38": "./img/icon-38.png", 11 | "128": "./img/icon-128.png", 12 | "300": "./img/icon-300.png" 13 | }, 14 | "background": { 15 | "scripts": ["./js/bundle.js"] 16 | }, 17 | "chrome_url_overrides": { 18 | "newtab": "index.html" 19 | }, 20 | "permissions": [ 21 | "tabs" 22 | ] 23 | } -------------------------------------------------------------------------------- /Ch12/examples1/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BeautyTab", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "BeautyTab", 6 | "short_name": "BeautyTab", 7 | "icons": { 8 | "16": "./img/icon-16.png", 9 | "19": "./img/icon-19.png", 10 | "38": "./img/icon-38.png", 11 | "128": "./img/icon-128.png", 12 | "300": "./img/icon-300.png" 13 | }, 14 | "background": { 15 | "scripts": ["./js/bundle.js"] 16 | }, 17 | "chrome_url_overrides": { 18 | "newtab": "index.html" 19 | }, 20 | "permissions": [ 21 | "tabs" 22 | ] 23 | } -------------------------------------------------------------------------------- /Ch15/README.md: -------------------------------------------------------------------------------- 1 | # NodeJS 網路爬蟲入門實戰 2 | 3 | ## 參考文件 4 | 1. [輕輕鬆鬆用 Nodejs 寫網路爬蟲](http://www.slideshare.net/ssusera1d1af/nodejs-53236276) 5 | 2. [資料爬蟲實戰-使用 node.js](http://blog.infographics.tw/2015/03/crawl-data-with-nodejs/) 6 | 3. [Node.js 網路爬蟲](https://docs.google.com/presentation/d/1Jy4ZsLBRaTuHTsI0y3-P3ozw3iFxzjnmDuxXFMTkz8k/edit#slide=id.p) 7 | 4. [How to make a web crawler in JavaScript / Node.js](http://www.netinstructions.com/how-to-make-a-simple-web-crawler-in-javascript-and-node-js/) 8 | 5. [Scraping the Web With Node.js](https://scotch.io/tutorials/scraping-the-web-with-node-js) 9 | 6. [pa4373/ptt-crawler.js](https://gist.github.com/pa4373/8007dbf28af8b0e39964) -------------------------------------------------------------------------------- /Ch09/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iPet", 3 | "version": "1.0.0", 4 | "description": "iPet examples", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-preset-es2015": "^6.16.0", 15 | "babel-register": "^6.16.3", 16 | "babelify": "^7.3.0", 17 | "browserify": "^13.1.0", 18 | "gulp": "^3.9.1", 19 | "gulp-connect": "^5.0.0", 20 | "gulp-sass": "^2.3.2", 21 | "gulp-uglify": "^2.0.0", 22 | "vinyl-source-stream": "^1.1.0" 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Ch03/examples2/dist/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: black; } 3 | 4 | .title { 5 | color: white; } 6 | 7 | .align-center { 8 | display: flex; 9 | align-items: center; 10 | justify-content: center; 11 | flex-direction: column; } 12 | 13 | .players-container { 14 | margin-top: 20px; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; } 18 | 19 | .player-box { 20 | width: 150px; 21 | margin: 10px; } 22 | 23 | .margin-top { 24 | margin-top: 15px; } 25 | 26 | .person { 27 | color: #FFFFFF; } 28 | 29 | .monster-img { 30 | width: 100px; } 31 | 32 | @media (max-width: 400px) { 33 | .title { 34 | font-size: 20px; } } 35 | -------------------------------------------------------------------------------- /Ch12/examples2/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ByeByeFB", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "ByeByeFB", 6 | "short_name": "ByeByeFB", 7 | "content_scripts": [ 8 | { 9 | "matches": ["https://zh-tw.facebook.com/*", "https://www.facebook.com/*"], 10 | "css": ["./css/main.css", "./bower_components/bootstrap/dist/css/bootstrap.css"], 11 | "js": ["./js/bundle.js"] 12 | } 13 | ], 14 | "page_action": { 15 | "default_title": "讀書法寶", 16 | "default_popup": "./popup.html" 17 | }, 18 | "background": { 19 | "page": "./index.html" 20 | } 21 | } -------------------------------------------------------------------------------- /Ch12/examples2/dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ByeByeFB", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "ByeByeFB", 6 | "short_name": "ByeByeFB", 7 | "content_scripts": [ 8 | { 9 | "matches": ["https://zh-tw.facebook.com/*", "https://www.facebook.com/*"], 10 | "css": ["./css/main.css", "./bower_components/bootstrap/dist/css/bootstrap.css"], 11 | "js": ["./js/bundle.js"] 12 | } 13 | ], 14 | "browser_action": { 15 | "default_title": "讀書法寶", 16 | "default_popup": "./popup.html" 17 | }, 18 | "background": { 19 | "page": "./index.html" 20 | } 21 | } -------------------------------------------------------------------------------- /Ch03/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript 簡史、開發環境建置與基礎介紹 2 | 3 | - JavaScript 發展 4 | - 環境建置(bower/npm/yeoman/babel/gulp) 5 | - 變數 6 | - 範例 7 | 8 | 1. [poker](https://www.flickr.com/photos/eurritimia/1028477026/in/photolist-2yTdow-2CTk4V-3wW2GC-8ykkXQ-7xrDVe-57A3ht-U8wbT-91rFCp-atNo65-7ws9Ki-w29mw-ajj8ri-atNmky-dUmpHm-7Z75Pj-azLgPb-5nJiAb-8tpWTu-ebaYib-xs6Ng-xs6QS-8tq2XW-xs6PY-akZqSN-xs6NQ-aVVuyp-7EVJap-58E4eP-xs6RS-aPrY7D-nK1fek-58Jdkw-xs6Qu-8tpZe1-dyJ53M-xs6Po-8i54tm-aV2U5a-8tpQ5f-dFoViL-58JdfY-8EUnCy-6YPydt-qHYbFq-6YTysL-6YSHZZ-6YSHUv-6YWK6q-dUYEAF-fNfFud) 9 | 2. [圖鑑](http://www.pikatw.com/t/pokedex_jt.htm) 10 | 3. [妙蛙種子](https://zh.wikipedia.org/wiki/%E5%A6%99%E8%9B%99%E7%A8%AE%E5%AD%90#/media/File:Bulbasaur.png) -------------------------------------------------------------------------------- /Ch12/examples2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ByeByeFB", 3 | "version": "1.0.0", 4 | "description": "ByeByeFB extensions", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-preset-es2015": "^6.16.0", 15 | "babel-register": "^6.16.3", 16 | "babelify": "^7.3.0", 17 | "browserify": "^13.1.0", 18 | "gulp": "^3.9.1", 19 | "gulp-connect": "^5.0.0", 20 | "gulp-image": "^2.7.2", 21 | "gulp-sass": "^2.3.2", 22 | "gulp-uglify": "^2.0.0", 23 | "vinyl-source-stream": "^1.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Ch12/examples1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BeautyTab", 3 | "version": "1.0.0", 4 | "description": "BeautyTab extensions", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-preset-es2015": "^6.16.0", 15 | "babel-register": "^6.16.3", 16 | "babelify": "^7.3.0", 17 | "browserify": "^13.1.0", 18 | "gulp": "^3.9.1", 19 | "gulp-connect": "^5.0.0", 20 | "gulp-image": "^2.7.2", 21 | "gulp-sass": "^2.3.2", 22 | "gulp-uglify": "^2.0.0", 23 | "vinyl-source-stream": "^1.1.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Ch03/examples2/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background: black; 3 | } 4 | 5 | .title { 6 | color: white; 7 | } 8 | 9 | .align-center { 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex-direction: column; 14 | } 15 | 16 | .players-container { 17 | margin-top: 20px; 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | } 22 | 23 | .player-box { 24 | width: 150px; 25 | margin: 10px; 26 | } 27 | 28 | .margin-top { 29 | margin-top: 15px; 30 | } 31 | 32 | .person { 33 | color: #FFFFFF; 34 | } 35 | 36 | .monster-img { 37 | width: 100px; 38 | } 39 | 40 | @media (max-width: 400px) { 41 | .title { 42 | font-size: 20px; 43 | } 44 | } -------------------------------------------------------------------------------- /Ch16/examples/views/index.ejs: -------------------------------------------------------------------------------- 1 | <% include includes/head %> 2 |

<%= title %>

3 |
4 | 5 | 6 |
7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | <% for(let i = 0; i < todos.length; i++) { %> 16 | 17 | 18 | 19 | 20 | <% } %> 21 |
代辦事項名稱記錄時間
<%= todos[i].title %><%= todos[i].date %>
22 | <% include includes/footer %> 23 | -------------------------------------------------------------------------------- /Ch12/examples2/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ByeByeFB 臉書掰掰 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Ch12/examples2/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ByeByeFB 臉書掰掰 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Ch11/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iRich", 3 | "version": "1.0.0", 4 | "description": "iRich", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-preset-es2015": "^6.16.0", 15 | "babel-register": "^6.16.3", 16 | "babelify": "^7.3.0", 17 | "browserify": "^13.1.0", 18 | "gulp": "^3.9.1", 19 | "gulp-connect": "^5.0.0", 20 | "gulp-sass": "^2.3.2", 21 | "gulp-uglify": "^2.0.0", 22 | "vinyl-source-stream": "^1.1.0" 23 | }, 24 | "dependencies": { 25 | "chart.js": "^2.3.0", 26 | "uuid": "^2.0.3" 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Ch16/examples/views/edit.ejs: -------------------------------------------------------------------------------- 1 | <% include includes/head %> 2 |
3 | 7 |
8 |
9 |
10 | 11 | 12 |
13 | 14 |
15 |
16 |
17 |
18 | <% include includes/footer %> 19 | -------------------------------------------------------------------------------- /Ch15/examples/app.js: -------------------------------------------------------------------------------- 1 | const request = require('request'); 2 | const cheerio = require('cheerio'); 3 | const fs = require('fs'); 4 | 5 | request({ 6 | url: 'https://www.ptt.cc/bbs/Soft_Job/index.html', 7 | method: 'GET', 8 | }, function(err, httpResponse, body) { 9 | if (err) { 10 | console.log(err); 11 | return; 12 | } 13 | const $ = cheerio.load(body); 14 | const results = []; 15 | let titles = $('a'); 16 | 17 | for(let i = 0; i < titles.length; i++) { 18 | console.log($(titles[0]).text()); 19 | console.log($(titles[0]).attr('href')); 20 | results.push({ title: $(titles[i]).text(), link: $(titles[i]).attr('href') }); 21 | } 22 | 23 | fs.writeFileSync('result.json', JSON.stringify(results)); 24 | console.log(results); 25 | }) -------------------------------------------------------------------------------- /Ch03/examples2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PokomenFight", 3 | "version": "1.0.0", 4 | "description": "Pokomen Fight", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-loader": "^6.2.5", 15 | "babel-preset-es2015": "^6.16.0", 16 | "babel-preset-stage-0": "^6.16.0", 17 | "babel-register": "^6.16.3", 18 | "babelify": "^7.3.0", 19 | "browserify": "^13.1.0", 20 | "gulp": "^3.9.1", 21 | "gulp-connect": "^5.0.0", 22 | "gulp-image": "^2.7.2", 23 | "gulp-sass": "^2.3.2", 24 | "gulp-uglify": "^2.0.0", 25 | "vinyl-source-stream": "^1.1.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Ch03/examples2/src/scripts/Monster.js: -------------------------------------------------------------------------------- 1 | class Pokomo { 2 | wow() { 3 | alert('wow! wow!'); 4 | } 5 | } 6 | 7 | class Monster extends Pokomo { 8 | constructor(name, image, hp, type) { 9 | super(); 10 | this.name = name; 11 | this.image = image; 12 | this.hp = hp; 13 | this.type = type; 14 | } 15 | 16 | getName() { 17 | return this.name; 18 | } 19 | 20 | getImage() { 21 | return this.image; 22 | } 23 | 24 | getHP() { 25 | return this.hp; 26 | } 27 | 28 | getType() { 29 | return this.type; 30 | } 31 | 32 | setHurt(value) { 33 | this.hp -= value; 34 | } 35 | 36 | isAlive() { 37 | if(this.hp > 0) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | } 44 | 45 | export default Monster; -------------------------------------------------------------------------------- /Ch16/examples/views/todo.ejs: -------------------------------------------------------------------------------- 1 | <% include includes/head %> 2 |
3 | 7 |
8 |
<%= todo.title %>
9 |
10 |
11 | 12 | 13 | 14 |
15 |
16 |
17 |
18 | <% include includes/footer %> 19 | -------------------------------------------------------------------------------- /Ch12/examples1/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BeautyTab 表特分頁 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |

分享生命中的美好事物

18 | 19 |
20 |

本外掛程式為教學使用,圖片取自網路公開資源,若有造成不便,煩請聯絡我們,我們會立即為您處理,謝謝您

21 |
22 |
23 |
24 |
25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Ch12/examples1/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BeautyTab 表特分頁 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |

分享生命中的美好事物

18 | 19 |
20 |

本外掛程式為教學使用,圖片取自網路公開資源,若有造成不便,煩請聯絡我們,我們會立即為您處理,謝謝您

21 |
22 |
23 |
24 |
25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Ch14/examples1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Google Map API 5 | 9 | 10 | 11 |
12 | 30 | 33 | 34 | -------------------------------------------------------------------------------- /Ch01/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iRich", 3 | "version": "1.0.0", 4 | "description": "bonus extensions", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-loader": "^6.2.5", 15 | "babel-preset-es2015": "^6.16.0", 16 | "babel-preset-stage-0": "^6.16.0", 17 | "babel-register": "^6.16.3", 18 | "babelify": "^7.3.0", 19 | "browserify": "^13.1.0", 20 | "css-loader": "^0.25.0", 21 | "extract-text-webpack-plugin": "^1.0.1", 22 | "gulp": "^3.9.1", 23 | "gulp-connect": "^5.0.0", 24 | "gulp-image": "^2.7.2", 25 | "gulp-sass": "^2.3.2", 26 | "gulp-uglify": "^2.0.0", 27 | "html-webpack-plugin": "^2.22.0", 28 | "sass-loader": "^4.0.2", 29 | "style-loader": "^0.13.1", 30 | "vinyl-source-stream": "^1.1.0", 31 | "webpack": "^1.13.2", 32 | "webpack-dev-server": "^1.16.2" 33 | }, 34 | "dependencies": { 35 | "chart.js": "^2.3.0", 36 | "uuid": "^2.0.3", 37 | "whatwg-fetch": "^1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Ch02/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iRich", 3 | "version": "1.0.0", 4 | "description": "bonus extensions", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "gulp", 8 | "build": "gulp build" 9 | }, 10 | "author": "kdchang", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "babel-core": "^6.17.0", 14 | "babel-loader": "^6.2.5", 15 | "babel-preset-es2015": "^6.16.0", 16 | "babel-preset-stage-0": "^6.16.0", 17 | "babel-register": "^6.16.3", 18 | "babelify": "^7.3.0", 19 | "browserify": "^13.1.0", 20 | "css-loader": "^0.25.0", 21 | "extract-text-webpack-plugin": "^1.0.1", 22 | "gulp": "^3.9.1", 23 | "gulp-connect": "^5.0.0", 24 | "gulp-image": "^2.7.2", 25 | "gulp-sass": "^2.3.2", 26 | "gulp-uglify": "^2.0.0", 27 | "html-webpack-plugin": "^2.22.0", 28 | "sass-loader": "^4.0.2", 29 | "style-loader": "^0.13.1", 30 | "vinyl-source-stream": "^1.1.0", 31 | "webpack": "^1.13.2", 32 | "webpack-dev-server": "^1.16.2" 33 | }, 34 | "dependencies": { 35 | "chart.js": "^2.3.0", 36 | "uuid": "^2.0.3", 37 | "whatwg-fetch": "^1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Ch14/examples2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Facebook API 6 | 7 | 8 | 20 | 21 | 39 | 40 | -------------------------------------------------------------------------------- /Ch18/examples/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import TodoList from './TodoList'; 3 | 4 | class App extends Component { 5 | constructor(props) { 6 | super(props); 7 | this.onChange = this.onChange.bind(this); 8 | this.handleSubmit = this.handleSubmit.bind(this); 9 | this.state = { 10 | items: [], 11 | text: '', 12 | } 13 | } 14 | onChange(e) { 15 | this.setState({text: e.target.value}); 16 | } 17 | handleSubmit(e) { 18 | e.preventDefault(); 19 | const nextItems = this.state.items.concat([{text: this.state.text, id: Date.now()}]); 20 | const nextText = ''; 21 | this.setState({items: nextItems, text: nextText}); 22 | } 23 | render() { 24 | return ( 25 |
26 |

TODO App

27 |
28 | 29 | 30 |
31 |
32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /Ch12/examples1/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | //const REQUEST_URL = 'http://163.29.157.32:8080/dataset/6a3e862a-e1cb-4e44-b989-d35609559463/resource/f4a75ba9-7721-4363-884d-c3820b0b917c/download/393625397fc043188a3f8237c1da1c6f.json'; 2 | let index = Math.floor(Math.random() * 400); 3 | let data = ''; 4 | 5 | function disLikeBtnListener() { 6 | const dislikeBtn = document.querySelector('#dislike-btn'); 7 | dislikeBtn.addEventListener('click', function() { 8 | index = Math.floor(Math.random() * 400); 9 | showData(); 10 | }); 11 | } 12 | 13 | function fetchDemo() { 14 | const REQUEST_URL = 'http://gank.io/api/data/%E7%A6%8F%E5%88%A9/400/1'; 15 | fetch(REQUEST_URL).then((response) => { 16 | return response.json(); 17 | }).then(function(json) { 18 | data = json.results; 19 | showData(); 20 | disLikeBtnListener(); 21 | }); 22 | } 23 | 24 | const showData = () => { 25 | let str = ''; 26 | str += 27 | ` 28 | 29 | 30 | 31 | `; 32 | document.querySelector('#show-img-box').innerHTML = str; 33 | } 34 | 35 | 36 | fetchDemo(); 37 | -------------------------------------------------------------------------------- /Ch12/examples2/dist/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ByeByeFB 臉書掰掰 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Ch12/examples2/src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ByeByeFB 臉書掰掰 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Ch09/examples/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | const REQUEST_URL = 'http://163.29.157.32:8080/dataset/6a3e862a-e1cb-4e44-b989-d35609559463/resource/f4a75ba9-7721-4363-884d-c3820b0b917c/download/393625397fc043188a3f8237c1da1c6f.json'; 2 | let data = ''; 3 | let str = ''; 4 | 5 | function fetchDemo() { 6 | fetch(REQUEST_URL).then((response) => { 7 | return response.json(); 8 | }).then(function(json) { 9 | data = json; 10 | dataList(); 11 | }); 12 | } 13 | 14 | const dataList = () => { 15 | data.map((value, index) => { 16 | str += 17 | ` 18 |
19 |
20 | ... 21 |
22 |

${value.Variety} ${value.Name} ${value.HairType}

23 |

${value.Resettlement}

24 |

聯絡電話 聯絡信箱

25 |
26 |
27 |
28 | `; 29 | }); 30 | document.querySelector('#data-list').innerHTML = str; 31 | } 32 | 33 | fetchDemo(); -------------------------------------------------------------------------------- /Ch09/examples/README.md: -------------------------------------------------------------------------------- 1 | # 福利分頁(BonusTab) 2 | 3 | ``` 4 | npm install --save-dev gulp gulp-sass gulp-uglify gulp-connect 5 | ``` 6 | 7 | # 延伸閱讀 8 | 1. [gulp 學習筆記](https://www.gitbook.com/book/kejyuntw/gulp-learning-notes/details) 9 | 2. [Getting started with Gulp and Sass](http://ryanchristiani.com/getting-started-with-gulp-and-sass/) 10 | 3. [Using ES6 with gulp](https://markgoodyear.com/2015/06/using-es6-with-gulp/) 11 | 4. [Setting up an ES6 Project Using Babel and Browserify](https://www.sitepoint.com/setting-up-es6-project-using-babel-browserify/) 12 | 5. [WEBPACK入門教學筆記](http://blog.kkbruce.net/2015/10/webpack.html#.WAIU7JN96zY) 13 | 6. [Setting up ES6+Babel+Gulp](http://ramkulkarni.com/blog/setting-up-es6-babel-gulp/) 14 | 7. [Configuring Webpack to write JS with ES6/ES2015 on browser](https://medium.com/daily-js-tips/configuring-webpack-to-write-js-with-es6-es2015-on-browser-cd089a79ecea#.uo1psi41n) 15 | 8. [求大牛帮忙,用webpack 打包jquery、bootstrap时出错。](http://react-china.org/t/webpack-jquery-bootstrap/1669) 16 | 9. [How-to setup Webpack on an ES6 React Application with SASS?](https://www.jonathan-petitcolas.com/2015/05/15/howto-setup-webpack-on-es6-react-application-with-sass.html) 17 | 10. [動物認養](http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx) 18 | 11. [如何使用CSS的「text-overflow: ellipsis;」屬性限制內容字數?](http://www.astralweb.com.tw/css-ellipsis/) -------------------------------------------------------------------------------- /Ch18/examples/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 17 | React App 18 | 19 | 20 |
21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Ch01/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 16 |
17 |
18 |
19 |

統計資料

20 | 21 |
22 |
23 |

詳細支出

24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 54 |
消費項目消費類別消費金額消費時間操作
買書lifeNT 3002016/10/10 40 | 41 | 42 |
看電影playNT 6002016/10/10 50 | 51 | 52 |
55 |
56 |
57 |
58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Ch16/examples/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const Todo = require('../models/db'); 4 | 5 | /* GET home page. */ 6 | router.get('/', function(req, res, next) { 7 | Todo.find({}, function(error, todos) { 8 | res.render('index', { title: 'TodoApp', todos: todos }); 9 | }); 10 | }); 11 | 12 | router.post('/create', function(req, res, next) { 13 | new Todo({ 14 | title: req.body.title, 15 | }).save(function(error) { 16 | res.redirect( '/' ); 17 | }); 18 | }); 19 | 20 | router.get('/todos/:id', function(req, res, next) { 21 | Todo.findById(req.params.id, function(error, todo){ 22 | res.render('todo', { title: 'TodoApp', todo: todo }); 23 | }); 24 | }); 25 | 26 | router.get('/todos/:id/edit', function(req, res, next) { 27 | Todo.findById(req.params.id, function(error, todo){ 28 | res.render('edit', { title: 'TodoApp', todo: todo }); 29 | }); 30 | }); 31 | 32 | router.post('/edit', function(req, res, next) { 33 | Todo.findById(req.body.id, function(error, todo){ 34 | todo.title = req.body.title; 35 | todo.date = Date.now(); 36 | todo.save(function(error) { 37 | res.redirect( '/' ); 38 | }); 39 | }); 40 | }); 41 | 42 | router.post('/delete', function(req, res, next) { 43 | Todo.findById(req.body.id, function(error, todo){ 44 | todo.remove(function(error, todo){ 45 | res.redirect( '/' ); 46 | }); 47 | }); 48 | }); 49 | 50 | module.exports = router; 51 | -------------------------------------------------------------------------------- /javascript101-live/Unit01/examples/main.js: -------------------------------------------------------------------------------- 1 | // 程式 = 資料結構 + 演算法 2 | /* 3 | 目標:設計一個寶可夢對戰遊戲 4 | 5 | 資料結構設計:儲存遊戲狀態、玩家和電腦選擇的神奇寶貝 6 | 7 | 演算法設計:隨機產生電腦選擇的寶貝,並依玩家和電腦所派出的寶貝判斷誰勝誰負 8 | 9 | 0. 菊草葉:草系 10 | 1. 火球鼠:火系 11 | 2. 小鋸鱷:水系 12 | */ 13 | 14 | var startBtn = document.querySelector('#start-btn'); 15 | var choice = 0; 16 | 17 | startBtn.addEventListener('click', function() { 18 | var comChoice = Math.floor(parseFloat(Math.random() * 3)); 19 | choice = parseInt(prompt('請輸入您想派出的神奇寶貝! 0. 菊草葉 1. 火球鼠 2. 小鋸鱷', 0)); 20 | if(choice === 0) { 21 | alert('你派出了菊草葉!'); 22 | if(comChoice === 0) { 23 | alert('對手派出菊草葉,平分秋色!'); 24 | } else if (comChoice === 1) { 25 | alert('對手派出火球鼠,屬性相剋,你輸了!'); 26 | } else if (comChoice === 2) { 27 | alert('對手派出小鋸鱷,耶,你贏了!'); 28 | } 29 | } else if(choice === 1) { 30 | alert('你派出了火球鼠!'); 31 | if(comChoice === 0) { 32 | alert('對手派出菊草葉,耶,你贏了!'); 33 | } else if (comChoice === 1) { 34 | alert('對手派出火球鼠,平分秋色!'); 35 | } else if (comChoice === 2) { 36 | alert('對手派出小鋸鱷,屬性相剋,你輸了!'); 37 | } 38 | } else if(choice === 2) { 39 | alert('你派出了小鋸鱷!'); 40 | if(comChoice === 0) { 41 | alert('對手派出菊草葉,屬性相剋,你輸了!'); 42 | } else if (comChoice === 1) { 43 | alert('對手派出火球鼠,耶,你贏了!'); 44 | } else if (comChoice === 2) { 45 | alert('對手派出小鋸鱷,平分秋色!'); 46 | } 47 | } 48 | }); 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Ch01/examples/create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 16 |
17 |

新增支出

18 |
19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 35 |
36 |
37 | 38 | 39 |
40 |
41 | 42 | 43 |
44 | 45 | 46 |
47 |
48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Ch09/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | iPet 愛寵物 6 | 7 | 8 | 9 | 10 | 11 | 27 |
28 |
29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Ch16/examples/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const favicon = require('serve-favicon'); 4 | const logger = require('morgan'); 5 | const cookieParser = require('cookie-parser'); 6 | const bodyParser = require('body-parser'); 7 | 8 | const routes = require('./routes/index'); 9 | 10 | const app = express(); 11 | 12 | // view engine setup 13 | app.set('views', path.join(__dirname, 'views')); 14 | app.set('view engine', 'ejs'); 15 | 16 | // uncomment after placing your favicon in /public 17 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 18 | app.use(logger('dev')); 19 | app.use(bodyParser.json()); 20 | app.use(bodyParser.urlencoded({ extended: false })); 21 | app.use(cookieParser()); 22 | app.use(express.static(path.join(__dirname, 'public'))); 23 | 24 | app.use('/', routes); 25 | // catch 404 and forward to error handler 26 | app.use(function(req, res, next) { 27 | var err = new Error('Not Found'); 28 | err.status = 404; 29 | next(err); 30 | }); 31 | 32 | // error handlers 33 | 34 | // development error handler 35 | // will print stacktrace 36 | if (app.get('env') === 'development') { 37 | app.use(function(err, req, res, next) { 38 | res.status(err.status || 500); 39 | res.render('error', { 40 | message: err.message, 41 | error: err 42 | }); 43 | }); 44 | } 45 | 46 | // production error handler 47 | // no stacktraces leaked to user 48 | app.use(function(err, req, res, next) { 49 | res.status(err.status || 500); 50 | res.render('error', { 51 | message: err.message, 52 | error: {} 53 | }); 54 | }); 55 | 56 | 57 | module.exports = app; 58 | -------------------------------------------------------------------------------- /Ch12/examples2/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | const bodyRef = document.querySelector('body'); 2 | bodyRef.innerHTML = ` 3 |
4 |

不能再用 Facebook 了!!

5 |
6 | 距離聯考只剩: 7 | 8 |
9 |
10 | 11 |
12 | ` 13 | countdown(); 14 | 15 | function countdown() { 16 | const target_date = new Date("June 7, 2017").getTime(); 17 | let days; 18 | let hours; 19 | let minutes 20 | let seconds; 21 | const countdown = document.querySelector('#countdown'); 22 | console.log('target_date'); 23 | 24 | var init = setInterval(function () { 25 | var current_date = new Date().getTime(); 26 | var seconds_left = (target_date - current_date) / 1000; 27 | if(seconds_left > 0){ 28 | days = parseInt(seconds_left / 86400); 29 | seconds_left = seconds_left % 86400; 30 | 31 | hours = parseInt(seconds_left / 3600); 32 | seconds_left = seconds_left % 3600; 33 | 34 | minutes = parseInt(seconds_left / 60); 35 | seconds = parseInt(seconds_left % 60); 36 | 37 | // format countdown string + set tag value 38 | countdown.className = 'countdown'; 39 | countdown.innerHTML = days + "天, " + hours + "小時, " 40 | + minutes + "分, " + seconds + "秒"; 41 | } 42 | else{ 43 | countdown.className = 'countdown'; 44 | countdown.innerHTML = "恭喜考完!XD"; 45 | clearInterval(init); 46 | } 47 | }, 1000); 48 | }; 49 | -------------------------------------------------------------------------------- /old.md: -------------------------------------------------------------------------------- 1 | #/ 從零開始學 JavaScript(JavaScript 程式設計新手村) 2 | 由淺入深系統性學習原生 JavaScript 和程式設計的重要觀念, 讓你不只會用 jQuery 還了解它背後使用的原理,並為未來離開新手村出發挑戰前端進階學習打好堅實基礎知識,培養自學各種前端框架和工具的能力。 3 | 4 | # 課程大綱(Syllabus) 5 | 1. 單元1 JavaScript 程式設計初體驗(Pokemon Fight 精靈快打)上 6 | 7 | 2. 單元2 Web 程式設計概論 8 | 9 | 3. 單元3 HTML 基礎入門 10 | 11 | 4. 單元4 HTML 標籤基礎 12 | 13 | 5. 單元5 HTML 實習(iRich 愛記帳) 14 | 15 | 6. 單元6 CSS 入門概論 16 | 17 | 7. 單元7 CSS 版面配置與框架 18 | 19 | 8. 單元8 CSS 實習(iRich 愛記帳) 20 | 21 | 9. 單元9 JavaScript 簡史 22 | 23 | 10. 單元10 JavaScript 基礎介紹 24 | 25 | 11. 單元11 JavaScript 開發環境建置 26 | 27 | 12. 單元12 JavaScript 流程控制 28 | 29 | 13. 單元13 JavaScript 函數 Function 基礎(上) 30 | 31 | 14. 單元14 JavaScript 函數 Function 基礎(下) 32 | 33 | 15. 單元15 JavaScript 物件 Object 基礎(上) 34 | 35 | 16. 單元16 JavaScript 物件 Object 基礎(下) 36 | 37 | 17. 單元17 BOM & DOM 操作基礎 38 | 39 | 18. 單元18 事件處理 Event Handle 40 | 41 | 19. 單元19 JavaScript 整合應用實習(Pokemon Fight 精靈快打) 42 | 43 | 20. 單元20 Fetch / Ajax / JSON 基礎介紹 44 | 45 | 21. 單元21 Fetch / Ajax / JSON 實習(iPet 愛寵物) 46 | 47 | 22. 單元22 Cookie、LocalStorage/SessionStorage 本地端資料儲存 48 | 49 | 23. 單元23 Firebase 雲端資料庫基礎介紹 50 | 51 | 24. 單元24 Firebase 雲端資料庫實習(iRich 愛記帳) 52 | 53 | 25. 單元25 Chrome Extensions 基礎介紹 54 | 55 | 26. 單元26 Chrome Extensions 實習(表特分頁、臉書掰掰) 56 | 57 | 27. 募資金額 100% 解鎖:前端開發面試常見問題研討 58 | 59 | 28. 募資金額 200% 解鎖:Google Map API / Facebook API 新手入門 60 | 61 | 29. 募資金額 400% 解鎖:NodeJS 網路爬蟲入門實戰 62 | 63 | 30. 募資金額 600% 解鎖:NodeJS / Express / MongoDB 新手入門 JavaScript 後端開發 64 | 65 | 31. 募資金額 800% 解鎖:Electron 桌面應用程式開發入門 66 | 67 | 32. 募資金額 1000% 解鎖:JavaScript 主流前端函式庫/框架簡介與 ReactJS 入門初體驗 68 | 69 | # 實戰教學(Examples) 70 | - [X] Fetch 71 | - [X] Firebase 72 | - [X] NewTab 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Ch09/examples/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import sass from 'gulp-sass';// import autoprefixer from 'gulp-autoprefixer'; 5 | import uglify from 'gulp-uglify';// import autoprefixer from 'gulp-autoprefixer'; 6 | import connect from 'gulp-connect';// import autoprefixer from 'gulp-autoprefixer'; 7 | import browserify from 'browserify';// import autoprefixer from 'gulp-autoprefixer'; 8 | import babelify from 'babelify';// import autoprefixer from 'gulp-autoprefixer'; 9 | import source from 'vinyl-source-stream'; 10 | 11 | const dirs = { 12 | src: 'src', 13 | dest: 'dist' 14 | }; 15 | 16 | const stylesPaths = { 17 | src: `${dirs.src}/styles/*.scss`, 18 | dest: `${dirs.dest}/css` 19 | }; 20 | 21 | const scriptsPaths = { 22 | src: `${dirs.src}/scripts/*.js`, 23 | dest: `${dirs.dest}/js` 24 | }; 25 | 26 | gulp.task('styles', () => { 27 | gulp.src(stylesPaths.src) 28 | .pipe(sass()) // 編譯 Scss 29 | .pipe(gulp.dest(stylesPaths.dest)) // 30 | .pipe(connect.reload()); 31 | }); 32 | 33 | gulp.task('scripts', function(){ 34 | return browserify({ 35 | entries: ['./src/scripts/main.js'] 36 | }) 37 | .transform(babelify) 38 | .bundle() 39 | .pipe(source('bundle.js')) 40 | .pipe(gulp.dest(scriptsPaths.dest)); 41 | }); 42 | 43 | gulp.task('server', function () { 44 | connect.server({ 45 | livereload: true, 46 | port: 7777, 47 | }); 48 | }); 49 | 50 | gulp.task('watch', function () { 51 | gulp.watch(stylesPaths.src, ['styles']); 52 | gulp.watch(scriptsPaths.src, ['scripts']); 53 | }); 54 | 55 | gulp.task('default', ['scripts', 'styles', 'server', 'watch']); 56 | gulp.task('build', ['scripts', 'styles']); 57 | -------------------------------------------------------------------------------- /Ch11/examples/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import sass from 'gulp-sass';// import autoprefixer from 'gulp-autoprefixer'; 5 | import uglify from 'gulp-uglify';// import autoprefixer from 'gulp-autoprefixer'; 6 | import connect from 'gulp-connect';// import autoprefixer from 'gulp-autoprefixer'; 7 | import browserify from 'browserify';// import autoprefixer from 'gulp-autoprefixer'; 8 | import babelify from 'babelify';// import autoprefixer from 'gulp-autoprefixer'; 9 | import source from 'vinyl-source-stream'; 10 | 11 | const dirs = { 12 | src: 'src', 13 | dest: 'dist' 14 | }; 15 | 16 | const stylesPaths = { 17 | src: `${dirs.src}/styles/*.scss`, 18 | dest: `${dirs.dest}/css` 19 | }; 20 | 21 | const scriptsPaths = { 22 | src: `${dirs.src}/scripts/*.js`, 23 | dest: `${dirs.dest}/js` 24 | }; 25 | 26 | gulp.task('styles', () => { 27 | gulp.src(stylesPaths.src) 28 | .pipe(sass()) // 編譯 Scss 29 | .pipe(gulp.dest(stylesPaths.dest)) // 30 | .pipe(connect.reload()); 31 | }); 32 | 33 | gulp.task('scripts', function(){ 34 | return browserify({ 35 | entries: ['./src/scripts/main.js'] 36 | }) 37 | .transform(babelify) 38 | .bundle() 39 | .pipe(source('bundle.js')) 40 | .pipe(gulp.dest(scriptsPaths.dest)); 41 | }); 42 | 43 | gulp.task('server', function () { 44 | connect.server({ 45 | livereload: true, 46 | port: 7777, 47 | }); 48 | }); 49 | 50 | gulp.task('watch', function () { 51 | gulp.watch(stylesPaths.src, ['styles']); 52 | gulp.watch(scriptsPaths.src, ['scripts']); 53 | }); 54 | 55 | gulp.task('default', ['scripts', 'styles', 'server', 'watch']); 56 | gulp.task('build', ['scripts', 'styles']); 57 | -------------------------------------------------------------------------------- /Ch12/examples1/dist/js/bundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n \n \n '; 30 | document.querySelector('#show-img-box').innerHTML = str; 31 | }; 32 | 33 | fetchDemo(); 34 | 35 | },{}]},{},[1]); 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #/ 從零開始學 JavaScript(JavaScript 程式設計新手村) 2 | 由淺入深系統性學習原生 JavaScript 和程式設計的重要觀念, 讓你不只會用 jQuery 還了解它背後使用的原理,並為未來離開新手村出發挑戰前端進階學習打好堅實基礎知識,培養自學各種前端框架和工具的能力。 3 | 4 | # 課程大綱(Syllabus) 5 | 1. 單元1 JavaScript 程式設計初體驗(Pokemon Fight 精靈快打)上 6 | 7 | 2. 單元2 JavaScript 程式設計初體驗(Pokemon Fight 精靈快打)下 8 | 9 | 3. 單元3 HTML/CSS 入門概論:註冊/登入表單(bootstrap) 10 | 11 | 4. 單元4 JavaScript 開發環境建置、Github 與瀏覽器 DevTool 教學 12 | 13 | 5. 單元5 實戰範例:TodoList 代辦事項應用程式(JavaScript 函數 Function 基礎) 14 | 15 | 6. 單元6 實戰範例:線上碼表(BOM & DOM 操作基礎與事件處理 Event Handle) 16 | 17 | 7. 單元7 實戰範例:蟲蟲大戰:打蚊子遊戲(BOM & DOM 操作基礎與事件處理 Event Handle) 18 | 19 | 8. 單元8 實戰範例:政府開放資料 API 範例(流程控制、Ajax / JSON 基礎介紹) 20 | 21 | 9. 單元9 實戰範例:政府開放資料 API 範例(流程控制、Ajax / JSON 基礎介紹) 22 | 23 | 10. 單元10 實戰範例:jQuery 入門範例 24 | 25 | 11. 單元11 實戰範例:jQuery 外掛開發入門:自動補完 AutoComplete 26 | 27 | 12. 單元12 實戰範例:jQuery 外掛開發入門:幻燈片相簿 28 | 29 | 13. 單元13 實戰範例:JavaScript 的 2D 打磚塊遊戲(Canvas) 30 | 31 | 14. 單元14 實戰範例:部屬 JavaScript 應用程式到網路 32 | 33 | 15. 單元15 實戰範例:Firebase 雲端資料庫基礎上(iRich 愛記帳) 34 | 35 | 16. 單元16 實戰範例:Firebase 雲端資料庫基礎下(iRich 愛記帳) 36 | 37 | 17. 單元17 實戰範例:NodeJS Web 基礎 38 | 39 | 18. 單元18 實戰範例:NodeJS 網路爬蟲,爬取 PTT 八卦版資料 40 | 41 | 19. 單元19 實戰範例:Chrome Extensions 基礎 42 | 43 | 20. 單元20 實戰範例:Chrome Extensions(表特分頁:Cookie、LocalStorage/SessionStorage 本地端資料儲存) 44 | 45 | 21. 單元21 實戰範例:上架自己的 Chrome Extensions 46 | 47 | 22. 募資金額 100% 解鎖:前端開發面試常見問題研討 48 | 49 | 23. 募資金額 200% 解鎖:NodeJS Google Map API / Facebook API 新手入門 50 | 51 | 24. 募資金額 400% 解鎖:NodeJS/PhantomJS 網路爬蟲爬取動態網頁入門實戰 52 | 53 | 25. 募資金額 600% 解鎖:NodeJS / Express / MongoDB 新手入門 JavaScript 後端開發 54 | 55 | 26. 募資金額 800% 解鎖:Electron 桌面應用程式開發入門(代辦事項清單) 56 | 57 | 27. 募資金額 1000% 解鎖:JavaScript ReactJS 應用程式開發入門初體驗 58 | 59 | # 實戰教學(Examples) 60 | - [X] Fetch 61 | - [X] Firebase 62 | - [X] NewTab 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Ch09/examples/dist/js/bundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n
\n

' + value.Variety + ' ' + value.Name + ' ' + value.HairType + '

\n

' + value.Resettlement + '

\n

\u806F\u7D61\u96FB\u8A71 \u806F\u7D61\u4FE1\u7BB1

\n
\n \n \n '; 20 | }); 21 | document.querySelector('#data-list').innerHTML = str; 22 | }; 23 | 24 | fetchDemo(); 25 | 26 | },{}]},{},[1]); 27 | -------------------------------------------------------------------------------- /Ch11/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 10 | 11 | 29 |
30 |
31 |
32 |

統計資料

33 |
34 | 35 |
36 |
37 |

詳細支出

38 |
39 |
40 |
41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Ch12/examples2/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import gulp from 'gulp'; 3 | import sass from 'gulp-sass'; 4 | import uglify from 'gulp-uglify'; 5 | import connect from 'gulp-connect'; 6 | import browserify from 'browserify'; 7 | import babelify from 'babelify'; 8 | // 轉成 gulp 讀取的 vinyl(黑膠)流 9 | import source from 'vinyl-source-stream'; 10 | import image from 'gulp-image'; 11 | 12 | const dirs = { 13 | src: 'src', 14 | dest: 'dist' 15 | }; 16 | 17 | const stylesPaths = { 18 | src: `${dirs.src}/styles/*.scss`, 19 | dest: `${dirs.dest}/css` 20 | }; 21 | 22 | const scriptsPaths = { 23 | src: `${dirs.src}/scripts/*.js`, 24 | dest: `${dirs.dest}/js` 25 | }; 26 | 27 | const imagesPaths = { 28 | src: `${dirs.src}/images/*`, 29 | dest: `${dirs.dest}/img` 30 | }; 31 | 32 | gulp.task('styles', () => { 33 | gulp.src(stylesPaths.src) 34 | .pipe(sass()) // 編譯 Scss 35 | .pipe(gulp.dest(stylesPaths.dest)) // 36 | .pipe(connect.reload()); 37 | }); 38 | 39 | gulp.task('scripts', function(){ 40 | return browserify({ 41 | entries: ['./src/scripts/main.js'] 42 | }) 43 | .transform(babelify) 44 | .bundle() 45 | .pipe(source('bundle.js')) 46 | .pipe(gulp.dest(scriptsPaths.dest)); 47 | }); 48 | 49 | gulp.task('images', function() { 50 | gulp.src(imagesPaths.src) 51 | .pipe(image()) 52 | .pipe(gulp.dest(imagesPaths.dest)); 53 | }); 54 | 55 | gulp.task('copy-html', function(){ 56 | return gulp.src(`${dirs.src}/*.html`).pipe(gulp.dest('dist')) 57 | }); 58 | 59 | gulp.task('server', function () { 60 | connect.server({ 61 | root: ['./dist'], 62 | livereload: true, 63 | port: 7777, 64 | }); 65 | }); 66 | 67 | gulp.task('watch', function () { 68 | gulp.watch(stylesPaths.src, ['styles']); 69 | gulp.watch(scriptsPaths.src, ['scripts']); 70 | }); 71 | 72 | gulp.task('default', ['copy-html', 'scripts', 'styles', 'images', 'server', 'watch']); 73 | gulp.task('build', ['copy-html', 'scripts', 'styles', 'images']); 74 | -------------------------------------------------------------------------------- /Ch12/examples1/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import gulp from 'gulp'; 3 | import sass from 'gulp-sass'; 4 | import uglify from 'gulp-uglify'; 5 | import connect from 'gulp-connect'; 6 | import browserify from 'browserify'; 7 | import babelify from 'babelify'; 8 | // 轉成 gulp 讀取的 vinyl(黑膠)流 9 | import source from 'vinyl-source-stream'; 10 | import image from 'gulp-image'; 11 | 12 | const dirs = { 13 | src: 'src', 14 | dest: 'dist' 15 | }; 16 | 17 | const stylesPaths = { 18 | src: `${dirs.src}/styles/*.scss`, 19 | dest: `${dirs.dest}/css` 20 | }; 21 | 22 | const scriptsPaths = { 23 | src: `${dirs.src}/scripts/*.js`, 24 | dest: `${dirs.dest}/js` 25 | }; 26 | 27 | const imagesPaths = { 28 | src: `${dirs.src}/images/*`, 29 | dest: `${dirs.dest}/img` 30 | }; 31 | 32 | gulp.task('styles', () => { 33 | gulp.src(stylesPaths.src) 34 | .pipe(sass()) // 編譯 Scss 35 | .pipe(gulp.dest(stylesPaths.dest)) // 36 | .pipe(connect.reload()); 37 | }); 38 | 39 | gulp.task('scripts', function(){ 40 | return browserify({ 41 | entries: ['./src/scripts/main.js'] 42 | }) 43 | .transform(babelify) 44 | .bundle() 45 | .pipe(source('bundle.js')) 46 | .pipe(gulp.dest(scriptsPaths.dest)); 47 | }); 48 | 49 | gulp.task('images', function() { 50 | gulp.src(imagesPaths.src) 51 | .pipe(image()) 52 | .pipe(gulp.dest(imagesPaths.dest)); 53 | }); 54 | 55 | gulp.task('copy-index', function(){ 56 | return gulp.src(`${dirs.src}/*.{json|html}`).pipe(gulp.dest('dist')) 57 | }); 58 | 59 | gulp.task('server', function () { 60 | connect.server({ 61 | root: ['./dist'], 62 | livereload: true, 63 | port: 7777, 64 | }); 65 | }); 66 | 67 | gulp.task('watch', function () { 68 | gulp.watch(stylesPaths.src, ['styles']); 69 | gulp.watch(scriptsPaths.src, ['scripts']); 70 | }); 71 | 72 | gulp.task('default', ['copy-index', 'scripts', 'styles', 'images', 'server', 'watch']); 73 | gulp.task('build', ['copy-index', 'scripts', 'styles', 'images']); 74 | -------------------------------------------------------------------------------- /Ch16/examples/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('examples:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /Ch01/examples/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import sass from 'gulp-sass';// import autoprefixer from 'gulp-autoprefixer'; 5 | import uglify from 'gulp-uglify';// import autoprefixer from 'gulp-autoprefixer'; 6 | import image from 'gulp-image'; 7 | import connect from 'gulp-connect';// import autoprefixer from 'gulp-autoprefixer'; 8 | import browserify from 'browserify';// import autoprefixer from 'gulp-autoprefixer'; 9 | import babelify from 'babelify';// import autoprefixer from 'gulp-autoprefixer'; 10 | import source from 'vinyl-source-stream'; 11 | 12 | const dirs = { 13 | src: 'src', 14 | dest: 'dist' 15 | }; 16 | 17 | const stylesPaths = { 18 | src: `${dirs.src}/styles/*.scss`, 19 | dest: `${dirs.dest}/css` 20 | }; 21 | 22 | const scriptsPaths = { 23 | src: `${dirs.src}/scripts/*.js`, 24 | dest: `${dirs.dest}/js` 25 | }; 26 | 27 | const imagesPaths = { 28 | src: `${dirs.src}/images/*`, 29 | dest: `${dirs.dest}/img` 30 | }; 31 | 32 | gulp.task('styles', () => { 33 | gulp.src(stylesPaths.src) 34 | .pipe(sass()) // 編譯 Scss 35 | .pipe(gulp.dest(stylesPaths.dest)) // 36 | .pipe(connect.reload()); 37 | }); 38 | 39 | gulp.task('scripts', function(){ 40 | return browserify({ 41 | entries: ['./src/scripts/main.js'] 42 | }) 43 | .transform(babelify) 44 | .bundle() 45 | .pipe(source('bundle.js')) 46 | .pipe(gulp.dest(scriptsPaths.dest)); 47 | }); 48 | 49 | gulp.task('images', function() { 50 | gulp.src(imagesPaths.src) 51 | .pipe(image()) 52 | .pipe(gulp.dest(imagesPaths.dest)); 53 | }); 54 | 55 | gulp.task('server', function() { 56 | connect.server({ 57 | livereload: true, 58 | port: 7777, 59 | }); 60 | }); 61 | 62 | gulp.task('watch', function() { 63 | gulp.watch(stylesPaths.src, ['styles']); 64 | gulp.watch(scriptsPaths.src, ['scripts']); 65 | }); 66 | 67 | gulp.task('default', ['scripts', 'styles', 'images', 'server', 'watch']); 68 | gulp.task('build', ['scripts', 'styles', 'images', 'server']); 69 | -------------------------------------------------------------------------------- /Ch02/examples/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import sass from 'gulp-sass';// import autoprefixer from 'gulp-autoprefixer'; 5 | import uglify from 'gulp-uglify';// import autoprefixer from 'gulp-autoprefixer'; 6 | import image from 'gulp-image'; 7 | import connect from 'gulp-connect';// import autoprefixer from 'gulp-autoprefixer'; 8 | import browserify from 'browserify';// import autoprefixer from 'gulp-autoprefixer'; 9 | import babelify from 'babelify';// import autoprefixer from 'gulp-autoprefixer'; 10 | import source from 'vinyl-source-stream'; 11 | 12 | const dirs = { 13 | src: 'src', 14 | dest: 'dist' 15 | }; 16 | 17 | const stylesPaths = { 18 | src: `${dirs.src}/styles/*.scss`, 19 | dest: `${dirs.dest}/css` 20 | }; 21 | 22 | const scriptsPaths = { 23 | src: `${dirs.src}/scripts/*.js`, 24 | dest: `${dirs.dest}/js` 25 | }; 26 | 27 | const imagesPaths = { 28 | src: `${dirs.src}/images/*`, 29 | dest: `${dirs.dest}/img` 30 | }; 31 | 32 | gulp.task('styles', () => { 33 | gulp.src(stylesPaths.src) 34 | .pipe(sass()) // 編譯 Scss 35 | .pipe(gulp.dest(stylesPaths.dest)) // 36 | .pipe(connect.reload()); 37 | }); 38 | 39 | gulp.task('scripts', function(){ 40 | return browserify({ 41 | entries: ['./src/scripts/main.js'] 42 | }) 43 | .transform(babelify) 44 | .bundle() 45 | .pipe(source('bundle.js')) 46 | .pipe(gulp.dest(scriptsPaths.dest)); 47 | }); 48 | 49 | gulp.task('images', function() { 50 | gulp.src(imagesPaths.src) 51 | .pipe(image()) 52 | .pipe(gulp.dest(imagesPaths.dest)); 53 | }); 54 | 55 | gulp.task('server', function() { 56 | connect.server({ 57 | livereload: true, 58 | port: 7777, 59 | }); 60 | }); 61 | 62 | gulp.task('watch', function() { 63 | gulp.watch(stylesPaths.src, ['styles']); 64 | gulp.watch(scriptsPaths.src, ['scripts']); 65 | }); 66 | 67 | gulp.task('default', ['scripts', 'styles', 'images', 'server', 'watch']); 68 | gulp.task('build', ['scripts', 'styles', 'images', 'server']); 69 | -------------------------------------------------------------------------------- /Ch03/examples2/gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import sass from 'gulp-sass';// import autoprefixer from 'gulp-autoprefixer'; 5 | import uglify from 'gulp-uglify';// import autoprefixer from 'gulp-autoprefixer'; 6 | import image from 'gulp-image'; 7 | import connect from 'gulp-connect';// import autoprefixer from 'gulp-autoprefixer'; 8 | import browserify from 'browserify';// import autoprefixer from 'gulp-autoprefixer'; 9 | import babelify from 'babelify';// import autoprefixer from 'gulp-autoprefixer'; 10 | import source from 'vinyl-source-stream'; 11 | 12 | const dirs = { 13 | src: 'src', 14 | dest: 'dist' 15 | }; 16 | 17 | const stylesPaths = { 18 | src: `${dirs.src}/styles/*.scss`, 19 | dest: `${dirs.dest}/css` 20 | }; 21 | 22 | const scriptsPaths = { 23 | src: `${dirs.src}/scripts/*.js`, 24 | dest: `${dirs.dest}/js` 25 | }; 26 | 27 | const imagesPaths = { 28 | src: `${dirs.src}/images/*`, 29 | dest: `${dirs.dest}/img` 30 | }; 31 | 32 | gulp.task('styles', () => { 33 | gulp.src(stylesPaths.src) 34 | .pipe(sass()) // 編譯 Scss 35 | .pipe(gulp.dest(stylesPaths.dest)) // 36 | .pipe(connect.reload()); 37 | }); 38 | 39 | gulp.task('scripts', function(){ 40 | return browserify({ 41 | entries: ['./src/scripts/main.js'] 42 | }) 43 | .transform(babelify) 44 | .bundle() 45 | .pipe(source('bundle.js')) 46 | .pipe(gulp.dest(scriptsPaths.dest)); 47 | }); 48 | 49 | gulp.task('images', function() { 50 | gulp.src(imagesPaths.src) 51 | .pipe(image()) 52 | .pipe(gulp.dest(imagesPaths.dest)); 53 | }); 54 | 55 | gulp.task('server', function() { 56 | connect.server({ 57 | livereload: true, 58 | port: 7777, 59 | }); 60 | }); 61 | 62 | gulp.task('watch', function() { 63 | gulp.watch(stylesPaths.src, ['styles']); 64 | gulp.watch(scriptsPaths.src, ['scripts']); 65 | }); 66 | 67 | gulp.task('default', ['scripts', 'styles', 'images', 'server', 'watch']); 68 | gulp.task('build', ['scripts', 'styles', 'images', 'server']); 69 | -------------------------------------------------------------------------------- /Ch12/examples1/src/styles/main.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 30px; 3 | font-family: "Lantinghei TC", Hiragino Kaku Gothic Pro, Heiti TC, "微軟正黑體", "STHeiti Light", "Microsoft Yahei", "Microsoft JhengHei", Helvetica, sans-serif !important; 4 | } 5 | 6 | .show-img-area { 7 | width: 450px; 8 | margin: 0 auto; 9 | } 10 | 11 | .show-img-area img { 12 | display: block; 13 | width: 390px; 14 | height: auto; 15 | transform:rotate(7deg); 16 | -ms-transform:rotate(7deg); /* IE 9 */ 17 | -moz-transform:rotate(7deg); /* Firefox */ 18 | -webkit-transform:rotate(7deg); /* Safari 和 Chrome */ 19 | -o-transform:rotate(7deg); /* Opera */ 20 | } 21 | 22 | .show-img-area img { 23 | margin: 0 auto; 24 | transform:rotate(7deg); 25 | -ms-transform:rotate(7deg); /* IE 9 */ 26 | -moz-transform:rotate(7deg); /* Firefox */ 27 | -webkit-transform:rotate(7deg); /* Safari 和 Chrome */ 28 | -o-transform:rotate(7deg); /* Opera */ 29 | 30 | -webkit-animation: fadein 2s; /* Safari, Chrome and Opera > 12.1 */ 31 | -moz-animation: fadein 2s; /* Firefox < 16 */ 32 | -ms-animation: fadein 2s; /* Internet Explorer */ 33 | -o-animation: fadein 2s; /* Opera < 12.1 */ 34 | animation: fadein 2s; 35 | } 36 | 37 | .show-img-area img:hover { 38 | transform:rotate(0deg); 39 | -ms-transform:rotate(0deg); /* IE 9 */ 40 | -moz-transform:rotate(0deg); /* Firefox */ 41 | -webkit-transform:rotate(0deg); /* Safari 和 Chrome */ 42 | -o-transform:rotate(0deg); /* Opera */ 43 | transition: 1s; 44 | } 45 | 46 | @keyframes fadein { 47 | from { opacity: 0; } 48 | to { opacity: 1; } 49 | } 50 | 51 | /* Firefox < 16 */ 52 | @-moz-keyframes fadein { 53 | from { opacity: 0; } 54 | to { opacity: 1; } 55 | } 56 | 57 | /* Safari, Chrome and Opera > 12.1 */ 58 | @-webkit-keyframes fadein { 59 | from { opacity: 0; } 60 | to { opacity: 1; } 61 | } 62 | 63 | /* Internet Explorer */ 64 | @-ms-keyframes fadein { 65 | from { opacity: 0; } 66 | to { opacity: 1; } 67 | } 68 | 69 | /* Opera < 12.1 */ 70 | @-o-keyframes fadein { 71 | from { opacity: 0; } 72 | to { opacity: 1; } 73 | } -------------------------------------------------------------------------------- /Ch01/examples/update.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 15 |
16 |

編輯支出

17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Ch02/examples/update.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 15 |
16 |

編輯支出

17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 |
43 | 44 | 45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Ch15/examples/result.json: -------------------------------------------------------------------------------- 1 | [{"title":"批踢踢實業坊","link":"/"},{"title":"看板 Soft_Job","link":"/bbs/Soft_Job/index.html"},{"title":"關於我們","link":"/about.html"},{"title":"聯絡資訊","link":"/contact.html"},{"title":"看板","link":"/bbs/Soft_Job/index.html"},{"title":"精華區","link":"/man/Soft_Job/index.html"},{"title":"最舊","link":"/bbs/Soft_Job/index1.html"},{"title":"‹ 上頁","link":"/bbs/Soft_Job/index1196.html"},{"title":"下頁 ›"},{"title":"最新","link":"/bbs/Soft_Job/index.html"},{"title":"[請益] Offer請益(東森信息/伊頓)","link":"/bbs/Soft_Job/M.1480246413.A.46A.html"},{"title":"[徵才] ASP.net VB.net開發工程師(30-34K)","link":"/bbs/Soft_Job/M.1480261226.A.6C8.html"},{"title":"[請益] 求職作品集內容","link":"/bbs/Soft_Job/M.1480267826.A.D09.html"},{"title":"[請益] 關於研發替代役與正職","link":"/bbs/Soft_Job/M.1480319224.A.ACA.html"},{"title":"Fw: [問卷] 跨國虛擬軟體開發團隊研究問卷","link":"/bbs/Soft_Job/M.1480331340.A.188.html"},{"title":"[轉讓] 聯成電腦課程","link":"/bbs/Soft_Job/M.1480337858.A.EA3.html"},{"title":"Re: [徵才] ASP.net VB.net開發工程師(30-34K)","link":"/bbs/Soft_Job/M.1480338553.A.1EC.html"},{"title":"[轉讓] CCNA_200-125認證 線上課程","link":"/bbs/Soft_Job/M.1480343236.A.9D8.html"},{"title":"[請益] 花錢上迷你型java課程 @值得嗎???","link":"/bbs/Soft_Job/M.1480354876.A.4F3.html"},{"title":"[徵才] 網住超越有限公司徵前端工程師(45~60K/M)","link":"/bbs/Soft_Job/M.1480385913.A.77D.html"},{"title":"Re: [閒聊] 微妙的合作關係","link":"/bbs/Soft_Job/M.1480392927.A.84D.html"},{"title":"Re: [請益] 新鮮人面對將來的android工作如何準","link":"/bbs/Soft_Job/M.1480403175.A.EAE.html"},{"title":"Re: [徵才] ASP.net VB.net開發工程師(30-34K)","link":"/bbs/Soft_Job/M.1480426788.A.F86.html"},{"title":"[心得] AppWork區塊鏈研討會心得","link":"/bbs/Soft_Job/M.1480427852.A.4C0.html"},{"title":"[請益] 資工資管研究所選擇","link":"/bbs/Soft_Job/M.1480433819.A.7B9.html"},{"title":"[求票] GDG DevFest Taipei 2016","link":"/bbs/Soft_Job/M.1480465051.A.517.html"},{"title":"[請益] 假日班?","link":"/bbs/Soft_Job/M.1480469258.A.A7E.html"},{"title":"[公告] 2016年1月1日 新版規上路! 新年快樂","link":"/bbs/Soft_Job/M.1451578149.A.2F4.html"},{"title":"[公告] 蒐集板上曾發文加班不符合勞基法者","link":"/bbs/Soft_Job/M.1453196050.A.D41.html"},{"title":"[情報] 11月訓練課程與付費APP與網站分享","link":"/bbs/Soft_Job/M.1459783651.A.DBE.html"},{"title":"[情報] 11月社群活動與免費APP與網站分享","link":"/bbs/Soft_Job/M.1459784168.A.0C8.html"}] -------------------------------------------------------------------------------- /Ch12/examples2/dist/js/bundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { 21 | days = parseInt(seconds_left / 86400); 22 | seconds_left = seconds_left % 86400; 23 | 24 | hours = parseInt(seconds_left / 3600); 25 | seconds_left = seconds_left % 3600; 26 | 27 | minutes = parseInt(seconds_left / 60); 28 | seconds = parseInt(seconds_left % 60); 29 | 30 | // format countdown string + set tag value 31 | countdown.className = 'countdown'; 32 | countdown.innerHTML = days + "天, " + hours + "小時, " + minutes + "分, " + seconds + "秒"; 33 | } else { 34 | countdown.className = 'countdown'; 35 | countdown.innerHTML = "恭喜考完!XD"; 36 | clearInterval(init); 37 | } 38 | }, 1000); 39 | }; 40 | 41 | },{}]},{},[1]); 42 | -------------------------------------------------------------------------------- /Ch12/examples1/dist/css/main.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | body { 3 | margin: 30px; 4 | font-family: "Lantinghei TC", Hiragino Kaku Gothic Pro, Heiti TC, "微軟正黑體", "STHeiti Light", "Microsoft Yahei", "Microsoft JhengHei", Helvetica, sans-serif !important; } 5 | 6 | .show-img-area { 7 | width: 450px; 8 | margin: 0 auto; } 9 | 10 | .show-img-area img { 11 | display: block; 12 | width: 390px; 13 | height: auto; 14 | transform: rotate(7deg); 15 | -ms-transform: rotate(7deg); 16 | /* IE 9 */ 17 | -moz-transform: rotate(7deg); 18 | /* Firefox */ 19 | -webkit-transform: rotate(7deg); 20 | /* Safari 和 Chrome */ 21 | -o-transform: rotate(7deg); 22 | /* Opera */ } 23 | 24 | .show-img-area img { 25 | margin: 0 auto; 26 | transform: rotate(7deg); 27 | -ms-transform: rotate(7deg); 28 | /* IE 9 */ 29 | -moz-transform: rotate(7deg); 30 | /* Firefox */ 31 | -webkit-transform: rotate(7deg); 32 | /* Safari 和 Chrome */ 33 | -o-transform: rotate(7deg); 34 | /* Opera */ 35 | -webkit-animation: fadein 2s; 36 | /* Safari, Chrome and Opera > 12.1 */ 37 | -moz-animation: fadein 2s; 38 | /* Firefox < 16 */ 39 | -ms-animation: fadein 2s; 40 | /* Internet Explorer */ 41 | -o-animation: fadein 2s; 42 | /* Opera < 12.1 */ 43 | animation: fadein 2s; } 44 | 45 | .show-img-area img:hover { 46 | transform: rotate(0deg); 47 | -ms-transform: rotate(0deg); 48 | /* IE 9 */ 49 | -moz-transform: rotate(0deg); 50 | /* Firefox */ 51 | -webkit-transform: rotate(0deg); 52 | /* Safari 和 Chrome */ 53 | -o-transform: rotate(0deg); 54 | /* Opera */ 55 | transition: 1s; } 56 | 57 | @keyframes fadein { 58 | from { 59 | opacity: 0; } 60 | to { 61 | opacity: 1; } } 62 | 63 | /* Firefox < 16 */ 64 | @-moz-keyframes fadein { 65 | from { 66 | opacity: 0; } 67 | to { 68 | opacity: 1; } } 69 | 70 | /* Safari, Chrome and Opera > 12.1 */ 71 | @-webkit-keyframes fadein { 72 | from { 73 | opacity: 0; } 74 | to { 75 | opacity: 1; } } 76 | 77 | /* Internet Explorer */ 78 | @-ms-keyframes fadein { 79 | from { 80 | opacity: 0; } 81 | to { 82 | opacity: 1; } } 83 | 84 | /* Opera < 12.1 */ 85 | @-o-keyframes fadein { 86 | from { 87 | opacity: 0; } 88 | to { 89 | opacity: 1; } } 90 | -------------------------------------------------------------------------------- /Ch03/examples2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Pokemon Fight 精靈快打 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 |
23 |

Pokemon Fight 精靈快打

24 |
25 |
26 | 27 |
28 |
29 |
30 |
    31 |
    32 |
    33 |
      34 |
      35 |
      36 | Fork me on GitHub 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Ch01/examples/README.md: -------------------------------------------------------------------------------- 1 | # iRich 愛記帳 2 | 3 | 1. Get a database reference 4 | 5 | 2. Reading and writing data 6 | 7 | - Listen for value events 8 | 9 | 3. Updating or deleting data 10 | 11 | The simplest way to delete data is to call remove() on a reference to the location of that data. 12 | 13 | You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call. 14 | 15 | ``` 16 | npm install --save-dev gulp gulp-sass gulp-uglify gulp-connect 17 | ``` 18 | 19 | # 延伸閱讀 20 | 1. [gulp 學習筆記](https://www.gitbook.com/book/kejyuntw/gulp-learning-notes/details) 21 | 2. [Getting started with Gulp and Sass](http://ryanchristiani.com/getting-started-with-gulp-and-sass/) 22 | 3. [Using ES6 with gulp](https://markgoodyear.com/2015/06/using-es6-with-gulp/) 23 | 4. [Setting up an ES6 Project Using Babel and Browserify](https://www.sitepoint.com/setting-up-es6-project-using-babel-browserify/) 24 | 5. [WEBPACK入門教學筆記](http://blog.kkbruce.net/2015/10/webpack.html#.WAIU7JN96zY) 25 | 6. [Setting up ES6+Babel+Gulp](http://ramkulkarni.com/blog/setting-up-es6-babel-gulp/) 26 | 7. [Configuring Webpack to write JS with ES6/ES2015 on browser](https://medium.com/daily-js-tips/configuring-webpack-to-write-js-with-es6-es2015-on-browser-cd089a79ecea#.uo1psi41n) 27 | 8. [求大牛帮忙,用webpack 打包jquery、bootstrap时出错。](http://react-china.org/t/webpack-jquery-bootstrap/1669) 28 | 9. [How-to setup Webpack on an ES6 React Application with SASS?](https://www.jonathan-petitcolas.com/2015/05/15/howto-setup-webpack-on-es6-react-application-with-sass.html) 29 | 10. [動物認養](http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx) 30 | 11. [如何使用CSS的「text-overflow: ellipsis;」屬性限制內容字數?](http://www.astralweb.com.tw/css-ellipsis/) 31 | 12. [Javascript iterate object](http://stackoverflow.com/questions/14379274/javascript-iterate-object) 32 | 13. [Object.keys()](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) 33 | 14. [Attaching event handlers to dynamically created JavaScript elements](https://toddmotto.com/attaching-event-handlers-to-dynamically-created-javascript-elements/) 34 | 15. [[宅] javascript筆記 - window.location類別](http://cat-son.blogspot.tw/2012/11/javascript-windowlocation.html) -------------------------------------------------------------------------------- /Ch02/examples/README.md: -------------------------------------------------------------------------------- 1 | # iRich 愛記帳 2 | 3 | 1. Get a database reference 4 | 5 | 2. Reading and writing data 6 | 7 | - Listen for value events 8 | 9 | 3. Updating or deleting data 10 | 11 | The simplest way to delete data is to call remove() on a reference to the location of that data. 12 | 13 | You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call. 14 | 15 | ``` 16 | npm install --save-dev gulp gulp-sass gulp-uglify gulp-connect 17 | ``` 18 | 19 | # 延伸閱讀 20 | 1. [gulp 學習筆記](https://www.gitbook.com/book/kejyuntw/gulp-learning-notes/details) 21 | 2. [Getting started with Gulp and Sass](http://ryanchristiani.com/getting-started-with-gulp-and-sass/) 22 | 3. [Using ES6 with gulp](https://markgoodyear.com/2015/06/using-es6-with-gulp/) 23 | 4. [Setting up an ES6 Project Using Babel and Browserify](https://www.sitepoint.com/setting-up-es6-project-using-babel-browserify/) 24 | 5. [WEBPACK入門教學筆記](http://blog.kkbruce.net/2015/10/webpack.html#.WAIU7JN96zY) 25 | 6. [Setting up ES6+Babel+Gulp](http://ramkulkarni.com/blog/setting-up-es6-babel-gulp/) 26 | 7. [Configuring Webpack to write JS with ES6/ES2015 on browser](https://medium.com/daily-js-tips/configuring-webpack-to-write-js-with-es6-es2015-on-browser-cd089a79ecea#.uo1psi41n) 27 | 8. [求大牛帮忙,用webpack 打包jquery、bootstrap时出错。](http://react-china.org/t/webpack-jquery-bootstrap/1669) 28 | 9. [How-to setup Webpack on an ES6 React Application with SASS?](https://www.jonathan-petitcolas.com/2015/05/15/howto-setup-webpack-on-es6-react-application-with-sass.html) 29 | 10. [動物認養](http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx) 30 | 11. [如何使用CSS的「text-overflow: ellipsis;」屬性限制內容字數?](http://www.astralweb.com.tw/css-ellipsis/) 31 | 12. [Javascript iterate object](http://stackoverflow.com/questions/14379274/javascript-iterate-object) 32 | 13. [Object.keys()](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) 33 | 14. [Attaching event handlers to dynamically created JavaScript elements](https://toddmotto.com/attaching-event-handlers-to-dynamically-created-javascript-elements/) 34 | 15. [[宅] javascript筆記 - window.location類別](http://cat-son.blogspot.tw/2012/11/javascript-windowlocation.html) -------------------------------------------------------------------------------- /Ch03/examples2/README.md: -------------------------------------------------------------------------------- 1 | # iRich 愛記帳 2 | 3 | 1. Get a database reference 4 | 5 | 2. Reading and writing data 6 | 7 | - Listen for value events 8 | 9 | 3. Updating or deleting data 10 | 11 | The simplest way to delete data is to call remove() on a reference to the location of that data. 12 | 13 | You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call. 14 | 15 | ``` 16 | npm install --save-dev gulp gulp-sass gulp-uglify gulp-connect 17 | ``` 18 | 19 | # 延伸閱讀 20 | 1. [gulp 學習筆記](https://www.gitbook.com/book/kejyuntw/gulp-learning-notes/details) 21 | 2. [Getting started with Gulp and Sass](http://ryanchristiani.com/getting-started-with-gulp-and-sass/) 22 | 3. [Using ES6 with gulp](https://markgoodyear.com/2015/06/using-es6-with-gulp/) 23 | 4. [Setting up an ES6 Project Using Babel and Browserify](https://www.sitepoint.com/setting-up-es6-project-using-babel-browserify/) 24 | 5. [WEBPACK入門教學筆記](http://blog.kkbruce.net/2015/10/webpack.html#.WAIU7JN96zY) 25 | 6. [Setting up ES6+Babel+Gulp](http://ramkulkarni.com/blog/setting-up-es6-babel-gulp/) 26 | 7. [Configuring Webpack to write JS with ES6/ES2015 on browser](https://medium.com/daily-js-tips/configuring-webpack-to-write-js-with-es6-es2015-on-browser-cd089a79ecea#.uo1psi41n) 27 | 8. [求大牛帮忙,用webpack 打包jquery、bootstrap时出错。](http://react-china.org/t/webpack-jquery-bootstrap/1669) 28 | 9. [How-to setup Webpack on an ES6 React Application with SASS?](https://www.jonathan-petitcolas.com/2015/05/15/howto-setup-webpack-on-es6-react-application-with-sass.html) 29 | 10. [動物認養](http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx) 30 | 11. [如何使用CSS的「text-overflow: ellipsis;」屬性限制內容字數?](http://www.astralweb.com.tw/css-ellipsis/) 31 | 12. [Javascript iterate object](http://stackoverflow.com/questions/14379274/javascript-iterate-object) 32 | 13. [Object.keys()](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) 33 | 14. [Attaching event handlers to dynamically created JavaScript elements](https://toddmotto.com/attaching-event-handlers-to-dynamically-created-javascript-elements/) 34 | 15. [[宅] javascript筆記 - window.location類別](http://cat-son.blogspot.tw/2012/11/javascript-windowlocation.html) -------------------------------------------------------------------------------- /Ch11/examples/README.md: -------------------------------------------------------------------------------- 1 | # iRich 愛記帳 2 | 3 | 1. Get a database reference 4 | 5 | 2. Reading and writing data 6 | 7 | - Listen for value events 8 | 9 | 3. Updating or deleting data 10 | 11 | The simplest way to delete data is to call remove() on a reference to the location of that data. 12 | 13 | You can also delete by specifying null as the value for another write operation such as set() or update(). You can use this technique with update() to delete multiple children in a single API call. 14 | 15 | ``` 16 | npm install --save-dev gulp gulp-sass gulp-uglify gulp-connect 17 | ``` 18 | 19 | # 延伸閱讀 20 | 1. [gulp 學習筆記](https://www.gitbook.com/book/kejyuntw/gulp-learning-notes/details) 21 | 2. [Getting started with Gulp and Sass](http://ryanchristiani.com/getting-started-with-gulp-and-sass/) 22 | 3. [Using ES6 with gulp](https://markgoodyear.com/2015/06/using-es6-with-gulp/) 23 | 4. [Setting up an ES6 Project Using Babel and Browserify](https://www.sitepoint.com/setting-up-es6-project-using-babel-browserify/) 24 | 5. [WEBPACK入門教學筆記](http://blog.kkbruce.net/2015/10/webpack.html#.WAIU7JN96zY) 25 | 6. [Setting up ES6+Babel+Gulp](http://ramkulkarni.com/blog/setting-up-es6-babel-gulp/) 26 | 7. [Configuring Webpack to write JS with ES6/ES2015 on browser](https://medium.com/daily-js-tips/configuring-webpack-to-write-js-with-es6-es2015-on-browser-cd089a79ecea#.uo1psi41n) 27 | 8. [求大牛帮忙,用webpack 打包jquery、bootstrap时出错。](http://react-china.org/t/webpack-jquery-bootstrap/1669) 28 | 9. [How-to setup Webpack on an ES6 React Application with SASS?](https://www.jonathan-petitcolas.com/2015/05/15/howto-setup-webpack-on-es6-react-application-with-sass.html) 29 | 10. [動物認養](http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx) 30 | 11. [如何使用CSS的「text-overflow: ellipsis;」屬性限制內容字數?](http://www.astralweb.com.tw/css-ellipsis/) 31 | 12. [Javascript iterate object](http://stackoverflow.com/questions/14379274/javascript-iterate-object) 32 | 13. [Object.keys()](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) 33 | 14. [Attaching event handlers to dynamically created JavaScript elements](https://toddmotto.com/attaching-event-handlers-to-dynamically-created-javascript-elements/) 34 | 15. [[宅] javascript筆記 - window.location類別](http://cat-son.blogspot.tw/2012/11/javascript-windowlocation.html) -------------------------------------------------------------------------------- /Ch02/examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 10 | 11 | 29 |
      30 |
      31 |
      32 |

      統計資料

      33 |
      34 | 35 |
      36 |
      37 |
      38 |

      詳細支出

      39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Ch18/examples/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Ch02/examples/create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 10 | 11 | 27 |
      28 |

      新增支出

      29 |
      30 |
      31 |
      32 | 33 | 34 |
      35 |
      36 | 37 | 46 |
      47 |
      48 | 49 | 50 |
      51 |
      52 | 53 | 54 |
      55 | 56 | 57 | 58 |
      59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Ch11/examples/create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 10 | 11 | 27 |
      28 |

      新增支出

      29 |
      30 |
      31 |
      32 | 33 | 34 |
      35 |
      36 | 37 | 46 |
      47 |
      48 | 49 | 50 |
      51 |
      52 | 53 | 54 |
      55 | 56 | 57 | 58 |
      59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Ch11/examples/update.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 愛記帳 iRich 6 | 7 | 8 | 9 | 10 | 11 | 27 |
      28 |

      編輯支出

      29 |
      30 |
      31 |
      32 | 33 | 34 |
      35 |
      36 | 37 | 46 |
      47 |
      48 | 49 | 50 |
      51 |
      52 | 53 | 54 |
      55 | 56 | 57 | 58 |
      59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /Ch03/examples2/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | import Monster from './Monster'; 2 | const playBtn = document.querySelector('#play'); 3 | playBtn.addEventListener('click', play); 4 | 5 | const charmander = new Monster('小火龍', './dist/img/charmander.png', 100, '火系'); 6 | const squirtle = new Monster('傑尼龜', './dist/img/squirtle.png', 100, '水系'); 7 | const bulbasaur = new Monster('妙蛙種子', './dist/img/bulbasaur.png', 100, '草系'); 8 | 9 | const cyndaquil = new Monster('火球鼠', './dist/img/cyndaquil.png', 100, '火系'); 10 | const totodile = new Monster('小鋸鱷', './dist/img/totodile.png', 100, '水系'); 11 | const chikorita = new Monster('菊草葉', './dist/img/chikorita.png', 100, '草系'); 12 | 13 | const monsters = [charmander, squirtle, bulbasaur]; 14 | const competitors = [cyndaquil, totodile, chikorita]; 15 | 16 | let myHP = 3; 17 | let cpHP = 3; 18 | 19 | function play() { 20 | let isFight = true; 21 | let choice = parseInt(prompt('小治,請問你要派出哪隻神奇寶貝呢(請輸入數字)? ---------- 0 小火龍 1 傑尼龜 2 妙蛙種子')); 22 | let competitorChoice = Math.floor(Math.random() * 3); 23 | 24 | const winner = checkWinner(); 25 | 26 | if (winner) { 27 | alert(`勝負已分,獲勝的是${winner}選手`); 28 | } else { 29 | while (!competitors[competitorChoice].isAlive()) { 30 | competitorChoice = Math.floor(Math.random() * 3); 31 | } 32 | 33 | if (!(choice < 3) || !(choice >= 0)) { 34 | alert('請輸入正確數字喔!'); 35 | return 0; 36 | } 37 | 38 | if (monsters[choice].isAlive()) { 39 | switch (choice) { 40 | case 0: 41 | if (competitorChoice === 0) { 42 | pk(choice, competitorChoice, 'tie'); 43 | showView(choice, competitorChoice); 44 | } else if (competitorChoice === 1) { 45 | pk(choice, competitorChoice, 'lost'); 46 | showView(choice, competitorChoice); 47 | } else { 48 | pk(choice, competitorChoice, 'win'); 49 | showView(choice, competitorChoice); 50 | } 51 | break; 52 | case 1: 53 | if (competitorChoice === 0) { 54 | pk(choice, competitorChoice, 'win'); 55 | showView(choice, competitorChoice); 56 | } else if (competitorChoice === 1) { 57 | pk(choice, competitorChoice, 'tie'); 58 | showView(choice, competitorChoice); 59 | } else { 60 | pk(choice, competitorChoice, 'lost'); 61 | showView(choice, competitorChoice); 62 | } 63 | break; 64 | case 2: 65 | if (competitorChoice === 0) { 66 | pk(choice, competitorChoice, 'lost'); 67 | showView(choice, competitorChoice); 68 | } else if (competitorChoice === 1) { 69 | pk(choice, competitorChoice, 'win'); 70 | showView(choice, competitorChoice); 71 | } else { 72 | pk(choice, competitorChoice, 'tie'); 73 | showView(choice, competitorChoice); 74 | } 75 | break; 76 | } 77 | } else { 78 | alert(`${monsters[choice].getName()} 已失去戰鬥能力!`); 79 | choice = -1; 80 | } 81 | } 82 | 83 | } 84 | 85 | function checkWinner() { 86 | if (myHP === 0 && cpHP === 0) { 87 | return '小治和小帽'; 88 | } else if (cpHP === 0) { 89 | return '小治' 90 | } else if (myHP === 0) { 91 | return '小帽'; 92 | } else { 93 | return false; 94 | } 95 | } 96 | 97 | function checkAlive(choice, competitorChoice) { 98 | if (!monsters[choice].isAlive()) { 99 | myHP -= 1; 100 | } 101 | if (!competitors[competitorChoice].isAlive()) { 102 | cpHP -= 1; 103 | } 104 | } 105 | 106 | function pk(choice, competitorChoice, type) { 107 | switch (type) { 108 | case 'win': 109 | monsters[choice].setHurt(5); 110 | competitors[competitorChoice].setHurt(50); 111 | checkAlive(choice, competitorChoice); 112 | alert(`就決定是你了!${monsters[choice].getName()} ------ 對方派出${competitors[competitorChoice].getName()},太好了,抓住對方弱點! HP -5,${monsters[choice].getName()} HP 還剩 ${monsters[choice].getHP()}`); 113 | break; 114 | case 'lost': 115 | monsters[choice].setHurt(50); 116 | competitors[competitorChoice].setHurt(5); 117 | checkAlive(choice, competitorChoice); 118 | alert(`就決定是你了!${monsters[choice].getName()} ------ 對方派出${competitors[competitorChoice].getName()},不好,屬性相剋! HP -50,${monsters[choice].getName()} HP 還剩 ${monsters[choice].getHP()}`); 119 | break; 120 | case 'tie': 121 | monsters[choice].setHurt(30); 122 | competitors[competitorChoice].setHurt(30); 123 | checkAlive(choice, competitorChoice); 124 | alert(`就決定是你了!${monsters[choice].getName()} ------ 對方派出${competitors[competitorChoice].getName()},雙方勢均力敵! HP -30,${monsters[choice].getName()} HP 還剩 ${monsters[choice].getHP()}`); 125 | break; 126 | } 127 | } 128 | 129 | function showView(choice, competitorChoice) { 130 | const player1List = document.querySelector('#player1-list'); 131 | const player2List = document.querySelector('#player2-list'); 132 | 133 | player1List.innerHTML = ` 134 |
    • 135 | 136 |
    • 137 |
    • 138 |
      139 |
      140 | ${monsters[choice].getHP()}% 141 |
      142 |
      143 |
    • 144 |
    • ${monsters[choice].getName()}
    • 145 |
    • 屬性:${monsters[choice].getType()}
    • 146 | `; 147 | 148 | player2List.innerHTML = ` 149 |
    • 150 | 151 |
    • 152 |
    • 153 |
      154 |
      155 | ${competitors[competitorChoice].getHP()}% 156 |
      157 |
      158 |
    • 159 |
    • ${competitors[competitorChoice].getName()}
    • 160 |
    • 屬性:${competitors[competitorChoice].getType()}
    • 161 | `; 162 | } 163 | 164 | 165 | -------------------------------------------------------------------------------- /Ch11/examples/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid'; 2 | import Chart from 'chart.js' 3 | 4 | const config = { 5 | apiKey: "AIzaSyCKePFlevYTQY5vNtisZFBcaoiSHlXZM5E", 6 | authDomain: "fir-irich-example.firebaseapp.com", 7 | databaseURL: "https://fir-irich-example.firebaseio.com", 8 | storageBucket: "fir-irich-example.appspot.com", 9 | messagingSenderId: "596812210739" 10 | }; 11 | 12 | firebase.initializeApp(config); 13 | const database = firebase.database(); 14 | 15 | function writeAccountData(id, title, type, number, date) { 16 | const accountRef = database.ref('account/' + id); 17 | accountRef.set({ 18 | title: title, 19 | type: type, 20 | number: number, 21 | date: date 22 | }); 23 | accountRef.on('value', function(snapshot) { 24 | console.log('success'); 25 | window.location = '/'; 26 | }); 27 | } 28 | 29 | function readAccountData() { 30 | let str = ` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | `; 41 | const accountRef = database.ref('account/'); 42 | const infoRef = document.querySelector('#data-chart-info'); 43 | const dataTableRef = document.querySelector('#data-table'); 44 | 45 | accountRef.once('value').then(function(snapshot) { 46 | const data = snapshot.val(); 47 | console.log(data); 48 | if (data === null) { 49 | str += '

      目前沒有資料喔!

      '; 50 | dataTableRef.innerHTML = str; 51 | infoRef.innerHTML = '

      目前沒有資料喔!

      '; 52 | } else { 53 | loadChart(data); 54 | Object.keys(data).forEach(function(key, index) { 55 | str += 56 | ` 57 | 58 | 59 | 60 | 61 | 62 | 66 | 67 | `; 68 | }); 69 | document.querySelector('#data-table').innerHTML = str; 70 | updateBtnListener(); 71 | deleteBtnListener(); 72 | } 73 | }); 74 | } 75 | 76 | function readFormData() { 77 | const params = window.location.search.replace('?', '').split('&'); 78 | console.log(params); 79 | const addFormRef = document.querySelector("#add-form"); 80 | addFormRef.title.value = decodeURI(params[1].split('=')[1]); 81 | addFormRef.type.value = params[2].split('=')[1]; 82 | addFormRef.number.value = params[3].split('=')[1]; 83 | addFormRef.date.value = params[4].split('=')[1]; 84 | } 85 | 86 | function updateData(id, title, type, number, date) { 87 | const accountRef = database.ref('account/' + id); 88 | accountRef.update({ 89 | title: title, 90 | type: type, 91 | number: number, 92 | date: date 93 | }); 94 | accountRef.on('value', function(snapshot) { 95 | console.log('success'); 96 | window.location = '/'; 97 | }); 98 | } 99 | 100 | function deleteData(id) { 101 | const accountRef = database.ref('account/' + id); 102 | accountRef.remove(); 103 | accountRef.on('value', function(snapshot) { 104 | console.log('success'); 105 | window.location = '/'; 106 | }); 107 | } 108 | 109 | function submitListener(submitType) { 110 | const addFormRef = document.querySelector("#add-form"); 111 | addFormRef.addEventListener('submit', function(e) { 112 | e.preventDefault(); 113 | const id = uuid.v4(); 114 | const title = addFormRef.title.value; 115 | const type = addFormRef.type.value; 116 | const number = addFormRef.number.value; 117 | const date = addFormRef.date.value; 118 | if (submitType === 'create') { 119 | writeAccountData(id, title, type, number, date); 120 | } else { 121 | const params = window.location.search.replace('?', '').split('&'); 122 | const id = params[0].split('=')[1]; 123 | updateData(id, title, type, number, date); 124 | } 125 | }); 126 | } 127 | 128 | function updateBtnListener() { 129 | const updateBtns = document.querySelectorAll(".update-btn"); 130 | console.log(updateBtns); 131 | for (let i = 0; i < updateBtns.length; i++) { 132 | updateBtns[i].addEventListener('click', function(e) { 133 | const id = updateBtns[i].getAttribute('data-id'); 134 | e.preventDefault(); 135 | const accountRef = database.ref('account/' + id); 136 | accountRef.on('value', function(snapshot) { 137 | window.location = '/update.html?id=' + id + '&title=' + snapshot.val().title + '&type=' + snapshot.val().type + '&number=' + snapshot.val().number + '&date=' + snapshot.val().date; 138 | }); 139 | }); 140 | } 141 | } 142 | 143 | function deleteBtnListener() { 144 | const deleteBtns = document.querySelectorAll(".delete-btn"); 145 | console.log(deleteBtns); 146 | for (let i = 0; i < deleteBtns.length; i++) { 147 | deleteBtns[i].addEventListener('click', function(e) { 148 | const id = deleteBtns[i].getAttribute('data-id'); 149 | e.preventDefault(); 150 | if (confirm('確認刪除?')) { 151 | deleteData(id); 152 | } else { 153 | alert('你按下取消'); 154 | } 155 | }); 156 | } 157 | } 158 | 159 | function loadChart(rawData) { 160 | let eat = 0; 161 | let life = 0; 162 | let play = 0; 163 | let edu = 0; 164 | let trafic = 0; 165 | let others = 0; 166 | const ctxRef = document.querySelector('#data-chart'); 167 | const infoRef = document.querySelector('#data-chart-info'); 168 | for(const key in rawData) { 169 | if (rawData.hasOwnProperty(key)) { 170 | const type = rawData[key].type; 171 | const number = rawData[key].number; 172 | switch(type) { 173 | case 'eat': 174 | eat += parseInt(number); 175 | break; 176 | case 'life': 177 | life += parseInt(number); 178 | break; 179 | case 'play': 180 | play += parseInt(number); 181 | break; 182 | case 'edu': 183 | edu += parseInt(number); 184 | break; 185 | case 'trafic': 186 | trafic += parseInt(number); 187 | break; 188 | case 'others': 189 | others += parseInt(number); 190 | break; 191 | } 192 | } 193 | } 194 | const data = { 195 | labels: [ 196 | '餐費', 197 | '生活', 198 | '娛樂', 199 | '教育', 200 | '交通', 201 | '其他' 202 | ], 203 | datasets: [{ 204 | data: [eat, life, play, edu, trafic, others], 205 | backgroundColor: [ 206 | 'rgba(255, 99, 132, 0.5)', 207 | 'rgba(54, 162, 235, 0.5)', 208 | 'rgba(255, 206, 86, 0.5)', 209 | 'rgba(75, 192, 192, 0.5)', 210 | 'rgba(153, 102, 255, 0.5)', 211 | 'rgba(255, 159, 64, 0.5)' 212 | ], 213 | borderColor: [ 214 | 'rgba(255, 99, 132, 1)', 215 | 'rgba(54, 162, 235, 1)', 216 | 'rgba(255, 206, 86, 1)', 217 | 'rgba(75, 192, 192, 1)', 218 | 'rgba(153, 102, 255, 1)', 219 | 'rgba(255, 159, 64, 1)' 220 | ], 221 | }] 222 | }; 223 | const myPieChart = new Chart(ctxRef, { 224 | type: 'pie', 225 | data: data, 226 | }); 227 | } 228 | 229 | const path = window.location.pathname; 230 | 231 | switch (path) { 232 | case '/create.html': 233 | submitListener('create'); 234 | break; 235 | case '/update.html': 236 | readFormData(); 237 | submitListener('update'); 238 | break; 239 | default: 240 | readAccountData(); 241 | } 242 | -------------------------------------------------------------------------------- /Ch01/examples/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid'; 2 | import Chart from 'chart.js' 3 | 4 | const config = { 5 | apiKey: "AIzaSyCKePFlevYTQY5vNtisZFBcaoiSHlXZM5E", 6 | authDomain: "fir-irich-example.firebaseapp.com", 7 | databaseURL: "https://fir-irich-example.firebaseio.com", 8 | storageBucket: "fir-irich-example.appspot.com", 9 | messagingSenderId: "596812210739" 10 | }; 11 | 12 | firebase.initializeApp(config); 13 | const database = firebase.database(); 14 | 15 | function writeAccountData(id, title, type, number, date) { 16 | const accountRef = database.ref('account/' + id); 17 | accountRef.set({ 18 | title: title, 19 | type: type, 20 | number: number, 21 | date: date 22 | }); 23 | accountRef.on('value', function(snapshot) { 24 | console.log('success'); 25 | window.location = '/'; 26 | }); 27 | } 28 | 29 | function readAccountData() { 30 | let str = ` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | `; 41 | const accountRef = firebase.database().ref('account/'); 42 | const infoRef = document.querySelector('#data-chart-info'); 43 | const dataTableRef = document.querySelector('#data-table'); 44 | 45 | accountRef.once('value').then(function(snapshot) { 46 | const data = snapshot.val(); 47 | console.log(data); 48 | if (data === null) { 49 | str += '

      目前沒有資料喔!

      '; 50 | dataTableRef.innerHTML = str; 51 | infoRef.innerHTML = '

      目前沒有資料喔!

      '; 52 | } else { 53 | // loadChart(data); 54 | Object.keys(data).forEach(function(key, index) { 55 | str += 56 | ` 57 | 58 | 59 | 60 | 61 | 62 | 66 | 67 | `; 68 | }); 69 | // document.querySelector('#data-table').innerHTML = str; 70 | updateBtnListener(); 71 | deleteBtnListener(); 72 | } 73 | }); 74 | } 75 | 76 | function readFormData() { 77 | const params = window.location.search.replace('?', '').split('&'); 78 | const addFormRef = document.querySelector("#add-form"); 79 | addFormRef.title.value = decodeURI(params[1].split('=')[1]); 80 | addFormRef.type.value = params[2].split('=')[1]; 81 | addFormRef.number.value = params[3].split('=')[1]; 82 | addFormRef.date.value = params[4].split('=')[1]; 83 | } 84 | 85 | function updateData(id, title, type, number, date) { 86 | const accountRef = database.ref('account/' + id); 87 | accountRef.update({ 88 | title: title, 89 | type: type, 90 | number: number, 91 | date: date 92 | }); 93 | accountRef.on('value', function(snapshot) { 94 | console.log('success'); 95 | window.location = '/'; 96 | }); 97 | } 98 | 99 | function deleteData(id) { 100 | const accountRef = database.ref('account/' + id); 101 | accountRef.remove(); 102 | accountRef.on('value', function(snapshot) { 103 | console.log('success'); 104 | window.location = '/'; 105 | }); 106 | } 107 | 108 | function submitListener(submitType) { 109 | const addFormRef = document.querySelector("#add-form"); 110 | addFormRef.addEventListener('submit', function(e) { 111 | e.preventDefault(); 112 | const id = uuid.v4(); 113 | const title = addFormRef.title.value; 114 | const type = addFormRef.type.value; 115 | const number = addFormRef.number.value; 116 | const date = addFormRef.date.value; 117 | if (submitType === 'create') { 118 | writeAccountData(id, title, type, number, date); 119 | } else { 120 | const params = window.location.search.replace('?', '').split('&'); 121 | const id = params[0].split('=')[1]; 122 | updateData(id, title, type, number, date); 123 | } 124 | }); 125 | } 126 | 127 | function updateBtnListener() { 128 | const updateBtns = document.querySelectorAll(".update-btn"); 129 | console.log(updateBtns); 130 | for (let i = 0; i < updateBtns.length; i++) { 131 | updateBtns[i].addEventListener('click', function(e) { 132 | const id = updateBtns[i].getAttribute('data-id'); 133 | e.preventDefault(); 134 | const accountRef = database.ref('account/' + id); 135 | accountRef.on('value', function(snapshot) { 136 | window.location = '/update.html?id=' + id + '&title=' + snapshot.val().title + '&type=' + snapshot.val().type + '&number=' + snapshot.val().number + '&date=' + snapshot.val().date; 137 | }); 138 | }); 139 | } 140 | } 141 | 142 | function deleteBtnListener() { 143 | const deleteBtns = document.querySelectorAll(".delete-btn"); 144 | console.log(deleteBtns); 145 | for (let i = 0; i < deleteBtns.length; i++) { 146 | deleteBtns[i].addEventListener('click', function(e) { 147 | const id = deleteBtns[i].getAttribute('data-id'); 148 | e.preventDefault(); 149 | if (confirm('確認刪除?')) { 150 | deleteData(id); 151 | } else { 152 | alert('你按下取消'); 153 | } 154 | }); 155 | } 156 | } 157 | 158 | function loadChart(rawData) { 159 | let eat = 0; 160 | let life = 0; 161 | let play = 0; 162 | let edu = 0; 163 | let trafic = 0; 164 | let others = 0; 165 | const ctxRef = document.querySelector('#data-chart'); 166 | const infoRef = document.querySelector('#data-chart-info'); 167 | for(const key in rawData) { 168 | if (rawData.hasOwnProperty(key)) { 169 | const type = rawData[key].type; 170 | const number = rawData[key].number; 171 | switch(type) { 172 | case 'eat': 173 | eat += parseInt(number); 174 | break; 175 | case 'life': 176 | life += parseInt(number); 177 | break; 178 | case 'play': 179 | play += parseInt(number); 180 | break; 181 | case 'edu': 182 | edu += parseInt(number); 183 | break; 184 | case 'trafic': 185 | trafic += parseInt(number); 186 | break; 187 | case 'others': 188 | others += parseInt(number); 189 | break; 190 | } 191 | } 192 | } 193 | const data = { 194 | labels: [ 195 | '餐費', 196 | '生活', 197 | '娛樂', 198 | '教育', 199 | '交通', 200 | '其他' 201 | ], 202 | datasets: [{ 203 | data: [eat, life, play, edu, trafic, others], 204 | backgroundColor: [ 205 | 'rgba(255, 99, 132, 0.5)', 206 | 'rgba(54, 162, 235, 0.5)', 207 | 'rgba(255, 206, 86, 0.5)', 208 | 'rgba(75, 192, 192, 0.5)', 209 | 'rgba(153, 102, 255, 0.5)', 210 | 'rgba(255, 159, 64, 0.5)' 211 | ], 212 | borderColor: [ 213 | 'rgba(255, 99, 132, 1)', 214 | 'rgba(54, 162, 235, 1)', 215 | 'rgba(255, 206, 86, 1)', 216 | 'rgba(75, 192, 192, 1)', 217 | 'rgba(153, 102, 255, 1)', 218 | 'rgba(255, 159, 64, 1)' 219 | ], 220 | }] 221 | }; 222 | const myPieChart = new Chart(ctxRef, { 223 | type: 'pie', 224 | data: data, 225 | }); 226 | } 227 | 228 | const path = window.location.pathname; 229 | 230 | // switch (path) { 231 | // case '/create.html': 232 | // submitListener('create'); 233 | // break; 234 | // case '/update.html': 235 | // readFormData(); 236 | // submitListener('update'); 237 | // break; 238 | // default: 239 | // readAccountData(); 240 | // } 241 | -------------------------------------------------------------------------------- /Ch02/examples/src/scripts/main.js: -------------------------------------------------------------------------------- 1 | import uuid from 'uuid'; 2 | import Chart from 'chart.js' 3 | 4 | const config = { 5 | apiKey: "AIzaSyCKePFlevYTQY5vNtisZFBcaoiSHlXZM5E", 6 | authDomain: "fir-irich-example.firebaseapp.com", 7 | databaseURL: "https://fir-irich-example.firebaseio.com", 8 | storageBucket: "fir-irich-example.appspot.com", 9 | messagingSenderId: "596812210739" 10 | }; 11 | 12 | firebase.initializeApp(config); 13 | const database = firebase.database(); 14 | 15 | function writeAccountData(id, title, type, number, date) { 16 | const accountRef = database.ref('account/' + id); 17 | accountRef.set({ 18 | title: title, 19 | type: type, 20 | number: number, 21 | date: date 22 | }); 23 | accountRef.on('value', function(snapshot) { 24 | console.log('success'); 25 | window.location = '/'; 26 | }); 27 | } 28 | 29 | function readAccountData() { 30 | let str = ` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | `; 41 | const accountRef = firebase.database().ref('account/'); 42 | const infoRef = document.querySelector('#data-chart-info'); 43 | const dataTableRef = document.querySelector('#data-table'); 44 | 45 | accountRef.once('value').then(function(snapshot) { 46 | const data = snapshot.val(); 47 | console.log(data); 48 | if (data === null) { 49 | str += '

      目前沒有資料喔!

      '; 50 | dataTableRef.innerHTML = str; 51 | infoRef.innerHTML = '

      目前沒有資料喔!

      '; 52 | } else { 53 | // loadChart(data); 54 | Object.keys(data).forEach(function(key, index) { 55 | str += 56 | ` 57 | 58 | 59 | 60 | 61 | 62 | 66 | 67 | `; 68 | }); 69 | // document.querySelector('#data-table').innerHTML = str; 70 | updateBtnListener(); 71 | deleteBtnListener(); 72 | } 73 | }); 74 | } 75 | 76 | function readFormData() { 77 | const params = window.location.search.replace('?', '').split('&'); 78 | const addFormRef = document.querySelector("#add-form"); 79 | addFormRef.title.value = decodeURI(params[1].split('=')[1]); 80 | addFormRef.type.value = params[2].split('=')[1]; 81 | addFormRef.number.value = params[3].split('=')[1]; 82 | addFormRef.date.value = params[4].split('=')[1]; 83 | } 84 | 85 | function updateData(id, title, type, number, date) { 86 | const accountRef = database.ref('account/' + id); 87 | accountRef.update({ 88 | title: title, 89 | type: type, 90 | number: number, 91 | date: date 92 | }); 93 | accountRef.on('value', function(snapshot) { 94 | console.log('success'); 95 | window.location = '/'; 96 | }); 97 | } 98 | 99 | function deleteData(id) { 100 | const accountRef = database.ref('account/' + id); 101 | accountRef.remove(); 102 | accountRef.on('value', function(snapshot) { 103 | console.log('success'); 104 | window.location = '/'; 105 | }); 106 | } 107 | 108 | function submitListener(submitType) { 109 | const addFormRef = document.querySelector("#add-form"); 110 | addFormRef.addEventListener('submit', function(e) { 111 | e.preventDefault(); 112 | const id = uuid.v4(); 113 | const title = addFormRef.title.value; 114 | const type = addFormRef.type.value; 115 | const number = addFormRef.number.value; 116 | const date = addFormRef.date.value; 117 | if (submitType === 'create') { 118 | writeAccountData(id, title, type, number, date); 119 | } else { 120 | const params = window.location.search.replace('?', '').split('&'); 121 | const id = params[0].split('=')[1]; 122 | updateData(id, title, type, number, date); 123 | } 124 | }); 125 | } 126 | 127 | function updateBtnListener() { 128 | const updateBtns = document.querySelectorAll(".update-btn"); 129 | console.log(updateBtns); 130 | for (let i = 0; i < updateBtns.length; i++) { 131 | updateBtns[i].addEventListener('click', function(e) { 132 | const id = updateBtns[i].getAttribute('data-id'); 133 | e.preventDefault(); 134 | const accountRef = database.ref('account/' + id); 135 | accountRef.on('value', function(snapshot) { 136 | window.location = '/update.html?id=' + id + '&title=' + snapshot.val().title + '&type=' + snapshot.val().type + '&number=' + snapshot.val().number + '&date=' + snapshot.val().date; 137 | }); 138 | }); 139 | } 140 | } 141 | 142 | function deleteBtnListener() { 143 | const deleteBtns = document.querySelectorAll(".delete-btn"); 144 | console.log(deleteBtns); 145 | for (let i = 0; i < deleteBtns.length; i++) { 146 | deleteBtns[i].addEventListener('click', function(e) { 147 | const id = deleteBtns[i].getAttribute('data-id'); 148 | e.preventDefault(); 149 | if (confirm('確認刪除?')) { 150 | deleteData(id); 151 | } else { 152 | alert('你按下取消'); 153 | } 154 | }); 155 | } 156 | } 157 | 158 | function loadChart(rawData) { 159 | let eat = 0; 160 | let life = 0; 161 | let play = 0; 162 | let edu = 0; 163 | let trafic = 0; 164 | let others = 0; 165 | const ctxRef = document.querySelector('#data-chart'); 166 | const infoRef = document.querySelector('#data-chart-info'); 167 | for(const key in rawData) { 168 | if (rawData.hasOwnProperty(key)) { 169 | const type = rawData[key].type; 170 | const number = rawData[key].number; 171 | switch(type) { 172 | case 'eat': 173 | eat += parseInt(number); 174 | break; 175 | case 'life': 176 | life += parseInt(number); 177 | break; 178 | case 'play': 179 | play += parseInt(number); 180 | break; 181 | case 'edu': 182 | edu += parseInt(number); 183 | break; 184 | case 'trafic': 185 | trafic += parseInt(number); 186 | break; 187 | case 'others': 188 | others += parseInt(number); 189 | break; 190 | } 191 | } 192 | } 193 | const data = { 194 | labels: [ 195 | '餐費', 196 | '生活', 197 | '娛樂', 198 | '教育', 199 | '交通', 200 | '其他' 201 | ], 202 | datasets: [{ 203 | data: [eat, life, play, edu, trafic, others], 204 | backgroundColor: [ 205 | 'rgba(255, 99, 132, 0.5)', 206 | 'rgba(54, 162, 235, 0.5)', 207 | 'rgba(255, 206, 86, 0.5)', 208 | 'rgba(75, 192, 192, 0.5)', 209 | 'rgba(153, 102, 255, 0.5)', 210 | 'rgba(255, 159, 64, 0.5)' 211 | ], 212 | borderColor: [ 213 | 'rgba(255, 99, 132, 1)', 214 | 'rgba(54, 162, 235, 1)', 215 | 'rgba(255, 206, 86, 1)', 216 | 'rgba(75, 192, 192, 1)', 217 | 'rgba(153, 102, 255, 1)', 218 | 'rgba(255, 159, 64, 1)' 219 | ], 220 | }] 221 | }; 222 | const myPieChart = new Chart(ctxRef, { 223 | type: 'pie', 224 | data: data, 225 | }); 226 | } 227 | 228 | const path = window.location.pathname; 229 | 230 | // switch (path) { 231 | // case '/create.html': 232 | // submitListener('create'); 233 | // break; 234 | // case '/update.html': 235 | // readFormData(); 236 | // submitListener('update'); 237 | // break; 238 | // default: 239 | // readAccountData(); 240 | // } 241 | -------------------------------------------------------------------------------- /Ch03/examples2/dist/js/bundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { 75 | return true; 76 | } else { 77 | return false; 78 | } 79 | } 80 | }]); 81 | 82 | return Monster; 83 | }(Pokomo); 84 | 85 | exports.default = Monster; 86 | 87 | },{}],2:[function(require,module,exports){ 88 | 'use strict'; 89 | 90 | var _Monster = require('./Monster'); 91 | 92 | var _Monster2 = _interopRequireDefault(_Monster); 93 | 94 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 95 | 96 | var playBtn = document.querySelector('#play'); 97 | playBtn.addEventListener('click', play); 98 | 99 | var charmander = new _Monster2.default('小火龍', './dist/img/charmander.png', 100, '火系'); 100 | var squirtle = new _Monster2.default('傑尼龜', './dist/img/squirtle.png', 100, '水系'); 101 | var bulbasaur = new _Monster2.default('妙蛙種子', './dist/img/bulbasaur.png', 100, '草系'); 102 | 103 | var cyndaquil = new _Monster2.default('火球鼠', './dist/img/cyndaquil.png', 100, '火系'); 104 | var totodile = new _Monster2.default('小鋸鱷', './dist/img/totodile.png', 100, '水系'); 105 | var chikorita = new _Monster2.default('菊草葉', './dist/img/chikorita.png', 100, '草系'); 106 | 107 | var monsters = [charmander, squirtle, bulbasaur]; 108 | var competitors = [cyndaquil, totodile, chikorita]; 109 | 110 | var myHP = 3; 111 | var cpHP = 3; 112 | 113 | function play() { 114 | var isFight = true; 115 | var choice = parseInt(prompt('小治,請問你要派出哪隻神奇寶貝呢(請輸入數字)? ---------- 0 小火龍 1 傑尼龜 2 妙蛙種子')); 116 | var competitorChoice = Math.floor(Math.random() * 3); 117 | 118 | var winner = checkWinner(); 119 | 120 | if (winner) { 121 | alert('\u52DD\u8CA0\u5DF2\u5206\uFF0C\u7372\u52DD\u7684\u662F' + winner + '\u9078\u624B'); 122 | } else { 123 | while (!competitors[competitorChoice].isAlive()) { 124 | competitorChoice = Math.floor(Math.random() * 3); 125 | } 126 | 127 | if (!(choice < 3) || !(choice >= 0)) { 128 | alert('請輸入正確數字喔!'); 129 | return 0; 130 | } 131 | 132 | if (monsters[choice].isAlive()) { 133 | switch (choice) { 134 | case 0: 135 | if (competitorChoice === 0) { 136 | pk(choice, competitorChoice, 'tie'); 137 | showView(choice, competitorChoice); 138 | } else if (competitorChoice === 1) { 139 | pk(choice, competitorChoice, 'lost'); 140 | showView(choice, competitorChoice); 141 | } else { 142 | pk(choice, competitorChoice, 'win'); 143 | showView(choice, competitorChoice); 144 | } 145 | break; 146 | case 1: 147 | if (competitorChoice === 0) { 148 | pk(choice, competitorChoice, 'win'); 149 | showView(choice, competitorChoice); 150 | } else if (competitorChoice === 1) { 151 | pk(choice, competitorChoice, 'tie'); 152 | showView(choice, competitorChoice); 153 | } else { 154 | pk(choice, competitorChoice, 'lost'); 155 | showView(choice, competitorChoice); 156 | } 157 | break; 158 | case 2: 159 | if (competitorChoice === 0) { 160 | pk(choice, competitorChoice, 'lost'); 161 | showView(choice, competitorChoice); 162 | } else if (competitorChoice === 1) { 163 | pk(choice, competitorChoice, 'win'); 164 | showView(choice, competitorChoice); 165 | } else { 166 | pk(choice, competitorChoice, 'tie'); 167 | showView(choice, competitorChoice); 168 | } 169 | break; 170 | } 171 | } else { 172 | alert(monsters[choice].getName() + ' \u5DF2\u5931\u53BB\u6230\u9B25\u80FD\u529B\uFF01'); 173 | choice = -1; 174 | } 175 | } 176 | } 177 | 178 | function checkWinner() { 179 | if (myHP === 0 && cpHP === 0) { 180 | return '小治和小帽'; 181 | } else if (cpHP === 0) { 182 | return '小治'; 183 | } else if (myHP === 0) { 184 | return '小帽'; 185 | } else { 186 | return false; 187 | } 188 | } 189 | 190 | function checkAlive(choice, competitorChoice) { 191 | if (!monsters[choice].isAlive()) { 192 | myHP -= 1; 193 | } 194 | if (!competitors[competitorChoice].isAlive()) { 195 | cpHP -= 1; 196 | } 197 | } 198 | 199 | function pk(choice, competitorChoice, type) { 200 | switch (type) { 201 | case 'win': 202 | monsters[choice].setHurt(5); 203 | competitors[competitorChoice].setHurt(50); 204 | checkAlive(choice, competitorChoice); 205 | alert('\u5C31\u6C7A\u5B9A\u662F\u4F60\u4E86\uFF01' + monsters[choice].getName() + ' ------ \u5C0D\u65B9\u6D3E\u51FA' + competitors[competitorChoice].getName() + '\uFF0C\u592A\u597D\u4E86\uFF0C\u6293\u4F4F\u5C0D\u65B9\u5F31\u9EDE\uFF01 HP -5\uFF0C' + monsters[choice].getName() + ' HP \u9084\u5269 ' + monsters[choice].getHP()); 206 | break; 207 | case 'lost': 208 | monsters[choice].setHurt(50); 209 | competitors[competitorChoice].setHurt(5); 210 | checkAlive(choice, competitorChoice); 211 | alert('\u5C31\u6C7A\u5B9A\u662F\u4F60\u4E86\uFF01' + monsters[choice].getName() + ' ------ \u5C0D\u65B9\u6D3E\u51FA' + competitors[competitorChoice].getName() + '\uFF0C\u4E0D\u597D\uFF0C\u5C6C\u6027\u76F8\u524B\uFF01 HP -50\uFF0C' + monsters[choice].getName() + ' HP \u9084\u5269 ' + monsters[choice].getHP()); 212 | break; 213 | case 'tie': 214 | monsters[choice].setHurt(30); 215 | competitors[competitorChoice].setHurt(30); 216 | checkAlive(choice, competitorChoice); 217 | alert('\u5C31\u6C7A\u5B9A\u662F\u4F60\u4E86\uFF01' + monsters[choice].getName() + ' ------ \u5C0D\u65B9\u6D3E\u51FA' + competitors[competitorChoice].getName() + '\uFF0C\u96D9\u65B9\u52E2\u5747\u529B\u6575\uFF01 HP -30\uFF0C' + monsters[choice].getName() + ' HP \u9084\u5269 ' + monsters[choice].getHP()); 218 | break; 219 | } 220 | } 221 | 222 | function showView(choice, competitorChoice) { 223 | var player1List = document.querySelector('#player1-list'); 224 | var player2List = document.querySelector('#player2-list'); 225 | 226 | player1List.innerHTML = '\n
    • \n \n
    • \n
    • \n
      \n
      \n ' + monsters[choice].getHP() + '%\n
      \n
      \n
    • \n
    • ' + monsters[choice].getName() + '
    • \n
    • \u5C6C\u6027\uFF1A' + monsters[choice].getType() + '
    • \n '; 227 | 228 | player2List.innerHTML = '\n
    • \n \n
    • \n
    • \n
      \n
      \n ' + competitors[competitorChoice].getHP() + '%\n
      \n
      \n
    • \n
    • ' + competitors[competitorChoice].getName() + '
    • \n
    • \u5C6C\u6027\uFF1A' + competitors[competitorChoice].getType() + '
    • \n '; 229 | } 230 | 231 | },{"./Monster":1}]},{},[2]); 232 | -------------------------------------------------------------------------------- /javascript101-live/subtitle/字幕/Unit2.txt: -------------------------------------------------------------------------------- 1 | WEBVTT 2 | 00:00:00,000 --> 00:00:12,000 3 | 哈囉,大家好,我是凱迪 4 | 歡迎來到javaScript程式設計新手村 5 | 00:00:12,000 --> 00:00:14,000 6 | 在27單元我們將討論前端開發面試常見問題研討 7 | 00:00:14,000 --> 00:00:20,000 8 | 首先介紹一下 9 | 我們這個單元的大鋼 10 | 00:00:20,000 --> 00:00:25,000 11 | 首先我們會介紹面試前的準備 12 | 前端面試的概論 13 | 00:00:25,000 --> 00:00:30,000 14 | 那還有 15 | 前端常見問題研討 16 | 00:00:30,000 --> 00:00:38,000 17 | 首先我們來探討面試前的準備 18 | 很多學員可能是第一次參加技術的面試 19 | 00:00:38,000 --> 00:00:42,000 20 | 事實上技術的面試 21 | 跟一般的面試事實上是比較不一樣的 22 | 00:00:42,000 --> 00:00:47,000 23 | 可能有些同學過去是 24 | 就是文學院或商管學院 25 | 00:00:47,000 --> 00:00:55,000 26 | 過去參與一些公司的實習 27 | 或是一些行銷企劃案的實習機會 28 | 00:00:55,000 --> 00:01:00,000 29 | 那事實上技術面試跟 30 | 以上提到的一些職位 31 | 00:01:00,000 --> 00:01:05,000 32 | 面試的過程中有許多不一樣 33 | 其中一個蠻重要的環節是 34 | 00:01:05,000 --> 00:01:10,000 35 | 在技術面試有一個很重要就是 36 | 可能需要當場寫程式 37 | 00:01:10,000 --> 00:01:23,000 38 | 或有許多技術上面的討論跟問答 39 | 這是跟一般的商管的或是一般的業務阿 40 | 00:01:23,000 --> 00:01:33,000 41 | 行銷相關的工作機會是比較不一樣的面談 42 | 那在面談之前事實上 43 | 00:01:33,000 --> 00:01:37,000 44 | 是有一些準備工作是要去做的 45 | 我們可以這樣講, 46 | 00:01:37,000 --> 00:01:46,000 47 | 就是說 48 | 事實上一個好的求職過程是包含面試前的準備 49 | 00:01:46,000 --> 00:01:51,000 50 | 面試中 面談中的一些對答 51 | 再來就是結束後的一些 52 | 00:01:51,000 --> 00:01:55,000 53 | 和面試官也好, 54 | 或是 跟人資也好的應對進退 55 | 00:01:55,000 --> 00:02:01,000 56 | 這是整個 57 | 一個面試蠻重要的環節 58 | 00:02:01,000 --> 00:02:07,000 59 | 就主要包括這三個部分 60 | 首先我們來探討面試前的準備 61 | 00:02:07,000 --> 00:02:12,000 62 | 在技術面試的話,事實上 63 | 一般的技術面試 64 | 00:02:12,000 --> 00:02:19,000 65 | 蠻重要是強調技術的扎實度和技術的吻合度 66 | 00:02:19,000 --> 00:02:29,000 67 | 所以蠻建議大家經營自己的技術部落格 68 | 或參與開放原始碼的專案或社群 69 | 00:02:29,000 --> 00:02:36,000 70 | follow整個社群有什麼新技術可以嘗試 71 | 00:02:36,000 --> 00:02:42,000 72 | 因為在這個領域尤其是前端 73 | 00:02:42,000 --> 00:02:44,000 74 | 可能有聽過前端摩爾定律 75 | 00:02:44,000 --> 00:02:49,000 76 | 每半年就有很多新的技術和框架出來 77 | 00:02:49,000 --> 00:02:59,000 78 | 唯有保持敏銳持續觀察才能在這個行業進步專業能力 79 | 00:02:59,000 --> 00:03:02,000 80 | 淨化自己的網路資訊 81 | 00:03:02,000 --> 00:03:09,000 82 | 很多學員可能在很多社群網路facebook、plurk、twitter 83 | 00:03:09,000 --> 00:03:12,000 84 | 發一些心情抒發的訊息 85 | 00:03:12,000 --> 00:03:20,000 86 | 但現在透過一些管道,人資或面談主管 87 | 00:03:20,000 --> 00:03:26,000 88 | 透過網路去搜尋社群網站一些相關資料 89 | 00:03:26,000 --> 00:03:32,000 90 | 如果這些資料對你不是有正面加分的話就盡量避免 91 | 00:03:32,000 --> 00:03:50,000 92 | 累積簡歷上的作品,包括學校競賽、打工實習、自己接案子 93 | 00:03:50,000 --> 00:03:57,000 94 | 這些都是佐證你能力蠻重要的重點 95 | 00:03:57,000 --> 00:04:06,000 96 | 有些公司要求比較嚴謹,大型的網路公司 97 | 00:04:06,000 --> 00:04:10,000 98 | 科技公司,包括facebook、google 99 | 00:04:10,000 --> 00:04:21,000 100 | 等等,除了前端的相關技術之外也很要求軟體工程的專業技術 101 | 00:04:21,000 --> 00:04:31,000 102 | 所以盡可能去累積自己軟體工程相關知識,如果要挑戰這些 103 | 企業的話是必須的 104 | 00:04:31,000 --> 00:04:40,000 105 | 這裡提到了一些網站 106 | 00:04:40,000 --> 00:04:43,000 107 | 有些面談可能要你寫程式 108 | 00:04:43,000 --> 00:04:47,000 109 | 包括演算法、資料結構相關的一些題目 110 | 00:04:47,000 --> 00:05:04,000 111 | 蠻鼓勵大家利用線上的這些平台 112 | 00:05:04,000 --> 00:05:08,000 113 | 這有點像是工程師的GRE 114 | 00:05:08,000 --> 00:05:14,000 115 | GRE就是你可能要出國留學英文的測試 116 | 00:05:14,000 --> 00:05:20,000 117 | 這裡有列出了一些資料結構、演算法的相關問題 118 | 00:05:20,000 --> 00:05:27,000 119 | 你可以點選比較簡單的題目先開始 120 | 00:05:27,000 --> 00:05:33,000 121 | 它裡面有一些題目,這邊看到是通過率 122 | 00:05:33,000 --> 00:05:39,000 123 | 我們這邊可以選擇javascript因為在前端開發 124 | 比較重要是javascropt這個程式語言 125 | 00:05:39,000 --> 00:05:51,000 126 | 在這個練習可以學祥api和資料結構演算法 127 | 的相關知識 128 | 00:05:57,000 --> 00:06:00,000 129 | 接下來介紹前端面試的概論 130 | 00:06:00,000 --> 00:06:07,000 131 | 在前端工程師的職位,他的光譜非常大 132 | 00:06:07,000 --> 00:06:16,000 133 | 有比較偏向設計,也有偏向軟體工程師的範疇 134 | 00:06:16,000 --> 00:06:25,000 135 | 在一些大型的IT或網路公司,通常視前端工程師為 136 | 軟體工程師 137 | 00:06:25,000 --> 00:06:38,000 138 | 前端工程師只是一個領域,他們希望部是哪種工程師 139 | 都能快速上手該領域的專業知識 140 | 00:06:38,000 --> 00:06:47,000 141 | 所以足夠solid的一些知識也是足夠必須要求的 142 | 00:06:47,000 --> 00:06:54,000 143 | 所以建議學員定位自己比較希望往哪發展 144 | 00:07:15,000 --> 00:07:19,000 145 | 都沒有關係,找好自己的定位 146 | 00:07:19,000 --> 00:07:27,000 147 | 相信你在面試工程師的時候,都會對你職涯有幫助 148 | 00:07:27,000 --> 00:07:36,000 149 | 不同公司對前端工程師有不同要求 150 | 00:07:36,000 --> 00:07:48,000 151 | 大家可以去人力銀、104 152 | 00:07:48,000 --> 00:07:55,000 153 | 或者是去你感興趣的公司 154 | 00:07:55,000 --> 00:08:05,000 155 | 一些招募招聘的一些資訊,看一下說有沒有招募前端工程師 156 | 00:08:05,000 --> 00:08:12,000 157 | 他在前端工程師的要求是怎樣的情況 158 | 00:08:12,000 --> 00:08:26,000 159 | 可以印出來看看那些我還不具備 160 | 00:08:26,000 --> 00:08:36,000 161 | 相信大家能夠進到理想公司,獲得理想工作的機會 162 | 00:08:36,000 --> 00:08:39,000 163 | 我們先來看F公司 164 | 00:08:39,000 --> 00:08:43,000 165 | F公司有四點重要要求 166 | 00:08:43,000 --> 00:08:53,000 167 | 3年的javascript經驗,非同步programming經驗 168 | 00:08:53,000 --> 00:09:03,000 169 | 我們在課堂提到ajax非同步,promise、closure 170 | types;ES6 171 | 00:09:03,000 --> 00:09:17,000 172 | F公司主要是用React當一個蠻重要的library 173 | 00:09:17,000 --> 00:09:32,000 174 | 第3點就是提到3年以上HTML。CSS相關經驗 175 | 包括排版、specificity權重,還有跨瀏覽器的一些資源 176 | 00:09:32,000 --> 00:09:40,000 177 | 還有就是API還有就是優化的相關經驗 178 | 00:09:40,000 --> 00:09:43,000 179 | 這是F公司前端的徵才文 180 | 00:09:43,000 --> 00:09:47,000 181 | 這是Y公司前端的徵才文 182 | 00:09:47,000 --> 00:09:56,000 183 | 同樣也是希望computer science的相關領域 184 | 00:09:56,000 --> 00:10:24,000 185 | 你有一些作品或一些開放原始碼的經驗,或一些令人驚艷 186 | 的特質,我們不要被這些明訂的標準限制住 187 | 00:10:24,000 --> 00:10:38,000 188 | 有時候這些要求只是理想的,不一定要符合這些要求才能進 189 | 到這家公司服務 190 | 00:10:38,000 --> 00:10:52,000 191 | 還有就是對server side程式語言,包括PHP,nodejs,jQuery 192 | 之類的framework的一些了解 193 | 00:10:52,000 --> 00:10,59,000 194 | 還有像是bootstrap、pure之類framework的一些了解 195 | 00:10:59,000 --> 00:11:03,000 196 | 還有一些次是工具,這是Y公司的前端徵才文 197 | 00:11:03,000 --> 00:11:12,000 198 | P公司的javascript的使用經驗 199 | 00:11:12,000 --> 00:11:18,000 200 | 還有跨瀏覽器,還有response design的相關經驗 201 | 00:11:18,000 --> 00:11:26,000 202 | 接下來講一下一般技術面式的流程 203 | 00:11:26,000 --> 00:11:32,000 204 | 面試的結果很多和事前和事後的準備是有關的 205 | 00:11:32,000 --> 00:11:38,000 206 | 通常技術面試會分為四部分 207 | 00:11:38,000 --> 00:11:45,000 208 | 簡歷審核,內推就是可能用內部推薦的方式 209 | 00:11:45,000 --> 00:11:48,000 210 | 校園招募啊,社會招募,或獵人頭公司 211 | 00:11:48,000 --> 00:11:54,000 212 | 獲取一些機會的管道 213 | 00:11:54,000 --> 00:12:02,000 214 | 通常簡歷通過的話會有phone interview 215 | 00:12:02,000 --> 00:12:09,000 216 | 所謂phone interview可能透過電話、skype、google handout 217 | 都有可能 218 | 00:12:09,000 --> 00:12:16,000 219 | 通常會要求自我介紹並問一些基本的技術問題 220 | 00:12:16,000 --> 00:12:30,000 221 | 有可能用codebunk或codepad去使用 222 | 00:12:30,000 --> 00:12:37,000 223 | 在使用過程中面試官也會同步看到你coding的畫面 224 | 00:12:37,000 --> 00:12:49,000 225 | 在你打的時候面試官會出題目,同步看到你編寫的過程 226 | 00:12:49,000 --> 00:12:57,000 227 | 去評斷你寫程式的能力 228 | 00:12:57,000 --> 00:13:07,000 229 | 另一種事前出一份作業,在一定的時間內回傳 230 | 00:13:07,000 --> 00:13:10,000 231 | 去評斷你的能力到底怎樣 232 | 00:13:10,000 --> 00:13:16,000 233 | 如果通過phone interview和前測就會受邀參加 234 | onsite interview 235 | 00:13:16,000 --> 00:13:26,000 236 | onsite interview就是到公司跟資深工程師、PM、人資去做面談 237 | 00:13:26,000 --> 00:13:34,000 238 | 通常會有兩部分的題目,包括behavior就是你的人格特質 239 | 00:13:34,000 --> 00:13:41,000 240 | 或者是對你過去的一些考核和檢驗 241 | 00:13:41,000 --> 00:13:45,000 242 | 另外蠻重要就是techinical的測驗 243 | 00:13:45,000 --> 00:13:49,000 244 | 包括紙筆測驗或是問答 245 | 00:13:49,000 --> 00:13:53,000 246 | 可能有些同學有聽過白板題 247 | 00:13:53,000 --> 00:13:58,000 248 | 就是在白板上直接寫出程式碼,和面試官討論 249 | 00:13:58,000 --> 00:14:06,000 250 | 很順利通過這些關卡的話,會有HR interview 251 | 00:14:06,000 --> 00:14:12,000 252 | 待會也會介紹相關的細節 253 | 00:14:12,000 --> 00:14:21,000 254 | 主要聊一些公司文化阿或薪資待遇的議題 255 | 00:14:21,000 --> 00:14,26,000 256 | 首先,前端問題的一些研討 257 | 00:14:26,000 --> 00:14:35,000 258 | 這裡提供三個連結,是有關面試的常見問題 259 | 00:14:35,000 --> 00:14:40,000 260 | 有些有參考的解決方法,有些沒有 261 | 00:14:40,000 --> 00:14:50,000 262 | 去檢查有那些是我們不足或不理解的 263 | 00:14:50,000 --> 00:14:56,000 264 | 是一個road map的方式讓大家理解哪裡還不足 265 | 00:14:56,000 --> 00:15:01,000 266 | 大家點擊進去就可以看到了 267 | 00:15:01,000 --> 00:15:11,000 268 | 這裡有繁體中文簡體中文和英文版 269 | 00:15:11,000 --> 00:15:15,000 270 | 比較建議看英文版的部分,因為他是有持續在更新的 271 | 00:15:15,000 --> 00:15:20,000 272 | 如果不習慣的話可以去看繁體中文或簡體中文都是可以的 273 | 00:15:20,000 --> 00:15:25,000 274 | 我們看到上面有很多前端相關的問答 275 | 00:15:25,000 --> 00:15:28,000 276 | 這裡面還又一些延伸閱讀,大家可以參考一下 277 | 00:15:28,000 --> 00:15:36,000 278 | 首先在面試過程通常都會自我介紹 279 | 00:15:36,000 --> 00:15:47,000 280 | 包括自己的工作經驗、學經歷、為什麼要加入這個團隊 281 | 、能有什麼貢獻 282 | 00:15:47,000 --> 00:15:53,000 283 | 通常有些外商公司會希望你用英文自我介紹,或用英文問答 284 | 00:15:53,000 --> 00:15:58,000 285 | 這些都是可以在事前做一些模擬跟準備的 286 | 00:15:58,000 --> 00:16:12,000 287 | HTML的問題,我們列出來的問題過去都有提到 288 | 如果學員有映像的話 289 | 00:16:12,000 --> 00:16:30,000 290 | 課程之前有埋下一些伏筆,前端面試相關問題,如果當下學不清楚的話 291 | 沒有關係,這編列了一些重點 292 | 00:16:30,000 --> 00:16:42,000 293 | 可以去回憶過去學得有沒有熟悉再去做補強查詢 294 | 00:16:42,000 --> 00:16:50,000 295 | 首先是確保知道什麼是doctype 296 | 00:16:50,000 --> 00:16:56,000 297 | 我們之前講過,用一句話講的話,就是讓瀏覽器知道你的版本是什麼 298 | 00:16:56,000 --> 00:17:02,000 299 | 我們在html5已經簡化這樣的一個過程 300 | 00:17:02,000 --> 00:17:09,000 301 | 可以這樣去宣告HTML的版本 302 | 00:17:09,000 --> 00:17:18,000 303 | 那如果用舊的版本或沒有宣告的話,瀏覽器可能會出現一些問題, 304 | 大家注意一下 305 | 00:17:18,000 --> 00:17:20,000 306 | HTML5有哪些語意標籤呢? 307 | 00:17:20,000 --> 00:17:31,000 308 | 在這邊可以看到一些語意標籤,我們過去可能div、span這些標籤 309 | 但這些只是排版 310 | 00:17:31,000 --> 00:17:42,000 311 | 這裡包括header、footer,footer就是關於版權說明阿或加入我們 312 | 之類的東西 313 | 00:17:42,000 --> 00:17:50,000 314 | 這個就是語意標籤,就是搜尋引擎檢索,讓你頁面更語意化的一種 315 | 方式 316 | 00:17:50,000 --> 00:18:04,000 317 | javascript引入,之前我們講過盡量在body關掉之前 318 | 00:18:04,000 --> 00:18:08,000 319 | 這邊可以看到script的引入 320 | 00:18:08,000 --> 00:18:18,000 321 | 如果dom還沒載入完就引入的話,會造成一些問題 322 | 00:18:18,000 --> 00:18:20,000 323 | 那這邊要特別注意 324 | 00:18:20,000 --> 00:18:26,000 325 | 那form表單有post和get之前講過 326 | 00:18:26,000 --> 00:18:28,000 327 | http的方法比較常見有post跟get 328 | 00:18:28,000 --> 00:18:40,000 329 | get的話就是寄明信片,內容都會被看到 330 | 就會顯示在網址上面,你的資料傳遞 331 | 00:18:40,000 --> 00:18:47,000 332 | 那post的話就不是了,他會在http的內容裡面 333 | 00:18:47,000 --> 00:18:57,000 334 | 比較建議登入登出用post的方法處理 335 | 00:18:57,000 --> 00:19:11,000 336 | 事實上我們可以搜尋,在query這裡就是我們get方法的 337 | 00:19:11,000 --> 00:19:20,000 338 | 項,這個的話我們就知道是get方法,蠻明顯的例子 339 | 00:19:20,000 --> 00:19:27,000 340 | 那HTML5離線儲存,我們之前在local storage 、session storage 341 | 有講過 342 | 00:19:27,000 --> 00:19:32,000 343 | 那大家可以再去比較一下session、localstorage、cookie 344 | 之間的差別 345 | 00:19:32,000 --> 00:19:36,000 346 | css 基礎知識的掌握 347 | 00:19:36,000 --> 00:19:41,000 348 | 這個部分我們講過怎麼用css兩籃式的排版 349 | 00:19:41,000 --> 00:19:53,000 350 | 大家可以回憶一下,像是position相對定位絕對定位、float方式、flexbox 351 | 00:19:53,000 --> 00:20:00,000 352 | 這邊有蠻不錯的一個網站大家可以去看一下 353 | 00:20:00,000 --> 00:20:07,000 354 | 這是css版面配置的一個練習網站 355 | 00:20:07,000 --> 20:15:00,000 356 | 這裡介紹了css版面配置的所有知識都在裡面 357 | 00:20:15,000 --> 00:20:17,000 358 | 鼓勵大家可以去看一下 359 | 00:20:17,000 --> 00:20:21,000 360 | 什麼是css選擇器,我們也講過 361 | 00:20:21,000 --> 00:20:25,000 362 | 最簡單的說法就是選擇器和你要改變的宣告 363 | 00:20:25,000 --> 00:20:32,000 364 | 你選到什麼元素,你要改變它的顏色或背景 365 | 00:20:32,000 --> 00:20:50,000 366 | pseudo class是什麼呢?pseudo-classes是,之前我們滑進跟點選 367 | 的冒號後面有一個state說明點擊還是滑進的狀況 368 | 00:20:50,000 --> 00:20:55,000 369 | 這些就是pseudo class的一些相關概念 370 | 00:20:55,000 --> 00:20:58,000 371 | css選擇器有很多,大家可以在去複習一下 372 | 00:20:58,000 --> 00:21:13,000 373 | 那box model的話,再css有講過,我們講過空城計的例子 374 | 就是說,我們有content,padding,border跟margin 375 | 00:21:13,000 --> 00:21:26,000 376 | 這樣去定義我們內容、距離、或留白寬度 377 | 00:21:26,000 --> 00:21:34,000 378 | 這個box model大家可以去css在仔細的研究一下 379 | 00:21:34,000 --> 00:21:37,000 380 | 那什麼是css sprites呢? 381 | 00:21:37,000 --> 00:21:51,000 382 | css sprites是一個實務上蠻常用的觀念,他是,為什麼要用css sprites 383 | 呢? 384 | 00:21:51,000 --> 00:21:58,000 385 | 前端開發效能的優化是蠻重要的 386 | 00:21:58,000 --> 00:22:09,000 387 | 當你送出一個request請求到你server side或其他地方 388 | 00:22:09,000 --> 00:22:13,000 389 | 請求資源都會造成資源的消耗 390 | 00:22:13,000 --> 00:22:25,000 391 | 如果一個站點,如果我們圖片很多的話,大家還記得嗎? 392 | src 393 | 00:22:25,000 --> 00:22:28,000 394 | 在 image裡面src 395 | 00:22:28,000 --> 00:22:35,000 396 | 如果說 397 | 00:22:46,000 --> 00:23:00,000 398 | 如果我們很多圖片都用src去送出請求,會影響前端頁面的效能 399 | 00:23:00,000 --> 00:23:06,000 400 | 所以我們就衍生出css sprites的技術 401 | 00:23:06,000 --> 00:23:15,000 402 | 大家可能有看過,把好多圖片和成一張圖片 403 | 00:23:19,000 --> 00:23:27,000 404 | 可以看到這邊 大家可能有看過,把好多圖片和成一張圖片 405 | 00:23:27,000 --> 00:23:33,000 406 | 那這樣每次只要載入一張圖片 407 | 00:23:33,000 --> 00:23:38,000 408 | 那我們再用css定位的方法,這邊有個例子 409 | 00:23:38,000 --> 00:23:43,000 410 | 這邊有個例子,這邊有張圖片這樣子 411 | 00:23:45,000 --> 00:23:49,000 412 | 這邊有張圖片,回首頁、上一頁、下一頁 413 | 00:23:49,000 --> 00:23:53,000 414 | 這是合併成一張圖片,事實上他是三個icon 415 | 00:23:53,000 --> 00:24:02,000 416 | 大家可以看到,也就是說使用上就只要載入一張圖片就好, 417 | 我們可以用css手法 418 | 00:24:02,000 --> 00:24:06,000 419 | 也就是這裡image id=home然後#id name嗎 420 | 00:24;06,000 --> 00:24:12,000 421 | 這邊就用url background去載入想要的圖片 422 | 00:24:12,000 --> 00:24:20,000 423 | 那我們這裡用 0 0 424 | 00:24:26,000 --> 00:24:30,000 425 | 那我們這裡用 0 0的圖片,我們就可以看到說,調整一下會怎樣 426 | 00:24:47,000 --> 00:24:53,000 427 | 可以看到說我這邊圖片都一直在改變 428 | 00:24:53,000 --> 00:24:57,000 429 | 可以看到位置 430 | 00:25:15,000 --> 00:25:26,000 431 | 大家有發現嗎?我去調整的話可以看到圖片的一些變動 432 | 00:25:26,000 --> 00:25:42,000 433 | 透過這樣的方式我們可以再同一張圖對我們想要的圖片 434 | 00:25:42,000 --> 00:25:56,000 435 | 通常我們這樣使用太麻煩了,所以通常會用這樣的工具, 436 | css sprite generator 437 | 00:25:56,000 --> 00:26:19,000 438 | 你把你想要的圖片放進來,這裡可以載入圖片,案download 439 | 他就會出現html css相關的資訊 440 | 00:26:19,000 --> 00:26:23,000 441 | 你可以複製這個,她就幫你定位好,你就不須自己去手動定位 442 | 00:26:23,000 --> 00:26:34,000 443 | 這就非常方便,你有這六張圖,她就幫你定位icon這樣子 444 | 00:26:38,000 --> 00:26:45,000 445 | 那最後一個css比較需要掌握的重點就是RWD的設計 446 | 00:26:45,000 --> 00:26:28,000 447 | RWD全名叫response web deaign 448 | 00:26:28,000 --> 00:26:53,000 449 | 也被稱為自適應設計或響應式設計 450 | 00:26:53,000 --> 00:27:14,000 451 | 主要的概念就是,透過css設計,讓在不同device螢幕大小 452 | 的是使用者享受到最好的體驗 453 | 00:27:14,000 --> 00:27:21,000 454 | 我們可以看一下這邊 455 | 00:27:25,000 --> 00:27:27,000 456 | 網路上有些response design的範例 457 | 00:27:38,000 --> 00:28:00,000 458 | 大概會長這樣子,會跟著螢幕大小,通常我們會有一個 459 | 叫media query的語法判斷 460 | 00:28:00,000 --> 00:28:11,000 461 | 他會去偵測大小,去偵測使用者最舒服的一個方式 462 | 00:28:11,000 --> 00:28:18,000 463 | 像這個本來340的畫面就變成140 464 | 00:28:18,000 --> 00:28:27,000 465 | 蠻適合去閱讀的,這就是response design的情境 466 | 00:28:27,000 --> 00:28:43,000 467 | 有很多小細節,就像這裡google設計師就有教人怎麼做response 468 | design 469 | 00:28:43,000 --> 00:29:00,000 470 | 這邊有動畫,大家可以拉動瀏覽器,當不同螢幕大小,會有不同畫面的 471 | 產生 472 | 00:29:00,000 --> 00:29:11,000 473 | 我們可以看到有些重要的設計,像是這裡viewport參數 474 | 00:29:30,000 --> 00:29:35,000 475 | 還有這裡media query螢幕大小在500到600之間 476 | 這些元素要怎麼設計 477 | 00:29:35,000 --> 00:29:43,000 478 | 大家可以參考一下其他學習資源 479 | 00:29:43,000 --> 00:29:49,000 480 | 接下來要講一下,javascript比較重要的觀念 481 | 00:29:49,000 --> 00:30:04,000 482 | 包括javascript的型別轉換,大家可以想,包括字串怎麼轉成數值、 483 | 使用pass integer或者是用number把字串丟進去 484 | 00:30:04,000 --> 00:30:10,000 485 | 這樣的一些方法就可以做型別轉換 486 | 00:30:10,000 --> 00:30:17,000 487 | 也要注意字串和數字相加會怎樣,大家可以嘗試看看 488 | 00:30:17,000 --> 00:30:23,000 489 | 這裡先往下看 490 | 00:30:23,000 --> 00:30:38,000 491 | scope生存域,講過的javascript是function scope也就是會存活在 492 | function之間,如果離開function就會結束生存 493 | 00:30:38,000 --> 00:30:42,000 494 | 注意包括var、const、let的一些用法 495 | 00:30:42,000 --> 00:30:47,000 496 | 怎樣用javascript建構函式去new物件? 497 | 00:30:47,000 --> 00:31:00,000 498 | 這在物件的單元就又講了,大家不熟悉的話再去複習 499 | 包括prototype怎樣建置,還有繼承的一些觀念 500 | 00:31:00,000 --> 00:31:09,000 501 | 大家再去複習一下關於物件的重點,面試很有可能出現 502 | 00:31:09,000 --> 00:31:32,000 503 | apply/call這牽扯到this用法,前面也講過四五種用法 504 | 包括指到物件 505 | 00:31:32,000 --> 00:31:37,000 506 | 要注意到apply後面是接陣列,call是直接塞進去 507 | 00:31:37,000 --> 00:31:43,000 508 | 大家忘記的話再去複習之前的內容 509 | 00:31:47,000 --> 00:32:11,000 510 | 那氣泡傳遞在你在觸發事件的時候,氣泡傳遞在第三個參數 511 | 第一個是事件名稱包括click 512 | 00:32:11,000 --> 00:32:23,000 513 | 或double click,中間是event handler名稱﹑第三個就是傳遞方式 514 | 00:32:23,000 --> 00:32:40,000 515 | false就是氣泡傳遞,氣泡傳遞就是就是觸發的地方往外傳 516 | 00:32:40,000 --> 00:32:46,000 517 | 什麼是ajax呢,我們在非同步處理有提到 518 | 00:32:46,000 --> 00:32:59,000 519 | promise就是在解決回掉地獄,非同步處理,處理完可以做其他事情 520 | 00:32:59,000 --> 00:33:19,000 521 | DOM一些基礎操作,包括document去做一些新增刪除元素, 522 | 搭配事件處理操作 523 | 00:33:19,000 --> 00:33:26,000 524 | 這裡有延伸閱讀,家有興趣可以參考一下 525 | 00:33:26,000 --> 00:33:36,000 526 | 裡面有javascript常見的面試題目,包括closure的觀念,有時也會在面 527 | 談出現 528 | 00:33:36,000 --> 00:33:42,000 529 | 在之前的單元也有提到,可以再複習 530 | 00:33:42,000 --> 00:33:48,000 531 | 除了一些前端三劍客比較基礎的問題 532 | 00:33:48,000 --> 00:34:01,000 533 | 面談時也會問到其餘的一些問題,包含 534 | 你用過那些框架或函式庫,優點缺點是什麼呢 535 | 00:34:01,000 --> 00:34:16,000 536 | 你可能講你用過react這個library,他是facebook的library 537 | 是跨平台開發 538 | 00:34:16,000 --> 00:34:40,000 539 | 他提出了現在前端的一些主流技術,包括component 540 | virtual dom,跨平台的方式都是他一些優點 541 | 00:34:40,000 --> 00:34:52,000 542 | 缺點相對學習門檻比較高一點 543 | 00:34:52,000 --> 00:35:03,000 544 | 前端優化,像剛剛css sprites也是某種程度優化 545 | 00:35:03,000 --> 00:35:26,000 546 | 在瀏覽器timeline我們可以去看那些script、那些元素是最花時間的 547 | 00:35:37,000 --> 00:36:03,000 548 | 這裡可以看一下,哪個可能佔去最多時間,我們就可以知道怎麼去優化 549 | 00:36:03,000 --> 00:36:15,000 550 | 除了css sprites還有像是CDN css javascript壓縮 551 | 00:36:15,000 --> 00:36:16,000 552 | 這些都是前端優化的方法 553 | 00:36:16,000 --> 00:36:21,000 554 | 大家可以去網路上或找書來看 555 | 00:36:21,000 --> 00:36:24,000 556 | 瀏覽器在載入頁面發生什麼呢? 557 | 00:36:24,000 --> 00:36:34,000 558 | 這是一個蠻全面的探討,這有比較簡單的講法,也有複雜的 559 | 00:36:34,000 --> 00:37:19,000 560 | 我們可以看成說當輸入網址十,會交給DNS域名解釋,轉換成ip位置 561 | 像這個位置的server發出請求,在請求後,後台會做一些處理 562 | 00:37:19,000 --> 00:37:46,000 563 | 如果是靜態網頁他就直接吐回html css javascript,在瀏覽器接 564 | 下來就會組裝起來做一些解析,繪製出相應的結構 565 | 00:37:46,000 --> 00:38:36,000 566 | 大家可以參考這個網頁,是比較複雜的講法 567 | 00:38:36,000 --> 00:38:57,000 568 | 我們可以看一下這邊,他會經過這樣的過程,結合成DOM tree 569 | 00:38:57,000 --> 00:39:36,000 570 | 最後他會進行browser render pipeline的管道,最終呈現給使用者 571 | 00:39:36,000 --> 00:40:08,000 572 | 包括怎麼跟設計師溝通,或最近有什麼前端的新技術 573 | 00:40:08,000 --> 00:40:14,000 574 | 最後通常會有面試官問你有沒有問題要問我們 575 | 00:40:14,000 --> 00:41:10,000 576 | 鼓勵大家在事前做功課,包括團隊新聞,事實的提出見解或看法詢問 577 | 00:41:10,000 --> 00:41:35,000 578 | 在結束技術面試後,通常有HR的面談 579 | 00:41:35,000 --> 00:42:15,000 580 | 在這個單元中我們提到面試前準備等等 581 | 00:42:15,000 --> 00:42:18,000 582 | 最後還是鼓勵大家像是github等等,都是在未來有些幫助 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | -------------------------------------------------------------------------------- /javascript101-live/subtitle/字幕/VTT/Unit2.vtt: -------------------------------------------------------------------------------- 1 | WEBVTT 2 | 00:00:00,000 --> 00:00:12,000 3 | 哈囉,大家好,我是凱迪 4 | 歡迎來到javaScript程式設計新手村 5 | 00:00:12,000 --> 00:00:14,000 6 | 在27單元我們將討論前端開發面試常見問題研討 7 | 00:00:14,000 --> 00:00:20,000 8 | 首先介紹一下 9 | 我們這個單元的大鋼 10 | 00:00:20,000 --> 00:00:25,000 11 | 首先我們會介紹面試前的準備 12 | 前端面試的概論 13 | 00:00:25,000 --> 00:00:30,000 14 | 那還有 15 | 前端常見問題研討 16 | 00:00:30,000 --> 00:00:38,000 17 | 首先我們來探討面試前的準備 18 | 很多學員可能是第一次參加技術的面試 19 | 00:00:38,000 --> 00:00:42,000 20 | 事實上技術的面試 21 | 跟一般的面試事實上是比較不一樣的 22 | 00:00:42,000 --> 00:00:47,000 23 | 可能有些同學過去是 24 | 就是文學院或商管學院 25 | 00:00:47,000 --> 00:00:55,000 26 | 過去參與一些公司的實習 27 | 或是一些行銷企劃案的實習機會 28 | 00:00:55,000 --> 00:01:00,000 29 | 那事實上技術面試跟 30 | 以上提到的一些職位 31 | 00:01:00,000 --> 00:01:05,000 32 | 面試的過程中有許多不一樣 33 | 其中一個蠻重要的環節是 34 | 00:01:05,000 --> 00:01:10,000 35 | 在技術面試有一個很重要就是 36 | 可能需要當場寫程式 37 | 00:01:10,000 --> 00:01:23,000 38 | 或有許多技術上面的討論跟問答 39 | 這是跟一般的商管的或是一般的業務阿 40 | 00:01:23,000 --> 00:01:33,000 41 | 行銷相關的工作機會是比較不一樣的面談 42 | 那在面談之前事實上 43 | 00:01:33,000 --> 00:01:37,000 44 | 是有一些準備工作是要去做的 45 | 我們可以這樣講, 46 | 00:01:37,000 --> 00:01:46,000 47 | 就是說 48 | 事實上一個好的求職過程是包含面試前的準備 49 | 00:01:46,000 --> 00:01:51,000 50 | 面試中 面談中的一些對答 51 | 再來就是結束後的一些 52 | 00:01:51,000 --> 00:01:55,000 53 | 和面試官也好, 54 | 或是 跟人資也好的應對進退 55 | 00:01:55,000 --> 00:02:01,000 56 | 這是整個 57 | 一個面試蠻重要的環節 58 | 00:02:01,000 --> 00:02:07,000 59 | 就主要包括這三個部分 60 | 首先我們來探討面試前的準備 61 | 00:02:07,000 --> 00:02:12,000 62 | 在技術面試的話,事實上 63 | 一般的技術面試 64 | 00:02:12,000 --> 00:02:19,000 65 | 蠻重要是強調技術的扎實度和技術的吻合度 66 | 00:02:19,000 --> 00:02:29,000 67 | 所以蠻建議大家經營自己的技術部落格 68 | 或參與開放原始碼的專案或社群 69 | 00:02:29,000 --> 00:02:36,000 70 | follow整個社群有什麼新技術可以嘗試 71 | 00:02:36,000 --> 00:02:42,000 72 | 因為在這個領域尤其是前端 73 | 00:02:42,000 --> 00:02:44,000 74 | 可能有聽過前端摩爾定律 75 | 00:02:44,000 --> 00:02:49,000 76 | 每半年就有很多新的技術和框架出來 77 | 00:02:49,000 --> 00:02:59,000 78 | 唯有保持敏銳持續觀察才能在這個行業進步專業能力 79 | 00:02:59,000 --> 00:03:02,000 80 | 淨化自己的網路資訊 81 | 00:03:02,000 --> 00:03:09,000 82 | 很多學員可能在很多社群網路facebook、plurk、twitter 83 | 00:03:09,000 --> 00:03:12,000 84 | 發一些心情抒發的訊息 85 | 00:03:12,000 --> 00:03:20,000 86 | 但現在透過一些管道,人資或面談主管 87 | 00:03:20,000 --> 00:03:26,000 88 | 透過網路去搜尋社群網站一些相關資料 89 | 00:03:26,000 --> 00:03:32,000 90 | 如果這些資料對你不是有正面加分的話就盡量避免 91 | 00:03:32,000 --> 00:03:50,000 92 | 累積簡歷上的作品,包括學校競賽、打工實習、自己接案子 93 | 00:03:50,000 --> 00:03:57,000 94 | 這些都是佐證你能力蠻重要的重點 95 | 00:03:57,000 --> 00:04:06,000 96 | 有些公司要求比較嚴謹,大型的網路公司 97 | 00:04:06,000 --> 00:04:10,000 98 | 科技公司,包括facebook、google 99 | 00:04:10,000 --> 00:04:21,000 100 | 等等,除了前端的相關技術之外也很要求軟體工程的專業技術 101 | 00:04:21,000 --> 00:04:31,000 102 | 所以盡可能去累積自己軟體工程相關知識,如果要挑戰這些 103 | 企業的話是必須的 104 | 00:04:31,000 --> 00:04:40,000 105 | 這裡提到了一些網站 106 | 00:04:40,000 --> 00:04:43,000 107 | 有些面談可能要你寫程式 108 | 00:04:43,000 --> 00:04:47,000 109 | 包括演算法、資料結構相關的一些題目 110 | 00:04:47,000 --> 00:05:04,000 111 | 蠻鼓勵大家利用線上的這些平台 112 | 00:05:04,000 --> 00:05:08,000 113 | 這有點像是工程師的GRE 114 | 00:05:08,000 --> 00:05:14,000 115 | GRE就是你可能要出國留學英文的測試 116 | 00:05:14,000 --> 00:05:20,000 117 | 這裡有列出了一些資料結構、演算法的相關問題 118 | 00:05:20,000 --> 00:05:27,000 119 | 你可以點選比較簡單的題目先開始 120 | 00:05:27,000 --> 00:05:33,000 121 | 它裡面有一些題目,這邊看到是通過率 122 | 00:05:33,000 --> 00:05:39,000 123 | 我們這邊可以選擇javascript因為在前端開發 124 | 比較重要是javascropt這個程式語言 125 | 00:05:39,000 --> 00:05:51,000 126 | 在這個練習可以學祥api和資料結構演算法 127 | 的相關知識 128 | 00:05:57,000 --> 00:06:00,000 129 | 接下來介紹前端面試的概論 130 | 00:06:00,000 --> 00:06:07,000 131 | 在前端工程師的職位,他的光譜非常大 132 | 00:06:07,000 --> 00:06:16,000 133 | 有比較偏向設計,也有偏向軟體工程師的範疇 134 | 00:06:16,000 --> 00:06:25,000 135 | 在一些大型的IT或網路公司,通常視前端工程師為 136 | 軟體工程師 137 | 00:06:25,000 --> 00:06:38,000 138 | 前端工程師只是一個領域,他們希望部是哪種工程師 139 | 都能快速上手該領域的專業知識 140 | 00:06:38,000 --> 00:06:47,000 141 | 所以足夠solid的一些知識也是足夠必須要求的 142 | 00:06:47,000 --> 00:06:54,000 143 | 所以建議學員定位自己比較希望往哪發展 144 | 00:07:15,000 --> 00:07:19,000 145 | 都沒有關係,找好自己的定位 146 | 00:07:19,000 --> 00:07:27,000 147 | 相信你在面試工程師的時候,都會對你職涯有幫助 148 | 00:07:27,000 --> 00:07:36,000 149 | 不同公司對前端工程師有不同要求 150 | 00:07:36,000 --> 00:07:48,000 151 | 大家可以去人力銀、104 152 | 00:07:48,000 --> 00:07:55,000 153 | 或者是去你感興趣的公司 154 | 00:07:55,000 --> 00:08:05,000 155 | 一些招募招聘的一些資訊,看一下說有沒有招募前端工程師 156 | 00:08:05,000 --> 00:08:12,000 157 | 他在前端工程師的要求是怎樣的情況 158 | 00:08:12,000 --> 00:08:26,000 159 | 可以印出來看看那些我還不具備 160 | 00:08:26,000 --> 00:08:36,000 161 | 相信大家能夠進到理想公司,獲得理想工作的機會 162 | 00:08:36,000 --> 00:08:39,000 163 | 我們先來看F公司 164 | 00:08:39,000 --> 00:08:43,000 165 | F公司有四點重要要求 166 | 00:08:43,000 --> 00:08:53,000 167 | 3年的javascript經驗,非同步programming經驗 168 | 00:08:53,000 --> 00:09:03,000 169 | 我們在課堂提到ajax非同步,promise、closure 170 | types;ES6 171 | 00:09:03,000 --> 00:09:17,000 172 | F公司主要是用React當一個蠻重要的library 173 | 00:09:17,000 --> 00:09:32,000 174 | 第3點就是提到3年以上HTML。CSS相關經驗 175 | 包括排版、specificity權重,還有跨瀏覽器的一些資源 176 | 00:09:32,000 --> 00:09:40,000 177 | 還有就是API還有就是優化的相關經驗 178 | 00:09:40,000 --> 00:09:43,000 179 | 這是F公司前端的徵才文 180 | 00:09:43,000 --> 00:09:47,000 181 | 這是Y公司前端的徵才文 182 | 00:09:47,000 --> 00:09:56,000 183 | 同樣也是希望computer science的相關領域 184 | 00:09:56,000 --> 00:10:24,000 185 | 你有一些作品或一些開放原始碼的經驗,或一些令人驚艷 186 | 的特質,我們不要被這些明訂的標準限制住 187 | 00:10:24,000 --> 00:10:38,000 188 | 有時候這些要求只是理想的,不一定要符合這些要求才能進 189 | 到這家公司服務 190 | 00:10:38,000 --> 00:10:52,000 191 | 還有就是對server side程式語言,包括PHP,nodejs,jQuery 192 | 之類的framework的一些了解 193 | 00:10:52,000 --> 00:10,59,000 194 | 還有像是bootstrap、pure之類framework的一些了解 195 | 00:10:59,000 --> 00:11:03,000 196 | 還有一些次是工具,這是Y公司的前端徵才文 197 | 00:11:03,000 --> 00:11:12,000 198 | P公司的javascript的使用經驗 199 | 00:11:12,000 --> 00:11:18,000 200 | 還有跨瀏覽器,還有response design的相關經驗 201 | 00:11:18,000 --> 00:11:26,000 202 | 接下來講一下一般技術面式的流程 203 | 00:11:26,000 --> 00:11:32,000 204 | 面試的結果很多和事前和事後的準備是有關的 205 | 00:11:32,000 --> 00:11:38,000 206 | 通常技術面試會分為四部分 207 | 00:11:38,000 --> 00:11:45,000 208 | 簡歷審核,內推就是可能用內部推薦的方式 209 | 00:11:45,000 --> 00:11:48,000 210 | 校園招募啊,社會招募,或獵人頭公司 211 | 00:11:48,000 --> 00:11:54,000 212 | 獲取一些機會的管道 213 | 00:11:54,000 --> 00:12:02,000 214 | 通常簡歷通過的話會有phone interview 215 | 00:12:02,000 --> 00:12:09,000 216 | 所謂phone interview可能透過電話、skype、google handout 217 | 都有可能 218 | 00:12:09,000 --> 00:12:16,000 219 | 通常會要求自我介紹並問一些基本的技術問題 220 | 00:12:16,000 --> 00:12:30,000 221 | 有可能用codebunk或codepad去使用 222 | 00:12:30,000 --> 00:12:37,000 223 | 在使用過程中面試官也會同步看到你coding的畫面 224 | 00:12:37,000 --> 00:12:49,000 225 | 在你打的時候面試官會出題目,同步看到你編寫的過程 226 | 00:12:49,000 --> 00:12:57,000 227 | 去評斷你寫程式的能力 228 | 00:12:57,000 --> 00:13:07,000 229 | 另一種事前出一份作業,在一定的時間內回傳 230 | 00:13:07,000 --> 00:13:10,000 231 | 去評斷你的能力到底怎樣 232 | 00:13:10,000 --> 00:13:16,000 233 | 如果通過phone interview和前測就會受邀參加 234 | onsite interview 235 | 00:13:16,000 --> 00:13:26,000 236 | onsite interview就是到公司跟資深工程師、PM、人資去做面談 237 | 00:13:26,000 --> 00:13:34,000 238 | 通常會有兩部分的題目,包括behavior就是你的人格特質 239 | 00:13:34,000 --> 00:13:41,000 240 | 或者是對你過去的一些考核和檢驗 241 | 00:13:41,000 --> 00:13:45,000 242 | 另外蠻重要就是techinical的測驗 243 | 00:13:45,000 --> 00:13:49,000 244 | 包括紙筆測驗或是問答 245 | 00:13:49,000 --> 00:13:53,000 246 | 可能有些同學有聽過白板題 247 | 00:13:53,000 --> 00:13:58,000 248 | 就是在白板上直接寫出程式碼,和面試官討論 249 | 00:13:58,000 --> 00:14:06,000 250 | 很順利通過這些關卡的話,會有HR interview 251 | 00:14:06,000 --> 00:14:12,000 252 | 待會也會介紹相關的細節 253 | 00:14:12,000 --> 00:14:21,000 254 | 主要聊一些公司文化阿或薪資待遇的議題 255 | 00:14:21,000 --> 00:14,26,000 256 | 首先,前端問題的一些研討 257 | 00:14:26,000 --> 00:14:35,000 258 | 這裡提供三個連結,是有關面試的常見問題 259 | 00:14:35,000 --> 00:14:40,000 260 | 有些有參考的解決方法,有些沒有 261 | 00:14:40,000 --> 00:14:50,000 262 | 去檢查有那些是我們不足或不理解的 263 | 00:14:50,000 --> 00:14:56,000 264 | 是一個road map的方式讓大家理解哪裡還不足 265 | 00:14:56,000 --> 00:15:01,000 266 | 大家點擊進去就可以看到了 267 | 00:15:01,000 --> 00:15:11,000 268 | 這裡有繁體中文簡體中文和英文版 269 | 00:15:11,000 --> 00:15:15,000 270 | 比較建議看英文版的部分,因為他是有持續在更新的 271 | 00:15:15,000 --> 00:15:20,000 272 | 如果不習慣的話可以去看繁體中文或簡體中文都是可以的 273 | 00:15:20,000 --> 00:15:25,000 274 | 我們看到上面有很多前端相關的問答 275 | 00:15:25,000 --> 00:15:28,000 276 | 這裡面還又一些延伸閱讀,大家可以參考一下 277 | 00:15:28,000 --> 00:15:36,000 278 | 首先在面試過程通常都會自我介紹 279 | 00:15:36,000 --> 00:15:47,000 280 | 包括自己的工作經驗、學經歷、為什麼要加入這個團隊 281 | 、能有什麼貢獻 282 | 00:15:47,000 --> 00:15:53,000 283 | 通常有些外商公司會希望你用英文自我介紹,或用英文問答 284 | 00:15:53,000 --> 00:15:58,000 285 | 這些都是可以在事前做一些模擬跟準備的 286 | 00:15:58,000 --> 00:16:12,000 287 | HTML的問題,我們列出來的問題過去都有提到 288 | 如果學員有映像的話 289 | 00:16:12,000 --> 00:16:30,000 290 | 課程之前有埋下一些伏筆,前端面試相關問題,如果當下學不清楚的話 291 | 沒有關係,這編列了一些重點 292 | 00:16:30,000 --> 00:16:42,000 293 | 可以去回憶過去學得有沒有熟悉再去做補強查詢 294 | 00:16:42,000 --> 00:16:50,000 295 | 首先是確保知道什麼是doctype 296 | 00:16:50,000 --> 00:16:56,000 297 | 我們之前講過,用一句話講的話,就是讓瀏覽器知道你的版本是什麼 298 | 00:16:56,000 --> 00:17:02,000 299 | 我們在html5已經簡化這樣的一個過程 300 | 00:17:02,000 --> 00:17:09,000 301 | 可以這樣去宣告HTML的版本 302 | 00:17:09,000 --> 00:17:18,000 303 | 那如果用舊的版本或沒有宣告的話,瀏覽器可能會出現一些問題, 304 | 大家注意一下 305 | 00:17:18,000 --> 00:17:20,000 306 | HTML5有哪些語意標籤呢? 307 | 00:17:20,000 --> 00:17:31,000 308 | 在這邊可以看到一些語意標籤,我們過去可能div、span這些標籤 309 | 但這些只是排版 310 | 00:17:31,000 --> 00:17:42,000 311 | 這裡包括header、footer,footer就是關於版權說明阿或加入我們 312 | 之類的東西 313 | 00:17:42,000 --> 00:17:50,000 314 | 這個就是語意標籤,就是搜尋引擎檢索,讓你頁面更語意化的一種 315 | 方式 316 | 00:17:50,000 --> 00:18:04,000 317 | javascript引入,之前我們講過盡量在body關掉之前 318 | 00:18:04,000 --> 00:18:08,000 319 | 這邊可以看到script的引入 320 | 00:18:08,000 --> 00:18:18,000 321 | 如果dom還沒載入完就引入的話,會造成一些問題 322 | 00:18:18,000 --> 00:18:20,000 323 | 那這邊要特別注意 324 | 00:18:20,000 --> 00:18:26,000 325 | 那form表單有post和get之前講過 326 | 00:18:26,000 --> 00:18:28,000 327 | http的方法比較常見有post跟get 328 | 00:18:28,000 --> 00:18:40,000 329 | get的話就是寄明信片,內容都會被看到 330 | 就會顯示在網址上面,你的資料傳遞 331 | 00:18:40,000 --> 00:18:47,000 332 | 那post的話就不是了,他會在http的內容裡面 333 | 00:18:47,000 --> 00:18:57,000 334 | 比較建議登入登出用post的方法處理 335 | 00:18:57,000 --> 00:19:11,000 336 | 事實上我們可以搜尋,在query這裡就是我們get方法的 337 | 00:19:11,000 --> 00:19:20,000 338 | 項,這個的話我們就知道是get方法,蠻明顯的例子 339 | 00:19:20,000 --> 00:19:27,000 340 | 那HTML5離線儲存,我們之前在local storage 、session storage 341 | 有講過 342 | 00:19:27,000 --> 00:19:32,000 343 | 那大家可以再去比較一下session、localstorage、cookie 344 | 之間的差別 345 | 00:19:32,000 --> 00:19:36,000 346 | css 基礎知識的掌握 347 | 00:19:36,000 --> 00:19:41,000 348 | 這個部分我們講過怎麼用css兩籃式的排版 349 | 00:19:41,000 --> 00:19:53,000 350 | 大家可以回憶一下,像是position相對定位絕對定位、float方式、flexbox 351 | 00:19:53,000 --> 00:20:00,000 352 | 這邊有蠻不錯的一個網站大家可以去看一下 353 | 00:20:00,000 --> 00:20:07,000 354 | 這是css版面配置的一個練習網站 355 | 00:20:07,000 --> 20:15:00,000 356 | 這裡介紹了css版面配置的所有知識都在裡面 357 | 00:20:15,000 --> 00:20:17,000 358 | 鼓勵大家可以去看一下 359 | 00:20:17,000 --> 00:20:21,000 360 | 什麼是css選擇器,我們也講過 361 | 00:20:21,000 --> 00:20:25,000 362 | 最簡單的說法就是選擇器和你要改變的宣告 363 | 00:20:25,000 --> 00:20:32,000 364 | 你選到什麼元素,你要改變它的顏色或背景 365 | 00:20:32,000 --> 00:20:50,000 366 | pseudo class是什麼呢?pseudo-classes是,之前我們滑進跟點選 367 | 的冒號後面有一個state說明點擊還是滑進的狀況 368 | 00:20:50,000 --> 00:20:55,000 369 | 這些就是pseudo class的一些相關概念 370 | 00:20:55,000 --> 00:20:58,000 371 | css選擇器有很多,大家可以在去複習一下 372 | 00:20:58,000 --> 00:21:13,000 373 | 那box model的話,再css有講過,我們講過空城計的例子 374 | 就是說,我們有content,padding,border跟margin 375 | 00:21:13,000 --> 00:21:26,000 376 | 這樣去定義我們內容、距離、或留白寬度 377 | 00:21:26,000 --> 00:21:34,000 378 | 這個box model大家可以去css在仔細的研究一下 379 | 00:21:34,000 --> 00:21:37,000 380 | 那什麼是css sprites呢? 381 | 00:21:37,000 --> 00:21:51,000 382 | css sprites是一個實務上蠻常用的觀念,他是,為什麼要用css sprites 383 | 呢? 384 | 00:21:51,000 --> 00:21:58,000 385 | 前端開發效能的優化是蠻重要的 386 | 00:21:58,000 --> 00:22:09,000 387 | 當你送出一個request請求到你server side或其他地方 388 | 00:22:09,000 --> 00:22:13,000 389 | 請求資源都會造成資源的消耗 390 | 00:22:13,000 --> 00:22:25,000 391 | 如果一個站點,如果我們圖片很多的話,大家還記得嗎? 392 | src 393 | 00:22:25,000 --> 00:22:28,000 394 | 在 image裡面src 395 | 00:22:28,000 --> 00:22:35,000 396 | 如果說 397 | 00:22:46,000 --> 00:23:00,000 398 | 如果我們很多圖片都用src去送出請求,會影響前端頁面的效能 399 | 00:23:00,000 --> 00:23:06,000 400 | 所以我們就衍生出css sprites的技術 401 | 00:23:06,000 --> 00:23:15,000 402 | 大家可能有看過,把好多圖片和成一張圖片 403 | 00:23:19,000 --> 00:23:27,000 404 | 可以看到這邊 大家可能有看過,把好多圖片和成一張圖片 405 | 00:23:27,000 --> 00:23:33,000 406 | 那這樣每次只要載入一張圖片 407 | 00:23:33,000 --> 00:23:38,000 408 | 那我們再用css定位的方法,這邊有個例子 409 | 00:23:38,000 --> 00:23:43,000 410 | 這邊有個例子,這邊有張圖片這樣子 411 | 00:23:45,000 --> 00:23:49,000 412 | 這邊有張圖片,回首頁、上一頁、下一頁 413 | 00:23:49,000 --> 00:23:53,000 414 | 這是合併成一張圖片,事實上他是三個icon 415 | 00:23:53,000 --> 00:24:02,000 416 | 大家可以看到,也就是說使用上就只要載入一張圖片就好, 417 | 我們可以用css手法 418 | 00:24:02,000 --> 00:24:06,000 419 | 也就是這裡image id=home然後#id name嗎 420 | 00:24;06,000 --> 00:24:12,000 421 | 這邊就用url background去載入想要的圖片 422 | 00:24:12,000 --> 00:24:20,000 423 | 那我們這裡用 0 0 424 | 00:24:26,000 --> 00:24:30,000 425 | 那我們這裡用 0 0的圖片,我們就可以看到說,調整一下會怎樣 426 | 00:24:47,000 --> 00:24:53,000 427 | 可以看到說我這邊圖片都一直在改變 428 | 00:24:53,000 --> 00:24:57,000 429 | 可以看到位置 430 | 00:25:15,000 --> 00:25:26,000 431 | 大家有發現嗎?我去調整的話可以看到圖片的一些變動 432 | 00:25:26,000 --> 00:25:42,000 433 | 透過這樣的方式我們可以再同一張圖對我們想要的圖片 434 | 00:25:42,000 --> 00:25:56,000 435 | 通常我們這樣使用太麻煩了,所以通常會用這樣的工具, 436 | css sprite generator 437 | 00:25:56,000 --> 00:26:19,000 438 | 你把你想要的圖片放進來,這裡可以載入圖片,案download 439 | 他就會出現html css相關的資訊 440 | 00:26:19,000 --> 00:26:23,000 441 | 你可以複製這個,她就幫你定位好,你就不須自己去手動定位 442 | 00:26:23,000 --> 00:26:34,000 443 | 這就非常方便,你有這六張圖,她就幫你定位icon這樣子 444 | 00:26:38,000 --> 00:26:45,000 445 | 那最後一個css比較需要掌握的重點就是RWD的設計 446 | 00:26:45,000 --> 00:26:28,000 447 | RWD全名叫response web deaign 448 | 00:26:28,000 --> 00:26:53,000 449 | 也被稱為自適應設計或響應式設計 450 | 00:26:53,000 --> 00:27:14,000 451 | 主要的概念就是,透過css設計,讓在不同device螢幕大小 452 | 的是使用者享受到最好的體驗 453 | 00:27:14,000 --> 00:27:21,000 454 | 我們可以看一下這邊 455 | 00:27:25,000 --> 00:27:27,000 456 | 網路上有些response design的範例 457 | 00:27:38,000 --> 00:28:00,000 458 | 大概會長這樣子,會跟著螢幕大小,通常我們會有一個 459 | 叫media query的語法判斷 460 | 00:28:00,000 --> 00:28:11,000 461 | 他會去偵測大小,去偵測使用者最舒服的一個方式 462 | 00:28:11,000 --> 00:28:18,000 463 | 像這個本來340的畫面就變成140 464 | 00:28:18,000 --> 00:28:27,000 465 | 蠻適合去閱讀的,這就是response design的情境 466 | 00:28:27,000 --> 00:28:43,000 467 | 有很多小細節,就像這裡google設計師就有教人怎麼做response 468 | design 469 | 00:28:43,000 --> 00:29:00,000 470 | 這邊有動畫,大家可以拉動瀏覽器,當不同螢幕大小,會有不同畫面的 471 | 產生 472 | 00:29:00,000 --> 00:29:11,000 473 | 我們可以看到有些重要的設計,像是這裡viewport參數 474 | 00:29:30,000 --> 00:29:35,000 475 | 還有這裡media query螢幕大小在500到600之間 476 | 這些元素要怎麼設計 477 | 00:29:35,000 --> 00:29:43,000 478 | 大家可以參考一下其他學習資源 479 | 00:29:43,000 --> 00:29:49,000 480 | 接下來要講一下,javascript比較重要的觀念 481 | 00:29:49,000 --> 00:30:04,000 482 | 包括javascript的型別轉換,大家可以想,包括字串怎麼轉成數值、 483 | 使用pass integer或者是用number把字串丟進去 484 | 00:30:04,000 --> 00:30:10,000 485 | 這樣的一些方法就可以做型別轉換 486 | 00:30:10,000 --> 00:30:17,000 487 | 也要注意字串和數字相加會怎樣,大家可以嘗試看看 488 | 00:30:17,000 --> 00:30:23,000 489 | 這裡先往下看 490 | 00:30:23,000 --> 00:30:38,000 491 | scope生存域,講過的javascript是function scope也就是會存活在 492 | function之間,如果離開function就會結束生存 493 | 00:30:38,000 --> 00:30:42,000 494 | 注意包括var、const、let的一些用法 495 | 00:30:42,000 --> 00:30:47,000 496 | 怎樣用javascript建構函式去new物件? 497 | 00:30:47,000 --> 00:31:00,000 498 | 這在物件的單元就又講了,大家不熟悉的話再去複習 499 | 包括prototype怎樣建置,還有繼承的一些觀念 500 | 00:31:00,000 --> 00:31:09,000 501 | 大家再去複習一下關於物件的重點,面試很有可能出現 502 | 00:31:09,000 --> 00:31:32,000 503 | apply/call這牽扯到this用法,前面也講過四五種用法 504 | 包括指到物件 505 | 00:31:32,000 --> 00:31:37,000 506 | 要注意到apply後面是接陣列,call是直接塞進去 507 | 00:31:37,000 --> 00:31:43,000 508 | 大家忘記的話再去複習之前的內容 509 | 00:31:47,000 --> 00:32:11,000 510 | 那氣泡傳遞在你在觸發事件的時候,氣泡傳遞在第三個參數 511 | 第一個是事件名稱包括click 512 | 00:32:11,000 --> 00:32:23,000 513 | 或double click,中間是event handler名稱﹑第三個就是傳遞方式 514 | 00:32:23,000 --> 00:32:40,000 515 | false就是氣泡傳遞,氣泡傳遞就是就是觸發的地方往外傳 516 | 00:32:40,000 --> 00:32:46,000 517 | 什麼是ajax呢,我們在非同步處理有提到 518 | 00:32:46,000 --> 00:32:59,000 519 | promise就是在解決回掉地獄,非同步處理,處理完可以做其他事情 520 | 00:32:59,000 --> 00:33:19,000 521 | DOM一些基礎操作,包括document去做一些新增刪除元素, 522 | 搭配事件處理操作 523 | 00:33:19,000 --> 00:33:26,000 524 | 這裡有延伸閱讀,家有興趣可以參考一下 525 | 00:33:26,000 --> 00:33:36,000 526 | 裡面有javascript常見的面試題目,包括closure的觀念,有時也會在面 527 | 談出現 528 | 00:33:36,000 --> 00:33:42,000 529 | 在之前的單元也有提到,可以再複習 530 | 00:33:42,000 --> 00:33:48,000 531 | 除了一些前端三劍客比較基礎的問題 532 | 00:33:48,000 --> 00:34:01,000 533 | 面談時也會問到其餘的一些問題,包含 534 | 你用過那些框架或函式庫,優點缺點是什麼呢 535 | 00:34:01,000 --> 00:34:16,000 536 | 你可能講你用過react這個library,他是facebook的library 537 | 是跨平台開發 538 | 00:34:16,000 --> 00:34:40,000 539 | 他提出了現在前端的一些主流技術,包括component 540 | virtual dom,跨平台的方式都是他一些優點 541 | 00:34:40,000 --> 00:34:52,000 542 | 缺點相對學習門檻比較高一點 543 | 00:34:52,000 --> 00:35:03,000 544 | 前端優化,像剛剛css sprites也是某種程度優化 545 | 00:35:03,000 --> 00:35:26,000 546 | 在瀏覽器timeline我們可以去看那些script、那些元素是最花時間的 547 | 00:35:37,000 --> 00:36:03,000 548 | 這裡可以看一下,哪個可能佔去最多時間,我們就可以知道怎麼去優化 549 | 00:36:03,000 --> 00:36:15,000 550 | 除了css sprites還有像是CDN css javascript壓縮 551 | 00:36:15,000 --> 00:36:16,000 552 | 這些都是前端優化的方法 553 | 00:36:16,000 --> 00:36:21,000 554 | 大家可以去網路上或找書來看 555 | 00:36:21,000 --> 00:36:24,000 556 | 瀏覽器在載入頁面發生什麼呢? 557 | 00:36:24,000 --> 00:36:34,000 558 | 這是一個蠻全面的探討,這有比較簡單的講法,也有複雜的 559 | 00:36:34,000 --> 00:37:19,000 560 | 我們可以看成說當輸入網址十,會交給DNS域名解釋,轉換成ip位置 561 | 像這個位置的server發出請求,在請求後,後台會做一些處理 562 | 00:37:19,000 --> 00:37:46,000 563 | 如果是靜態網頁他就直接吐回html css javascript,在瀏覽器接 564 | 下來就會組裝起來做一些解析,繪製出相應的結構 565 | 00:37:46,000 --> 00:38:36,000 566 | 大家可以參考這個網頁,是比較複雜的講法 567 | 00:38:36,000 --> 00:38:57,000 568 | 我們可以看一下這邊,他會經過這樣的過程,結合成DOM tree 569 | 00:38:57,000 --> 00:39:36,000 570 | 最後他會進行browser render pipeline的管道,最終呈現給使用者 571 | 00:39:36,000 --> 00:40:08,000 572 | 包括怎麼跟設計師溝通,或最近有什麼前端的新技術 573 | 00:40:08,000 --> 00:40:14,000 574 | 最後通常會有面試官問你有沒有問題要問我們 575 | 00:40:14,000 --> 00:41:10,000 576 | 鼓勵大家在事前做功課,包括團隊新聞,事實的提出見解或看法詢問 577 | 00:41:10,000 --> 00:41:35,000 578 | 在結束技術面試後,通常有HR的面談 579 | 00:41:35,000 --> 00:42:15,000 580 | 在這個單元中我們提到面試前準備等等 581 | 00:42:15,000 --> 00:42:18,000 582 | 最後還是鼓勵大家像是github等等,都是在未來有些幫助 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | --------------------------------------------------------------------------------
      消費項目消費類別消費金額消費時間操作
      買書lifeNT 3002016/10/10 55 | 56 | 57 |
      看電影playNT 6002016/10/10 65 | 66 | 67 |
      消費項目消費類別消費金額消費時間操作
      ${data[key].title}${data[key].type}NT ${data[key].number}${data[key].date} 63 | 64 | 65 |
      消費項目消費類別消費金額消費時間操作
      ${data[key].title}${data[key].type}NT ${data[key].number}${data[key].date} 63 | 64 | 65 |
      消費項目消費類別消費金額消費時間操作
      ${data[key].title}${data[key].type}NT ${data[key].number}${data[key].date} 63 | 64 | 65 |