CHAPTER 3 ทำ�งานกับสว่ นแสดงผลดว้ ย Pug และ Static Files index.js (ต่อ) 8 app.get(‘/products’, function (req, res) { 9 res.sendFile(__dirname + ‘/public/products.html’); 10 }); 11 12 app.listen(3000, function () { 13 console.log(‘Express running on port 3000’) 14 }); จากสครปิ ตข์ ้างตน้ ใหเ้ ข้ามาทพี่ าธ localhost:3000/products พบว่าเราสามารถสง่ั ให้ ไฟล์ products.html แสดงผลโดยตรงไดเ้ ช่นกนั ดงั รปู ท่ี 3-8 รูปท่ี 3-8 แสดงไฟล์ products.html ถกู เรยี กใชง้ านโดยตรง อธิบายการท�ำ งานของสคริปต์ หลกั การอา้ งองิ รายการ Static Files ท่เี กบ็ อยู่ในโฟลเดอร์ public ประกอบด้วย ÂÂ __dirname ทำ�หนา้ ที่แทนพาธของโปรเจก็ ตป์ จั จุบัน ÂÂ ระบโุ ฟลเดอร์ public และไฟล์ products.html index.js 1 app.get(‘/products’, function (req, res) { 2 res.sendFile(__dirname + ‘/public/products.html’); 3 }); การตกแตง่ ไฟล์ HTML5 ด้วย CSS สำ� หรบั การตกแตง่ สว่ นแสดงผลในหนา้ เวบ็ เพจ เปน็ หนา้ ทขี่ องCascadingStyleSheets เรียกย่อๆ ว่า CSS มไี ฟล์นามสกลุ .css แบ่งแยกหนา้ ที่กันอย่างชัดเจน กล่าวคอื ÂÂ ไฟล์ HTML5 ทำ�หน้าทแี่ สดงผล ÂÂ ไฟล์ CSS ทำ�หนา้ ที่ตกแตง่ สว่ นแสดงผล เราถือวา่ ไฟล์ CSS เป็น Static Files ประเภทหนึง่ เม่อื สรา้ งขึน้ มาแลว้ ก็ไมต่ ้องไปยงุ่ กับ สคริปตใ์ นไฟล์ CSS อกี รอเรียกใชง้ านอย่างเดยี ว ขึ้นอยกู่ ับว่าเราตอ้ งการตกแต่งหนา้ เว็บเพจ ด้วย CSS อยา่ งไร ScJraivpat 45
ตวั อยา่ งที่ 3-2 การตกแต่งไฟล์ HTML5 ดว้ ย CSS มขี น้ั ตอนดังน้ี 1. ภายในโฟลเดอร์ public ผู้เขยี นสรา้ งไฟล์ HTML5 เพิ่มขน้ึ มาอีก 2 ไฟล์ คอื hh ไฟล์ products.html ทำ�หน้าท่ีแสดงรายการสินค้า เป็น ไฟล์เดมิ ทเ่ี รามอี ย่แู ลว้ hh ไฟล์ store.html ทำ�หน้าทแ่ี สดงสินคา้ ในสต๊อก hh ไฟล์ styles.css ทำ�หน้าท่ีตกแต่งส่วนแสดงผลให้กับไฟล์ products.html รปู ท ี่ 3-9 แสดงรายการไฟลใ์ นโฟลเดอร์ public สคริปต์ HTML5 ท่ี 3-2 การตกแตง่ ไฟล์ HTML5 ด้วย CSS (\\public\\products.html) 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=“utf-8”> 5 <meta http-equiv=“X-U3-Compatible” content=“IE=edge”> 6 <title></title> 7 <link type=“text/css” rel=“stylesheet” href=“styles.css” /> 8 </head> 9 <body> 10 <h1>Product Page</h1> 11 <a href=“store.html”>Go to Store</a> 12 </body> 13 </html> สคริปต์ HTML5 ท่ี 3-2 การตกแต่งไฟล์ HTML5 ดว้ ย CSS (\\public\\store.html) 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=“utf-8”> 5 <meta http-equiv=“X-U3-Compatible” content=“IE=edge”> 6 <title></title> 46
CHAPTER 3 ทำ�งานกับส่วนแสดงผลด้วย Pug และ Static Files สคริปต์ HTML5 ท่ี 3-2 การตกแตง่ ไฟล์ HTML5 ด้วย CSS (\\public\\store.html) 7 </head> 8 <body> 9 <h1>Store Page</h1> 10 <a href=“/products”>Home</a> 11 </body> 12 </html> สครปิ ต์ CSS ท่ี 3-2 การตกแตง่ ไฟล์ HTML5 ด้วย CSS (\\public\\styles.css) 1 body { 2 color:#FFFFFF; 3 background-color:#FF0000; 4} 5 6 a:hover { 7 text-decoration:none; 8} 2. ต่อมา ท่ไี ฟล์ index.js ใหเ้ ขียนสครปิ ตด์ งั ต่อไปน้ี สครปิ ต์ Express ที่ 3-2 การตกแตง่ ไฟล์ HTML5 ดว้ ย CSS (index.js) 1 var express = require(‘express’); 2 var app = express(); 3 4 app.use(express.static(__dirname + ‘/public’)); 5 6 app.get(‘/’, function (req, res) { 7 res.send(‘Hello Express’); 8 }); 9 10 app.get(‘/Products’, function (req, res) { 11 res.redirect(‘products.html’) 12 }); 13 14 app.listen(3000, function () { 15 console.log(‘Express running on port 3000’) 16 }); ScJraivpat 47
3. ใหท้ ดสอบรนั ตวั อยา่ ง(nodeindex) ผลการทำ�งาน แสดงดงั รูปท่ี 3-10 รูปท ี่ 3-10 ผลการรนั ตัวอย่างที่ 3-2 จากรปู ที่ 3-10 ผเู้ ขยี นตกแตง่ ใหเ้ พจ products.html มพี น้ื หลงั เปน็ สแี ดง ขอ้ ความสขี าว มลี ิงค์เช่อื มโยงไปทหี่ น้าเพจ store.html 4. ผู้เขยี นตกแต่งทีล่ งิ ค์เพ่ิมเตมิ เมื่อผู้ใชง้ านเอาเมาสไ์ ปลอยอยูเ่ หนือลิงค์ ขดี เสน้ ใต้ก็ จะหายไป เน่อื งจากกำ�หนดในไฟล์ styles.css รูปท่ ี 3-11 แสดงลิงค์ที่ได้ จากรูปท่ี 3-11 เราได้เว็บเพจแสดงรายการสินค้าที่ถูกตกแต่งด้วย CSS และมีลิงค์ เชอ่ื มโยงไปหนา้ เวบ็ เพจ store.html แลว้ อธิบายการท�ำ งานของสคริปต์ 1. ที่ไฟล์ index.js เมอ่ื ผใู้ ชง้ านร้องขอแบบ get มาท่พี าธ /Products กำ�หนดใหไ้ ปท่ี เพจ products.html index.js 1 app.get(‘/Products’, function (req, res) { 2 res.redirect(‘products.html’) 3 }); 2. ในไฟล์ products.html กำ�หนดให้อ้างอิงใช้งาน CSS ที่ชื่อว่า styles.css ระหว่าง อลิ ีเมนต์ <head>…</head> \\public\\products.html 1 <head> 2 <meta charset=“utf-8”> 3 <meta http-equiv=“X-U3-Compatible” content=“IE=edge”> 4 <title></title> 5 <link type=“text/css” rel=“stylesheet” href=“styles.css” /> 6 </head> 48
CHAPTER 3 ท�ำ งานกับสว่ นแสดงผลด้วย Pug และ Static Files 3. เนื้อหาภายในไฟล์ products.html มีเพียงอย่างเดียว นั่นคือ สร้างลิงค์ไปที่เพจ store.html \\public\\products.html 1 <body> 2 <h1>Product Page</h1> 3 <a href=“store.html”>Go to Store</a> 4 </body> 4. สว่ นทเ่ี พจ store.html กม็ เี พยี งลงิ คก์ ลบั มาทห่ี นา้ products.html (href= /products) \\public\\store.html 1 <body> 2 <h1>Store Page</h1> 3 <a href=“/products”>Home</a> 4 </body> 5. การตกแต่งสว่ นแสดงผลในไฟล์ styles.css มเี พียง 2 สว่ น คอื ÂÂ อลิ เี มนต์ body เนื้อหาท่แี สดงอยรู่ ะหวา่ งอลิ เี มนต์ <body>…</body> กำ�หนดให้ ใชข้ ้อความสีขาว (color:#FFFFFF) พ้นื หลงั สแี ดง (background-color:#FF0000) \\public\\styles.css 1 body { 2 color:#FFFFFF; 3 background-color:#FF0000; 4} ÂÂ อิลีเมนต์ a เม่ือเมาส์ลอยอยู่เหนือลิงค์ (a:hover) กำ�หนดให้แสดงข้อความแบบ ปกติ (text-decoration:none) \\public\\styles.css 1 a:hover { 2 text-decoration:none; 3} ScJraivpat 49
พน้ื ฐานการสรา้ งสว่ นแสดงผลด้วย Pug รูปแบบพ้นื ฐานของการสรา้ งสว่ นแสดงผลใน MEAN Stack มี 2 รูปแบบ ดงั น้ี 1. แสดงผลโดยอาศัยไฟล์ HTML5 โดยตรง สามารถสั่งให้แสดงผลได้โดยตรงจาก Express เป็นเนือ้ หาทผี่ ่านมา 2. แสดงผลโดยอาศัย Template Engine ตา่ งๆ ที่สนบั สนนุ แพลตฟอร์ม MEAN Stack เช่น Pug, EJS เปน็ ต้น ในหัวข้อน้ีเป็นการสร้างส่วนแสดงผลด้วย Pug ถือเป็นรูปแบบพ้ืนฐานส�ำหรับการ แสดงผลใน Web Apps ดว้ ย MEAN Stack ตัวอย่างที่ 3-3 พื้นฐานการสรา้ งส่วนแสดงผลด้วย Pug มขี น้ั ตอนดังน้ี 1. ให้เปิด Command Prompt ข้ึนมา ไป ยังพาธท่ีเก็บโปรเจ็กต์ ในกรณีน้ี คือ พาธ E:\\Projects สร้างไฟล์ package.json ข้ึนมาด้วยคำ�ส่ัง npm init ก่อน ต้ังช่ือ โปรเจ็กต์นว้ี ่า basicpug 2. ต่อมา ให้ติดตั้ง express ให้กับโปรเจ็กต์ รูปที ่ 3-12 แสดงการสรา้ งไฟลท์ ช่ี อื่ วา่ ปัจจบุ นั ด้วยคำ�สงั่ ต่อไปน้ี package.json Command Prompt 1 npm install - -save express รปู ท่ี 3-13 แสดงการดาวน์โหลด และติดตั้ง express ให้ กับโปรเจ็กตป์ ัจจุบัน 50
CHAPTER 3 ท�ำ งานกับส่วนแสดงผลด้วย Pug และ Static Files 3. จากนัน้ พมิ พ์ค�ำ ส่งั ตอ่ ไปน้ี เพือ่ ดาวนโ์ หลดและติดตั้ง Pug เพ่ิมเติมให้กบั โปรเจก็ ต์ ปัจจบุ นั ดงั รูปท่ี 3-14 Command Prompt 1 npm install - -save pug รปู ที่ 3-14 แสดงการดาวนโ์ หลดและตดิ ตง้ั pug ให้ กบั โปรเจก็ ต์ปัจจุบัน จากรูปท่ี 3-14 ตอนนเี้ ราไดช้ ้ินสว่ นที่ตอ้ งใช้งานครบแล้ว 3. ต่อมา ใหล้ องเปดิ ดไู ฟล์ package.json พบวา่ จะมกี ารระบุให้ใช้ express และ pug แล้ว ดังรปู ที่ 3-15 รปู ที ่ 3-15 แสดงการระบุให้ใช้ JADE ของโปรเจ็กต์ ปจั จุบนั 4. โดยปกตแิ ลว้ โฟลเดอรท์ ที่ �ำ หนา้ ทเี่ กบ็ Pug ชอ่ื วา่ views ใหส้ รา้ งโฟลเดอรข์ นึ้ มาใหม่ จากนนั้ สร้างไฟลใ์ หมข่ นึ้ มา 2 ไฟล์ คอื index.pug และ layout.pug ไฟล์ส่วนแสดงผลของ Pug มีนามสกุล .pug ดงั รปู ที่ 3-16 รูปที ่ 3-16 ไฟล์ส่วนแสดงผลท่ีชื่อว่า layout.pug และ index.pug ในโฟลเดอร์ views ScJraivpat 51
จากรูปท่ี 3-16 ผเู้ ขยี นสรา้ งไฟล์ใหมข่ ้ึนมา 2 ไฟล์ คือ ไฟล์ layou.pug และ index. pug ยังเปน็ ไฟลว์ า่ งๆ อยู่ ท�ำหนา้ ทส่ี รา้ งสว่ นแสดงผล เพ่ือให้โครงสร้างโปรเจ็กต์ของเราเป็นระเบียบต้ังแต่เริ่มต้น ผู้เขียนขอแยกส่วนแสดง ผลออกเปน็ 2 ส่วน ดังนี้ ÂÂ ส่วนแสดงผลทีต่ อ้ งปรากฎเสมอ เชน่ โครงสรา้ งของไฟล์ HTML5, โลโก้ของบริษัท, ระบบเมนูหลกั , การอา้ งอิงไฟล์ CSS, ไฟล์ JavaScript ต่างๆ เปน็ ตน้ ใหเ้ กบ็ ไว้ที่ ไฟล์ layout.pug ÂÂ ส่วนแสดงผลของแต่ละหน้า ในกรณีน้ีเราต้องการสร้างส่วนแสดงผลหนา้ แรกเพียง หน้าเดยี ว ตงั้ ชอ่ื วา่ index.pug การใช้งานอิลเี มนตข์ อง HTML5 ใน Pug ไมจ่ �ำเป็นต้องมอี ิลีเมนต์เปดิ ปดิ ยกตัวอย่าง เชน่ ใน HTML5 ตอ้ งระบอุ ิลีเมนตเ์ ปิด-ปดิ ใหค้ รบถ้วน ดังนี้ HTML5 1 <h1>สวสั ดีครับ</h1> แตใ่ น Pug เพยี งระบชุ อื่ อลิ ีเมนต์เพยี งอย่างเดียวเทา่ น้ัน Pug 1 h1 สวัสดีครับ ความพเิ ศษของ Pug อกี ประการหนึ่งทมี่ คี วามสำ� คญั เป็นอย่างมาก นน่ั คือ สามารถ สง่ คา่ เขา้ ไปใน Pug โดยอาศัยตวั แปร ได้อีกดว้ ย น่ีคือชอ่ งทางทีเ่ ราจะสง่ ข้อมลู ตา่ งๆ เขา้ ไป เพอ่ื แสดงผลในบราวเซอร์นนั่ เอง หมายความว่า การสร้างส่วนแสดงผลด้วย Pug แยกสง่ิ ท่เี หน็ ในบราวเซอร์ออกเปน็ 2 สว่ นคือ ÂÂ สว่ นโครงสร้างไฟล์ เปน็ หนา้ ทีข่ อง Pug ÂÂ สว่ นขอ้ มลู เราเป็นผ้สู ง่ ขอ้ มลู เขา้ ไปผา่ นทางตัวแปร 5. ตอ่ มา ให้เพิ่มไฟล์ทช่ี ือ่ วา่ index.js ทำ�หนา้ ทเ่ี ป็นไฟล์ลำ�ดับแรกในโปรเจ็กต์ของเรา ต้องกำ�หนดให้โปรเจก็ ตข์ องเรารู้จกั กบั โฟลเดอร์ views และมกี ารใชง้ าน pug กอ่ น ดังสคริปต์ต่อไปน้ี 52
CHAPTER 3 ท�ำ งานกับส่วนแสดงผลดว้ ย Pug และ Static Files รปู ที ่ 3-17 แสดงสคริปต์ในไฟล์ index.js สคริปต์ Express ท่ี 3-3 พนื้ ฐานการสร้างส่วนแสดงผลด้วย Pug (index.js) 1 var express = require(‘express’); 2 var path = require(‘path’); 3 var app = express(); 4 5 app.set(‘views’, path.join(__dirname, ‘views’)); 6 app.set(‘view engine’, ‘pug’); 7 8 app.get(‘/’, function (req, res) { 9 res.render(‘index’, { title: ‘Express และ Pug’ }); 10 }); 11 12 app.listen(3000, function () { 13 console.log(‘Express running on port 3000’) 14 }); ต่อมา ส่วนไฟล์ Pug ทั้งไฟล์ layout.pug และ index.pug ให้เขียนสครปิ ตด์ ังตอ่ ไปนี้ รปู ท่ ี 3-18 แสดงสคริปตใ์ นไฟล์ layout.pug และ index.pug จากรูปท่ี 3-18 การเขยี นอลี เี มนต์ของ HTML5 ในไฟล์ Pug ใช้การย่อหน้าดงั สคริปต์ ต่อไปนี้ ScJraivpat 53
สคริปต์ Pug ที่ 3-3 พน้ื ฐานการสรา้ งส่วนแสดงผลดว้ ย Pug (\\views\\layout.pug) 1 doctype html 2 html 3 head 4 title= title 5 body 6 block content สครปิ ต์ Pug ท่ี 3-3 พื้นฐานการสร้างสว่ นแสดงผลด้วย Pug (\\views\\index.pug) 1 extends layout 2 3 block content 4 h1= title 5 p สวสั ดีจา้ #{title} ยอ่ หน้าแตล่ ะอิลีเมนต์ท่เี หน็ มีความสำ� คัญเชน่ กัน แนะน�ำใหใ้ ช้ป่มุ Tab บนคียบ์ อร์ด 6. การทำ�งานของตัวอย่างนีม้ เี พยี งอยา่ งเดยี ว นนั่ คือ สรา้ งสว่ นแสดงผลทเ่ี กิดมาจาก ไฟล์ layout.pug ร่วมกับ index.pug ทำ�หนา้ ท่เี ปน็ สว่ นแสดงผลหนา้ แรก ใหล้ อง รนั โปรเจ็กต์ (คำ�สง่ั node index) ผลการทำ�งาน แสดงดงั รปู ท่ี 3-19 รปู ท่ี 3-18 สว่ นแสดงผลทเ่ี กดิ จากไฟล์ layout.pug + index.pug จากรปู ที่ 3-19 ใหค้ ลกิ ขวาในบราวเซอร์ เลอื กดู Page Source พบวา่ โครงสรา้ งของสว่ น แสดงผลทไี่ ดม้ าจากไฟล์ layout.pug ถูกประกอบรวมเข้ากบั index.pug ดังสคริปตต์ ่อไปนี้ layout.pug ร่วมกบั index.pug 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Express และ Pug</title> 5 </head> 6 <body> 7 <h1>สวสั ดีจ้า Express และ Pug</h1> 8 </body> 9 </html> 54
CHAPTER 3 ท�ำ งานกับส่วนแสดงผลด้วย Pug และ Static Files จากสครปิ ตข์ ้างต้น พบวา่ เราไดโ้ ครงสร้าง HTML5 ทีเ่ กดิ มาจาก Pug รว่ มกับการส่ง ข้อมูลเขา้ มาผ่านทางตัวแปร อธิบายการทำ�งานของสคริปต์ 1. การกำ�หนดให้โปรเจ็กต์ปัจจุบันทำ�งานกับโฟลเดอร์ views ให้กำ�หนดค่าผ่านทาง ตวั แปร app มี 2 ขัน้ ตอนย่อย คือ hh กำ�หนดให้ views ท�ำ หน้าทแ่ี ทนพาธปัจจบุ นั (__dirname) ตอ่ ดว้ ยโฟลเดอร์ที่ ชื่อวา่ views hh กำ�หนดใหใ้ ชส้ ่วนแสดงผลของ pug index.js 1 app.set(‘views’, path.join(__dirname, ‘views’)); 2 app.set(‘view engine’, pug); 2. ต่อมา ผูเ้ ขยี นกำ�หนดการทำ�งานง่ายๆ ว่า เมื่อมกี ารร้องขอแบบ get มาทร่ี ูท / ให้ ทำ�สง่ิ นี้ ÂÂ ไปที่หน้าเว็บเพจ index (หมายถึง index.pug) ด้วยเมธอด render() ของ พารามิเตอร์ res ÂÂ สรา้ งตัวแปรท่ชี อื่ วา่ title ทำ�หน้าท่ีเก็บขอ้ ความ Express และ Pug ในกรณีน้ีเมธอด render ของพารามเิ ตอร์ ทำ� หนา้ ทว่ี าดส่วนแสดงผลของไฟล์ Pug index.js 1 app.get(‘/’, function (req, res) { 2 res.render(‘index’, { title: ‘Express และ Pug’ }); 3 }); 3. มาท่ีไฟล์ layout.pug ทำ�หน้าทเ่ี ป็นโครงสรา้ งพนื้ ฐานของไฟล์ HTML5 พบว่าวธิ ีการ เขียนอิลเี มนต์ HTML5 ของ Pug ใหร้ ะบชุ อ่ื อลิ เี มนต์โดยตรงเทา่ นนั้ หน้าท่ีของไฟล์ นี้กค็ อื ก�ำ หนดโครงสร้างพื้นฐานของไฟล์ HTML5 เทา่ นัน้ กล่าวคือ ÂÂ doctype หมายถึง ส่วนหวั ของเอกสาร HTML5 ทำ�หน้าที่บอกประเภทเอกสาร ÂÂ โครงสร้างพ้นื ฐานของไฟล์ HTML5 ประกอบดว้ ยอิลเี มนต์ 4 ตวั คอื อิลีเมนต์ html, head title และอลิ เี มนต์ body ScJraivpat 55
\\views\\layout.pug 1 doctype html 2 html 3 head 4 title= title 5 body 6 block content สว่ นคำ� สัง่ block content หมายถงึ พ้ืนทีส่ �ำหรับน�ำเน้ือหามาตอ่ หรือมาแทรก 4. ท้ายทสี่ ุด ในกรณีนมี้ เี พียง 1 หนา้ จอ คือ ไฟล์ index.pug ซ่ึงถกู สงั่ ให้ทำ�งานมา จากเมธอด render() ให้ทำ� hh ใชส้ ว่ นหวั ของเอกสารท่อี ยู่ในไฟล์ layout (extends layout) กอ่ น hh แทรกเน้ือหาในตำ�แหน่ง content (block content) hh แสดงข้อความ สวัสดีจ้า ร่วมกับค่าท่ีเก็บอยู่ในตัวแปร title (#{title}) ด้วยอิลี เมนต์ p ซงึ่ ทำ�หน้าท่แี สดงขอ้ ความในย่อหนา้ ใหม่ \\views\\index.pug 1 extends layout 2 43 block content 5 h1= title 6 p สวัสดจี า้ #{title} สรุปทา้ ยบท “Pug เป็นช้ินส่วนทีม่ คี วามสำ� คัญมากท่สี ุดอกี ตวั หน่ึง ไมว่ า่ ผอู้ ่านจะพฒั นา Web Apps ใดกต็ ามกต็ อ้ งมีส่วนแสดงผลปรากฎในบราวเซอร์ การใชง้ าน Pug โดยสว่ นใหญแ่ ล้วเป็นการใชง้ านรว่ มกับชนิ้ สว่ นอน่ื ๆ เพือ่ ท�ำ หนา้ ทแี่ สดงผลในรปู แบบตา่ งๆ สง่ ผลใหเ้ นอื้ หาตง้ั แตบ่ ทหนา้ เปน็ ตน้ ไปจะมกี ารใชง้ าน Pug ควบคู่อยูด่ ว้ ยเสมอ และจะมเี นื้อหา Pug อืน่ ๆ เพิ่มเติมข้นึ มาในแตล่ ะหวั ข้อ 56
4Java script CHAPTER ทำ� ความรจู้ กั กบั เสน้ ทาง (Route) เส้นทาง (Route) ถอื เป็นหวั ขอ้ พ้ืนฐานที่ตอ้ งทำ� ความเข้าใจเปน็ ลำ� ดบั ตน้ ๆอีก 1 หวั ขอ้ เม่ือเขา้ มาสู่โลกของการพัฒนา Web Apps ดว้ ย Express เพราะว่าเสน้ ทางพาธ URL ต่างๆ ภายใน เว็บไซต์เราตอ้ งเป็นผูก้ ำ� หนดทง้ั หมด มาดูกันว่ามปี ระเดน็ ใดบ้างที่ต้องศกึ ษา พน้ื ฐานการ Redirect ไปยงั พาธอ่ืน โดยปกติแล้วการรอ้ งขอไฟลแ์ บบ get มาท่พี าธต่างๆ เราเปน็ ผู้ก�ำหนดการท�ำงานเอง ว่าเมื่อเข้ามาท่ีพาธนีใ้ หท้ ำ� อะไร เม่ือไปอีกพาธใหท้ �ำอะไร สามารถส่ังให้มีการ Redirect ไปยัง พาธตามทกี่ �ำหนด เม่อื มีพาธใดพาธหน่ึงยงั ไม่พรอ้ มให้บรกิ าร ตวั อย่างที่ 4-1 พื้นฐานการ Redirect ไปยงั พาธอ่ืน มีขัน้ ตอนดังน้ี 1. ก�ำหนดให้ไปที่พาธ E:\\Projects ก่อน (หรือพาธที่เราต้องการเก็บโปรเจ็กต์) จากนั้นพิมพ์ค�ำส่ัง npm init สร้าง โปรเจก็ ตว์ า่ งทช่ี อ่ื วา่ basicroute ขนึ้ มา ก่อน ดังรูปท่ี 4-1 รปู ท่ ี 4-1 แสดงการสรา้ งโปรเจก็ ตท์ ชี่ อื่ วา่ basicroute ในพาธ E:\\Projects HTML .Net HTML
จากรูปที่ 4-1 ให้กดปุ่ม Enter ที่คีย์บอร์ดจนกว่าจะมีค�ำส่ัง Command Prompt บรรทัดใหม่ ก็จะได้ไฟล์ที่ช่ือว่า package.json เก็บอยู่ในพาธ E:\\Projects 2. ต่อมา ให้ดาวน์โหลดและติดต้ัง Express เพียงตัวเดียว ด้วยคำ�สั่ง npm install - -save express ดงั รปู ท่ี 4-2 รูปที่ 4-2 แสดงการดาวนโ์ หลดและตดิ ตงั้ Express ใหก้ บั โปรเจก็ ตป์ จั จบุ นั 3. ตอ่ มา ใหเ้ ปิดโปรเจก็ ต์ข้ึนมา ดทู ไี่ ฟล์ package.json พบวา่ มีการใช้งาน Express แลว้ ดังรูปที่ 4-3 รูปท ่ี 4-3 แสดงการระบุให้ มีการใช้งาน Express ในโปรเจ็กต์ ปัจจบุ นั 4. ต่อมา ให้เพิ่มไฟล์ท่ีชื่อว่า index.js ทำ�หน้าทเ่ี ปน็ ไฟล์ ลำ�ดับแรก จากนั้นเขียน สคริปตด์ งั ตอ่ ไปนี้ รปู ท่ี 4-4 แสดงสคริปต์ในไฟล์ index.js 58
CHAPTER 4 ท�ำ ความรจู้ กั กบั เส้นทาง (Route) สคริปต์ Express ท่ี 4-1 พนื้ ฐานการ Redirect ไปยังพาธอื่น (index.js) 1 var express = require(‘express’); 2 var app = express(); 3 4 app.get(‘/’, function (req, res) { 5 res.send(‘Hello Express’); 6 }); 7 8 app.get(‘/products’, function (req, res) { 9 res.redirect(301, ‘/info’); 10 }); 11 12 app.get(‘/info’, function (req, res) { 13 res.send(‘Error Info Page’); 14 }); 15 16 app.listen(3000, function () { 17 console.log(‘Express running on port 3000’) 18 }); 5. ท้ายที่สุด ให้ทดสอบรันโปรเจ็กต์โดยการพิมพ์คำ�สั่ง node index จากน้ันเปิด บราวเซอร์ข้นึ มา ใหเ้ ขา้ มาทพ่ี าธ localhost:3000/products พบวา่ มีการ redirect มาที่พาธ /info แทนโดยอัตโนมัติ เพราะผู้เขียนจำ�ลองสถานะการณ์ว่าท่ีพาธ / products อยูใ่ นสภาวะไมพ่ ร้อมใหบ้ รกิ าร ดงั รปู ท่ี 4-5 รปู ท ี่ 4-5 ผลการรัน ตวั อย่างที่ 4-1 อธบิ ายการทำ�งานของสคริปต์ 59 1. เร่มิ ต้นท่พี าธ /products กำ�หนดใหม้ ีการ Redirect (res.redirect()) กำ�หนดรหสั สถานะการทำ�งานเป็นตัวเลข 301 และกำ�หนดใหไ้ ปทีพ่ าธ /info โดยอตั โนมตั ิทนั ที index.js 1 app.get(‘/products’, function (req, res) { 2 res.redirect(301, ‘/info’); 3 }); ScJraivpat
2. ตอ่ มา กำ�หนดการทำ�งานใหก้ บั พาธ /info แสดงขอ้ ความ “Error Info Page” index.js 1 app.get(‘/info’, function (req, res) { 2 res.send(‘Error Info Page’); 3 }); การจัดโครงสร้างเส้นทาง Route สำ� หรับหัวขอ้ น้ีกจ็ ะว่ากันด้วยเร่ืองของการจัดโครงสร้างโปรเจ็กต์ให้เปน็ ระเบียบมากยิง่ ขน้ึ เราสามารถแยกสว่ นของเสน้ ทางออกมาเปน็ ไฟลต์ า่ งหากเกบ็ ไวใ้ นโฟลเดอรท์ ช่ี อ่ื วา่ “routes” ส่งผลให้เม่ือใดก็ตามที่เราต้องการจัดการด้านก�ำหนดเส้นทางและรายละเอียดต่างๆก็ สามารถไปดรู ายการไฟลท์ อ่ี ยู่ในโฟลเดอร์ routes ทั้งหมดแทน หมายความวา่ เราก�ำลังจะแบ่ง หนา้ ท่กี ำ� หนดเสน้ ทางแยกออกมาจากไฟล์ index.js น่ันเอง เราไม่ต้องการเก็บทกุ สง่ิ ทกุ อย่าง ไว้ในไฟล์ index.js เพยี งไฟลเ์ ดยี ว ตวั อยา่ งที่ 4-2 การจดั โครงสร้างเสน้ ทาง Route โดยที่ผเู้ ขยี นจะนำ� ตวั อยา่ งทแี่ ลว้ มาท�ำต่อ มีขน้ั ตอนดงั น้ี 1. การกำ�หนดเส้นทาง Route ต้องทำ�งานเกี่ยวข้องกับส่วนแสดงผลในแต่ละหน้าจอ ด้วย จึงต้องมีการดาวน์โหลดและติดต้ัง pug เพิ่มขึ้นมาอีก 1 รายการ โดยการ พิมพ์คำ�สั่ง npm instal - -save pug ดังรปู ที่ 4-6 รูปที่ 4-6 แสดงการดาวนโ์ หลดและตดิ ตง้ั pug เพม่ิ เตมิ ใหก้ บั โปรเจก็ ตป์ จั จบุ นั ใหล้ องเปิดดูไฟล์ package.json พบว่าโปรเจ็กตป์ จั จบุ นั มีการระบุให้ใช้ pug เพ่ิมข้ึน มาแลว้ ดงั รปู ที่ 4-7 60
CHAPTER 4 ทำ�ความรจู้ กั กบั เส้นทาง (Route) รูปที่ 4-7 แสดงการระบุให้ใช้ pug ในโปรเจก็ ต์ปัจจจบุ นั ดว้ ย 2. ตอ่ มา ใหส้ รา้ งโฟลเดอรข์ น้ึ มาใหม่ ชอ่ื วา่ routes ขน้ึ มากอ่ น ภายในโฟลเดอรย์ อ่ ยน้ี มี 2 ไฟล์ ดงั น้ี hh ไฟล์ index.js ทำ�หน้าที่กำ�หนดเส้นทางสำ�หรับหน้าแรก hh ไฟล์ webboard.js ทำ�หน้าที่กำ�หนดเส้นทางให้กับพาธ / Webboard รูปท ่ี 4-8 โฟลเดอร์ routes มไี ฟล์ index.js กบั webboard.js อยภู่ ายใน 3. ต่อมา ที่ไฟล์ index.js ที่อย่ใู นโฟลเดอร์ routes ซึ่งทำ�หนา้ ทจ่ี ดั การพาธ / ใหเ้ ขียน สครปิ ตด์ ังตอ่ ไปนี้ รูปท่ี 4-9 แสดงสครปิ ตใ์ นไฟล์ \\routes\\index.js สคริปต์ Express ที่ 4-2 การจดั โครงสร้างเส้นทาง Route (\\routes\\index.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 res.render(‘index’, { strHeader: ‘หนา้ แรก Express’ }); 6 }); 7 8 module.exports = router; ScJraivpat 61
4. ตอ่ มา สว่ นไฟล์ webboard.js ทำ�หนา้ ทจ่ี ดั การของพาธ /Webboard ใหเ้ ขยี นสครปิ ต์ ดังตอ่ ไปน้ี รูปที่ 4-10 แสดงสคริปต์ในไฟล์ \\routes\\webboard.js สคริปต์ Express ที่ 4-2 การจัดโครงสร้างเสน้ ทาง Route (\\routes\\webboard.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 res.send(‘หน้า Webboard’); 6 }); 7 8 module.exports = router; 5. ต่อมา เมื่อแยกส่วนของการจัดการพาธออกไปเก็บอยู่ในโฟลเดอร์ routes แล้ว ก็ต้องมีการแก้ไขสคริปต์ในไฟล์หน้าแรก index.js ที่อยู่ด้านนอกใหม่ ดังสคริปต์ ตอ่ ไปนี้ รปู ท ี่ 4-11 แสดงสครปิ ตใ์ นไฟล์ index.js 62
CHAPTER 4 ท�ำ ความรจู้ กั กับเส้นทาง (Route) สคริปต์ Express ท่ี 4-2 การจัดโครงสรา้ งเส้นทาง Route (index.js) 1 var express = require(‘express’); 2 var pug = require(‘pug’); 3 var app = express(); 4 5 var index = require(‘./routes/index’); 6 var webboard = require(‘./routes/webboard’); 7 8 app.set(‘views’, __dirname + ‘/views’); 9 app.set(‘view engine’, ‘pug’); 10 11 app.use(‘/’, index); 12 app.use(‘/Webboard’, webboard); 13 14 app.listen(3000, function () { 15 console.log(‘Express running on port 3000’) 16 }); 6. ต่อมา ในไฟล์หน้าแรก index.js ข้างตน้ มกี ารกำ�หนดให้ใช้สว่ นแสดงผลทเ่ี ก็บอยู่ ในโฟลเดอร์ views ด้วย ให้สร้างโฟลเดอร์ทชี่ ่อื ว่า views ข้ึนมาก่อน ให้ทำ�สิ่งน้ี ÂÂ เพ่มิ ไฟล์ layout.pug ทำ�หนา้ ท่เี ปน็ โครงสร้างของไฟล์ตามมาตรฐาน HTML5 ÂÂ เพม่ิ ไฟล์ index.pug ทำ�หนา้ ทีเ่ ป็นหนา้ แรก สำ�หรับการร้องขอแบบ get มาทีพ่ าธ / รปู ท่ ี 4-12 แสดงรายการไฟลส์ ่วนแสดงผลในโฟลเดอร์ views จากรูปที่ 4-12 ทั้ง 2 ไฟลม์ ีสคริปต์ดังต่อไปนี้ สครปิ ต์ Express ที่ 4-2 การจดั โครงสรา้ งเส้นทาง Route (\\views\\layout.pug) 1 doctype html 2 html 3 head 4 title= strHeader 5 body 6 block content ScJraivpat 63
สคริปต์ Express ท่ี 4-2 การจัดโครงสรา้ งเสน้ ทาง Route (\\views\\index.pug) 1 extends layout 2 3 block content 4 h1= strHeader 5 p Welcome to #{strHeader} 7. ท้ายท่สี ดุ ให้ลองรันโปรเจก็ ต์ (คำ�สั่ง node index) เมอ่ื เข้ามาทีพ่ าธ / กจ็ ะได้ส่วน แสดงผลที่เกิดจากไฟล์ index.pug + layout.pug ตามปกติ รปู ที่ 4-13 สว่ นแสดงผลของพาธ / 8. แต่ถ้ามาทพี่ าธ /webboard ก็จะไดข้ ้อความ “หนา้ Webboard” ผเู้ ขียนกำ�หนด ให้พาธน้สี ่งข้อความโดยตรง ไมไ่ ดใ้ ชส้ ่วนแสดงผลใดๆ ท้ังส้นิ ดังรปู ที่ 4-14 รปู ท ี่ 4-14 สว่ นแสดงผลของพาธ /Webboard อธิบายการท�ำ งานของสคริปต์ 1. เรมิ่ ตน้ ทส่ี ่วนแสดงผลของพาธ / กอ่ น อยู่ในความรบั ผิดชอบของไฟล์ index.js ท่ี อยู่ในโฟลเดอร์ routes ให้ประกาศตัวแปร express (var express) ทำ�หน้าที่แทน Express กอ่ น ท่ีส�ำคญั ก็คอื ให้สร้างตัวแปรทชี่ อื่ วา่ router (var router) ขนึ้ มา ท�ำหนา้ ที่แทนเฉพาะ สว่ นของการกำ� หนดเส้นทาง (express.Router()) \\routes\\index.js 1 var express = require(‘express’); 2 var router = express.Router(); 64
CHAPTER 4 ท�ำ ความรจู้ กั กับเส้นทาง (Route) 2. การทำ�งานภายในของไฟล์ index.js มีเพียงอย่างเดียวก็คือ สั่งให้ส่วนแสดงผลที่ช่ือ วา่ index.pug ทำ�งาน ผา่ นทางพารามิเตอร์ res รว่ มกบั เมธอด render() พรอ้ มกับ ส่งข้อความ “หน้าแรก Express” ให้กับตวั แปรท่ชี ือ่ ว่า strHeader ด้วย \\routes\\index.js 1 router.get(‘/’, function (req, res) { 2 res.render(‘index’, { strHeader: ‘หน้าแรก Express’ }); 3 }); 3. ทา้ ยทีส่ ดุ ตอ้ งกำ�หนด exports ตวั router ซ่ึงเป็นการทำ�งานของไฟล์ index.js นี้ ดว้ ย เพ่อื ให้ภายนอกเรยี กใชง้ านได้ \\routes\\index.js 1 module.exports = router; 4. ตอ่ มา ที่ไฟล์ webboard.js ทอี่ ยใู่ นโฟลเดอร์ routes มีการทำ�งานแตกตา่ งเล็กน้อย ก็คอื เป็นการสง่ั ให้แสดงขอ้ ความ “หนา้ Webboard” เทา่ นั้น ไมไ่ ดใ้ ช้สว่ นแสดง ผลใดๆ ท้ังสิน้ \\routes\\webboard.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 res.send(‘หนา้ Webboard’); 6 }); 7 8 module.exports = router; จากสคริปต์ข้างต้น สรปุ ได้ว่า ÂÂ ไฟล์ index.js ทีอ่ ยูใ่ นโฟลเดอร์ routes พรอ้ มทำ�หน้าที่แทนการร้องขอแบบ get มา ทพี่ าธ / แลว้ ÂÂ ไฟล์ webboard.js ท่ีอยู่ในโฟลเดอร์ routes พร้อมทำ�หน้าที่แทนการร้องขอมาท่ี พาธ /webboard เชน่ กนั 5. ตอ่ มา เม่อื แยกไฟล์ index.js และ webboard.js ออกไปเก็บไวใ้ นโฟลเดอร์ routes แล้ว กต็ ้องแกไ้ ขวิธีการอ้างองิ ในไฟล์หน้าแรก index.js ใหม่ กลา่ วคอื ScJraivpat 65
hh สร้างตัวแปรท่ีช่ือว่า index (var index) ทำ�หน้าที่แทนท้ังพาธ /routes/index (กลา่ วไดอ้ กี นัยหนึ่งว่า /routes/index.js นัน่ เอง) hh สร้างตัวแปรท่ีช่ือว่า webboard (var webboard) ทำ�หน้าที่แทนทั้งพาธ / routes/webboard (กล่าวไดอ้ ีกนัยหนงึ่ ว่า /routes/webboard.js นน่ั เอง) index.js 1 var index = require(‘./routes/index’); 2 var webboard = require(‘./routes/webboard’); 6. ท้ายท่สี ุด ใหผ้ กู พาธเข้ากบั ตวั แปรตามทต่ี อ้ งการ กล่าวคือ ÂÂ พาธ / ให้ใชเ้ สน้ ทางท่ีเก็บอย่ใู นตวั แปร index ÂÂ พาธ /Webboard ใหใ้ ชเ้ ส้นทางที่อยู่ในตัวแปร webboard index.js 1 app.use(‘/’, index); 2 app.use(‘/Webboard’, webboard); ตัวอยา่ งน้แี สดงใหเ้ ห็นวา่ เราเรมิ่ จัดโครงสรา้ งโปรเจก็ ต์ Express ของเราโดยการแยก เกบ็ แตล่ ะไฟล์ตามหนา้ ทอ่ี อกเปน็ สดั สว่ นทช่ี ดั เจนย่งิ ข้นึ การสรา้ ง Library (หรือ Module) ข้ึนมาใชง้ านเอง การพฒั นาWebApps ในโลกของMEANStack เกดิ จากการนำ� ชน้ิ สว่ น(dependencies) ตา่ งๆ ตามทร่ี ะบไุ วใ้ นไฟล์package.json มาใชง้ านรว่ มกนั โดยการดาวนโ์ หลดและตดิ ตงั้ ดว้ ย คำ� สงั่ npm instal รายการ Library หรือ Module ตา่ งๆ ของ JavaScript จะถูกดาวน์โหลดและน�ำมาเก็บไว้ในโฟลเดอร์ท่ีชื่อว่า node_ modules ภายในโปรเจ็กตข์ องเรา ดงั รปู ที่ 4-15 จากรูปที่ 4-15 ในไฟล์ package.json ของโปรเจ็กต์ ปจั จบุ นั มกี ารระบวุ า่ ตอ้ งการใชช้ นิ้ สว่ นเพมิ่ เตมิ ทช่ี อ่ื วา่ express และ pug ตามเวอรช์ ันปัจจุบันเทา่ ท่มี อี ยู่เป็นช้นิ สว่ นส�ำเรจ็ รปู ท่ี เราสามารถเรียกมาใชง้ านไดเ้ ลย รปู ท่ี 4-15 แสดงโฟลเดอร์ท่จี ัดเก็บ Library หรอื Module 66
CHAPTER 4 ทำ�ความร้จู กั กบั เสน้ ทาง (Route) ใหล้ องเปดิ เขา้ ไปดใู นโฟลเดอร์ node_modules กจ็ ะพบกบั โฟลเดอรย์ ่อยตา่ งๆ มากมาย ทถ่ี กู ดาวน์โหลดและติดตัง้ อยู่ในโปรเจ็กตป์ ัจจบุ นั ของเรา เปน็ ไปตามทรี่ ะบุในไฟล์ package. json ดงั รปู ที่ 4-16 รปู ที่ 4-16 แสดงรายการโฟลเดอร์ตา่ งๆ ในโฟลเดอร์ node_modules จากรูปท่ี 4-16 ในแต่ละโฟลเดอรก์ จ็ ะมีรายการไฟล์ JavaScript ตา่ งๆ มากมาย เม่ือ ต้องการใช้งานฟังก์ชันใดกต็ ามกต็ อ้ งมกี ารอา้ งองิ กอ่ นเสมอ เช่น ตอ้ งการใชง้ าน express และ pug ดงั สครปิ ตต์ อ่ ไปน้ี index.js 1 var express = require(‘express’); 2 var pug = require(‘pug’) 3 var app = express(); 4… 5… 6… เราถือว่า Library เหล่านเ้ี ป็น Library สำ� เร็จรูป ท่ีเราไม่ไดเ้ ขียนข้นึ มาเอง หนา้ ท่ขี องเรา เพียงเรียกใชง้ านอย่างเดียวเทา่ นน้ั และไมค่ วรเข้าไปแกไ้ ขสครปิ ตใ์ ดๆ ทงั้ ส้นิ ในกรณที ่เี ราต้องการเขียน Library ขึ้นมาใชง้ านเอง สามารถท�ำได้เชน่ กัน ScJraivpat 67
ตัวอย่างที่ 4-3 การสรา้ ง Library (หรอื Module) ขน้ึ มาใชง้ านเอง Library ท่จี ะสรา้ งข้ึนมา มีหนา้ ท่เี พียงอย่างเดียว คือ เก็บขอ้ มลู สนิ คา้ ตามโครงสรา้ งท่ี เราก�ำหนดไว้ มขี ้นั ตอนดังน้ี 1. สรา้ งโฟลเดอรท์ ชี่ อ่ื วา่ data ขน้ึ มา ภายในโฟลเดอรน์ มี้ ไี ฟลท์ ชี่ อ่ื วา่ data.js ทำ�หนา้ ท่ี เกบ็ ขอ้ มลู สนิ คา้ 2 อยา่ ง คอื รหสั สนิ คา้ (ProductID) และชอ่ื สนิ คา้ (ProductName) ดงั สครปิ ตต์ อ่ ไปนี้ สคริปต์ JavaScript ท่ี 4-3 การสรา้ ง Library (หรอื Module) ขึ้นมาใช้งานเอง (\\data\\data.js) 1 var Products = { 2 ProductID: “111”, 3 ProductName: “การใชง้ าน MEAN Stack” 4} 5 6 module.exports = Products; รูปท ี่ 4-17 แสดงสคริปต์ในไฟล์ data.js 2. ต่อมา สร้างไฟล์ท่ีชื่อว่า products.js ข้ึนมาในโฟลเดอร์ routes รับผิดชอบเกี่ยว กับการแสดงข้อมูลสินค้าทั้งหมด ส่ังให้แสดงข้อมูลสินค้าที่เก็บอยู่ในไฟล์ data.js ดังสคริปตต์ อ่ ไปนี้ สครปิ ต์ Express ท่ี 4-3 การสรา้ ง Library (หรอื Module) ขึ้นมาใช้งานเอง (\\routes\\products.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 var p = require(‘../data/data’); 6 res.send(‘รหัสสินคา้ : ‘ + p.ProductID + ‘<br />ชอื่ สนิ คา้ : ‘ + p.ProductName); 7 }); 8 9 module.exports = router; 68
CHAPTER 4 ทำ�ความรจู้ ักกบั เสน้ ทาง (Route) รปู ที่ 4-18 แสดงการอา้ งองิ ไฟล์ data.js ใน products.js 3. ท่ีไฟล์ index.js กำ�หนดเสน้ ทางพาธ /products เพื่อแสดงขอ้ มูลสนิ คา้ ดังสครปิ ต์ ตอ่ ไปนี้ สครปิ ต์ Express ท่ี 4-3 การสร้าง Library (หรือ Module) ข้นึ มาใช้งานเอง (index.js) 1 var express = require(‘express’); 2 var pug = require(‘pug’) 3 var app = express(); 4 5 var index = require(‘./routes/index’); 6 var products = require(‘./routes/products’); 7 8 app.set(‘views’, __dirname + ‘/views’); 9 app.set(‘view engine’, ‘pug’); 10 11 app.use(‘/’, index); 12 app.use(‘/products’, products); 13 14 app.listen(3000, function () { 15 console.log(‘Express running on port 3000’) 16 }); รปู ที่ 4-19 แสดงการก�ำ หนดเสน้ ทางพาธ /products ScJraivpat 69
4. ท้ายท่ีสุด ให้รันโปรเจ็กต์ (ด้วยคำ�สั่ง node index) ไปท่ีพาธ /products ก็จะได้ ขอ้ มูลสนิ คา้ ตามทีเ่ ราระบุไวใ้ น data.js แลว้ ดังรปู ท่ี 4-20 รูปท ี่ 4-20 ผลการรนั ตวั อยา่ งที่ 4-3 อธิบายการทำ�งานของสคริปต์ 1. การทำ�งานเรมิ่ ตน้ ทไ่ี ฟล์ index.js สรา้ งตวั แปรทชี่ อื่ วา่ products (var products) ทำ� หนา้ ทแี่ ทนไฟล์ products.js ทอ่ี ยใู่ นโฟลเดอร์ routes (var products = require(‘./ routes/products’)) index.js 1 var products = require(‘./routes/products’); 2. ต่อมา กำ�หนดไว้ว่าเมื่อมีการร้องขอมาท่ีพาธ /products กำ�หนดให้ใช้เส้นทางที่ เก็บอยูใ่ นตัวแปร products index.js 1 app.use(‘/products’, products); 3. ต่อมา การทำ�งานภายในไฟล์ products.js มเี พียงอยา่ งเดยี ว คือ แสดงขอ้ มูลสินค้า เกดิ จากการทำ�งานยอ่ ย 2 ขั้นตอน ดังน้ี ÂÂ สรา้ งตวั แปรทช่ี อ่ื วา่ p(varp) ขน้ึ มา ทำ�หนา้ ทแี่ ทนไฟล์data.js ทเ่ี กบ็ อยใู่ นโฟลเดอร์ data (require(‘../data/data’)) ซึง่ เปน็ Library ทเี่ ราเปน็ ผสู้ รา้ งขน้ึ มาเอง \\routes\\products.js 1 router.get(‘/’, function (req, res) { 2 var p = require(‘../data/data’); ÂÂ แสดงข้อมูลสินค้า เมื่อตัวแปร p ทำ�หน้าที่แทน data.js แล้ว ก็จะสั่งให้แสดง ข้อมูลตามโครงสร้างท่ีมีอยู่ น่ันคือ รหัสสินค้า (p.ProductID) และชื่อสินค้า (p.ProductName) \\routes\\products.js 1 res.send(‘รหสั สินค้า : ‘ + p.ProductID + ‘<br />ช่ือสนิ คา้ : ‘ + p.ProductName); 2 }); 70
CHAPTER 4 ท�ำ ความรจู้ กั กับเสน้ ทาง (Route) 4. ทา้ ยท่ีสดุ ในไฟล์ data.js ผู้เขียนกำ�หนดใหท้ ำ�หนา้ ที่เพยี งอยา่ งเดยี ว คอื เก็บขอ้ มลู สินค้า ประกอบด้วย 2 สว่ นคือ ÂÂ รหัสสนิ คา้ (ProductID) เกบ็ รหสั “1111” ÂÂ ชือ่ สนิ คา้ (ProductName) เก็บข้อความ “การใชง้ าน MEAN Stack” \\data\\data.js 1 var Products = { 2 ProductID: “111”, 3 ProductName: “การใช้งาน MEAN Stack” 4} 5 6 module.exports = Products; การสรา้ งฟังกช์ ันใน Library ของเราเอง Library ทเ่ี ราสรา้ งขน้ึ มาอยใู่ นรปู แบบฟงั กช์ นั ไดอ้ กี ดว้ ย ขนึ้ อยกู่ บั วา่ จะกำ� หนดใหฟ้ งั กช์ นั ทีส่ ร้างขึน้ มา ทำ� หน้าทีอ่ ะไร ตัวอยา่ งท่ี 4-4 การสร้างฟังก์ชนั ใน Library ของเราเอง ผ้เู ขยี นนำ� data.js ของตวั อย่างทแี่ ล้วมาปรบั ปรุงใหม่ มีขน้ั ตอนดงั น้ี 1. ตอ้ งการสร้างเคร่อื งคดิ เลขข้ึนมา ทำ�หน้าทีบ่ วกเลข 2 จำ�นวน ผา่ นทางฟงั กช์ นั ทช่ี ่ือ วา่ Add (this.Add) ดังสคริปต์ต่อไปน้ี สครปิ ต์ JavaScript ท่ี 4-4 การสรา้ งฟังก์ชันใน Library ของเราเอง (\\data\\data.js) 1 function Calculator() { 2 this.Add = function (num1, num2) { 3 return num1 + num2; 4} 5} 6 7 module.exports = new Calculator; รปู ท่ี 4-21 แสดงไฟล์ data.js ท่ีมีการแก้ไข หนา้ ทใ่ี หม่ ScJraivpat 71
2. ที่ส่วนเรียกใช้งาน data.js อยู่ท่ีไฟล์ products.js (ในโฟลเดอร์ routes) ผู้เขียน ต้องการบวกเลข 100 กับ 300 โดยอาศยั ฟงั กช์ ัน Add() ดังสครปิ ต์ต่อไปนี้ สครปิ ต์ JavaScript ท่ี 4-4 การสร้างฟงั กช์ ันใน Library ของเราเอง (\\routes\\products.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 var c = require(‘../data/data’); 6 res.send(‘ผลบวก : ‘ + c.Add(100, 300)); 7 }); 8 9 module.exports = router; รปู ที ่ 4-22 แสดงวิธีการเรียกใช้ ฟงั กช์ ันท่อี ยใู่ น data.js จากรูปท่ี 4-22 เป็นการเรียกใชฟ้ งั กช์ นั ทอ่ี ย่ใู นไฟล์ data.js ผา่ นทางไฟล์ products.js 3. ทา้ ยทส่ี ดุ ให้รันโปรเจก็ ตด์ ้วยคำ�สง่ั node index แลว้ ไปท่ีพาธ /products กจ็ ะได้ คำ�ตอบ 400 เกดิ มาจากการทำ�งานของฟงั ก์ชนั Add() ใน data.js บวกเลข 100 + 300 ตามคา่ ท่ีเราส่งเขา้ ไปน่นั เอง รปู ท่ี 4-23 ผลการรนั ตวั อยา่ งท่ี 4-4 พนื้ ฐานการรบั -ส่งพารามิเตอรแ์ บบ Query String การรับ-ส่งข้อมูลระหว่างเว็บเพจถือเป็นการท�ำงานพ้ืนฐานอีกประการหนึ่งที่ต้องศึกษา เปน็ เร่อื งแรกๆ ในขั้นต้นนผี้ ูเ้ ขยี นน�ำเสนอวธิ กี ารรบั -สง่ พารามิเตอร์ที่เรียกวา่ “Query String” Query String หมายถึง การรับ-สง่ ข้อมูลแนบไปกบั พาธ URL สง่ ผลให้ข้อมลู ทแี่ นบไป ด้วย ปรากฎในช่องป้อน URL ของบราวเซอร์ (ผใู้ ชง้ านมองเหน็ ) จงึ เป็นขอ้ ควรระวงั วา่ ไม่ควร ส่งข้อมลู ทเ่ี ปน็ ความลับด้วยวิธนี ี้ 72
CHAPTER 4 ทำ�ความร้จู ักกบั เสน้ ทาง (Route) ตัวอย่างที่ 4-5 พืน้ ฐานการรบั -สง่ พารามเิ ตอร์แบบ Query String เปา้ หมายของตวั อย่างน้เี พือ่ สร้างสว่ นแสดงผลขึ้นมาด้วยไฟล์ HTML5 ประกอบไปดว้ ย ลงิ ก์ต่างๆ และแนบค่าพารามิเตอร์ไปกบั ลิงกด์ ้วย ผู้เขยี นตอ้ งการแสดงวธิ กี ารอ่านค่าพารามเิ ตอรท์ แี่ นบมากบั ลิงก์ มขี นั้ ตอนดังนี้ 1. เร่มิ ต้นพมิ พ์คำ�สงั่ npm init สรา้ งไฟล์ package.json ขึน้ มาก่อน ตั้งชอื่ โปรเจก็ ต์ ว่า usingparameter ผ้เู ขียนเกบ็ ไว้ที่พาธ E:\\Projects เชน่ เดิม 2. ท่ไี ฟล์ package.json ตอ้ งการชน้ิ สว่ น 2 รายการ คือ express กบั pug ดงั คำ�สั่ง ต่อไปน้ี Command Prompt 1 npm install - - save express 2 npm install - - save pug รปู ท่ี 4-24 แสดงการดาวน์โหลดและติดต้ัง ท้งั 2 ชน้ิ ส่วน 3. ต่อมา เมือ่ ดูทไี่ ฟล์ package.json ก็จะมกี ารระบใุ ช้ชน้ิ ส่วน Express และ Pug ดงั รปู ที่ 4-25 รูปที่ 4-25 แสดงรายการdepen- 73 dencies ในไฟล์ package.json ScJraivpat
4. ตอ่ มา เพ่ิมไฟลท์ ่ชี ื่อว่า index.js ทำ�หน้าท่เี ป็นไฟลล์ ำ�ดับแรก สร้างพาธ /products เช่อื มโยงไปทไ่ี ฟล์ products.js ที่เก็บอยใู่ นโฟลเดอร์ \\routes ดังสคริปต์ตอ่ ไปนี้ สคริปต์ Express ท่ี 4-5 พ้นื ฐานการรบั -ส่งพารามิเตอร์แบบ Query String (index.js) 1 var express = require(‘express’); 2 var pug = require(‘pug’) 3 var path = require(‘path’); 4 var app = express(); 5 6 var index = require(‘./routes/index’); 7 var webboard = require(‘./routes/webboard’); 8 var products = require(‘./routes/products’); 9 10 app.set(‘views’, __dirname + ‘/views’); 11 app.set(‘view engine’, ‘pug’); 12 13 app.use(express.static(path.join(__dirname, ‘public’))); 14 15 app.use(‘/’, index); 16 app.use(‘/Webboard’, webboard); 17 app.use(‘/Products’, products); 18 19 app.listen(3000, function () { 20 console.log(‘Express running on port 3000’) 21 }); รปู ท่ ี 4-25 แสดงโครงสร้าง โปรเจก็ ตใ์ นปจั จบุ ัน 74
CHAPTER 4 ท�ำ ความรูจ้ ักกับเสน้ ทาง (Route) จากรูปที่ 4-26 ในไฟล์ index.js ก�ำหนดไว้ 3 เส้นทาง ดังนี้ ÂÂ พาธ / เชื่อมโยงไปยงั ไฟล์ index.js ที่อยใู่ นโฟลเดอร์ routes ÂÂ พาธ /webboard เชอ่ื มโยงไปยังไฟล์ webboard.js ท่ีอยูใ่ นโฟลเดอร์ routes ÂÂ พาธ /products เช่อื มโยงไปยงั ไฟล์ products.js ทีอ่ ยู่ในโฟลเดอร์ routes 5. ตอ่ มา ทไ่ี ฟล์ products.js ในโฟลเดอร์ \\routes ทำ�หนา้ ที่สง่ั ใหไ้ ฟล์ HTML5 ทีช่ อ่ื วา่ productslist.html เกบ็ อยู่ในโฟลเดอร์ \\public ทำ�งาน และตรวจสอบรายการ พารามิเตอร์อกี หน้าที่หน่งึ ด้วย ดงั สครปิ ตต์ อ่ ไปน้ี สครปิ ต์ Express ที่ 4-5 พน้ื ฐานการรับ-ส่งพารามิเตอรแ์ บบ Query String (\\routes\\products.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 var brand = req.query.brand; 6 var model = req.query.model; 7 8 if (brand == undefined || model == undefined) { 9 res.redirect(‘productslist.html’); 10 } else { 11 var str = ‘ยห่ี อ้ : ‘ + brand + ‘<br />สนิ ค้าเด่น : ‘ + model; 12 res.send(str); 13 } 14 }); 15 16 module.exports = router; รูปท่ ี 4-27 แสดงสคริปต์ในไฟล์ products.js ScJraivpat 75
6. ต่อมา ท่ไี ฟล์ productslist.html ทอ่ี ยู่ในโฟลเดอร์ \\public ให้เขยี นสคริปต์ HTML5 ดงั ต่อไปนี้ รูปท ่ี 4-28 แสดงสครปิ ต์ HTML5 ในไฟล์ productslits.html สครปิ ต์ HTML5 ท่ี 4-5 พ้นื ฐานการรบั -ส่งพารามิเตอร์แบบ Query String (\\public\\productslist.html) 1 <!DOCTYPE html> 2 <html lang=”en”> 3 <head> 4 <title></title> 5 <meta charset=”UTF-8”> 6 <meta name=”viewport” content=”width=device-width, initial-scale=1”> 7 </head> 8 <body> 9 <h1>รายการสนิ คา้ </h1> 10 <ula> 11 <li><a href=”products?brand=microsoft&model=surface”>Surface</a></li> 12 <li><a href=”products?brand=google&model=android”>Android</a></li> 13 <li><a href=”products?brand=apple&model=ios”>iOS</a></li> 14 </ul> 15 </body> 16 </html> 7. ท้ายท่ีสุด ให้รันโปรเจ็กต์ด้วยคำ�ส่ัง node index แล้วไปท่ีพาธ /products ก็จะพบกับรายการลิงก์ ทเี่ กดิ จากไฟล์ productslist.html ดังรปู ท่ี 4-29 รปู ที่ 4-29 ผลการรันตวั อยา่ งท่ี 4-5 76
CHAPTER 4 ท�ำ ความรู้จกั กบั เสน้ ทาง (Route) จากรูปท่ี 4-29 เม่ือไปทพี่ าธ /products ส่งผลให้ ไฟล์ productslist.html ถูกส่ังใหท้ ำ� งานตามท่ีเรากำ� หนด ไว้ในไฟล์ products.js ใหล้ องเอาเมาสไ์ ปลอยอยเู่ หนอื ลงิ กไ์ หนกไ็ ด้ มสี งิ่ ที่ น่าสนใจ 3 ประการ คอื รูปท ี่ 4-30 กรณนี �ำ เมาสไ์ ป ÂÂ พาธ เป็นการร้องขอข้อมูลแบบ get ไปทพี่ าธ /products ลอยอยูเ่ หนือรายการ iOS ÂÂ พารามิเตอรต์ ัวที่ 1 ชอ่ื ว่า brand ในกรณนี ีล้ งิ ก์ iOS ถูกกำ�หนดคา่ เป็น apple ÂÂ พารามเิ ตอรต์ วั ที่ 2 ชอ่ื วา่ model ในกรณนี ีล้ ิงก์ iOS ถกู กำ�หนดคา่ เป็น ios 8. ตอ่ มา ผู้เขียนลองเอาเมาส์ไปลอยอยเู่ หนอื ลงิ ก์ Surface ผลทีไ่ ด้ ดังน้ี hh พาธ เปน็ การร้องขอขอ้ มูลไปท่พี าธ /products hh พารามิเตอรต์ ัวท่ี 1 ชอื่ ว่า brand ในกรณนี ี้ ลิงก์ Surface ถูกกำ�หนดค่าเปน็ microsoft hh พารามิเตอร์ตัวท่ี 2 ชื่อว่า model ในกรณี น้ีลิงก์ Surface ถกู กำ�หนดคา่ เป็น surface รูปท่ี 4-31 กรณลี งิ ก์ของ Surface ไม่ว่าจะเป็นลิงก์ไหนก็ตามเราต้องการอ่านค่าออกมาจากพารามิเตอร์ brand และ model 9. ทา้ ยทสี่ ดุ ใหค้ ลกิ ทล่ี งิ ก์ไหนกไ็ ด้ ผลทไี่ ดจ้ ะเปน็ การอา่ นคา่ พารามเิ ตอร์ brand และ model ออกมาจากลงิ กท์ ค่ี ลกิ ในกรณนี ผี้ เู้ ขยี นคลกิ ลงิ ก์ iOS กจ็ ะไดค้ า่ พารามเิ ตอร์ ทัง้ 2 ตวั ตามที่แสดงอยู่ในช่อง URL ของบราวเซอร์ ดงั รูปที่ 4-32 รูปที่ 4-32 แสดงค่าของพารามิเตอรท์ ัง้ 2 ตวั ScJraivpat 77
จากรปู ที่ 4-32 พาธทท่ี ำ� หนา้ ทแี่ สดงค่าของพารามิเตอรท์ ง้ั 2 ตัว คือ พาธ /products ตามที่ได้จาก URL ในลงิ ก์น่นั เอง อธบิ ายการทำ�งานของสคริปต์ 1. เรม่ิ ตน้ ในไฟล์ index.js สรา้ งตวั แปรทช่ี อ่ื วา่ products (var products) ทำ�หนา้ ทแ่ี ทน ไฟล์ products.js ทเ่ี กบ็ อยใู่ นโฟลเดอร์ \\routes (require(‘./routes/products’)) กอ่ น จากนน้ั กำ� หนดวา่ เมอ่ื ใดกต็ ามทม่ี กี ารรอ้ งขอมาทพี่ าธ/Products กำ� หนดใหใ้ ชพ้ าธทเ่ี กบ็ อย่ใู นตัวแปร products กล่าวไดอ้ ีกนัยหนึ่งวา่ เป็นการส่งั ให้ไฟล์ products.js ทอ่ี ยใู่ นโฟลเดอร์ \\routes ทำ� งานนัน่ เอง index.js 1 var products = require(‘./routes/products’); 2… 3… … app.use(‘/Products’, products); 2. ตอ่ มา รายการลงิ กท์ ีแ่ สดงอยใู่ นไฟล์ productslist.html เม่อื ผใู้ ชง้ านคลกิ ท่ีลิงก์ใด ก็ตาม สง่ ผลใหเ้ กดิ การทำ�งานเหมอื นกนั 3 ประการ คือ ÂÂ เป็นการร้องขอข้อมลู ไปทพ่ี าธ /products ÂÂ กำ�หนดคา่ ใหก้ บั พารามิเตอรท์ ชี่ อ่ื ว่า brand ÂÂ กำ�หนดค่าให้กับพารามิเตอร์ที่ชื่อว่า model (พารามิเตอร์แต่ละตัวค่ันด้วย เคร่ืองหมาย ?) \\public\\productslist.html 1 <body> 2 <h1>รายการสนิ ค้า</h1> 3 <ul> 4 <li><a href=”products?brand=microsoft&model=surface”>Surface</a></li> 5 <li><a href=”products?brand=google&model=android”>Android</a></li> 6 <li><a href=”products?brand=apple&model=ios”>iOS</a></li> 7 </ul> 8 </body> 78
CHAPTER 4 ท�ำ ความร้จู กั กบั เส้นทาง (Route) 3. กลับมาที่ไฟล์ index.js เราต้องเขียนสคริปต์รองรับการร้องขอข้อมูลมาท่ีพาธ / products ด้วย ซ่ึงเกิดมาจากการคลิกท่ีลิงก์นั่นเอง การทำ�งานภายในพาธ / products นีม้ ีเพยี งอย่างเดียว คือ แสดงค่าของพารามเิ ตอร์ brand และ model ใหท้ ำ� ÂÂ สร้างตัวแปรท่ีช่ือว่า brand (var brand) อ่านค่าออกมาจากพารามิเตอร์ที่ช่ือว่า brand (req.query.brand) ÂÂ สร้างตัวแปรที่ช่ือว่า model (var model) อ่านค่าออกมาจากพารามิเตอร์ท่ีชื่อว่า brand (req.query.model) index.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res) { 5 var brand = req.query.brand; 6 var model = req.query.model; 4. ตอ่ มา ตอ้ งตรวจสอบกอ่ นเลยวา่ ถา้ ตวั แปรbrand หรอื model ไมม่ คี า่ (undefined) ตคี วามไดว้ า่ เกดิ การสง่ คา่ ไมค่ รบถว้ นตามทเี่ ราตอ้ งการ กจ็ ะสง่ั ใหไ้ ฟล์productslist. html ทำ�งานทันที เพื่อใหผ้ ใู้ ช้งานคลกิ เลอื กลงิ กส์ ่งคา่ ท่ีถูกตอ้ งและครบถว้ น index.js 1 if (brand == undefined || model == undefined) { 2 res.redirect(‘productslist.html’); 5. ทา้ ยที่สดุ ถา้ ตัวแปร brand และ model เก็บคา่ ทีถ่ ูกตอ้ ง กจ็ ะส่ังใหแ้ สดงค่าของ ตัวแปรทง้ั 2 ตัวในบราวเซอร์ index.js 1 } else { 2 var str = ‘ยี่หอ้ : ‘ + brand + ‘<br />สนิ คา้ เดน่ : ‘ + model; 3 res.send(str); 4} 5 }); 6 7 module.exports = router; ScJraivpat 79
รายละเอียดโปรเจก็ ต์ท่ีได้จาก express-generator เนื้อหาต้ังแต่บทท่ี 2 จนถงึ หวั ขอ้ ท่ีแลว้ เป็นการเรยี กใชง้ านช้นิ ส่วนพ้ืนฐานตา่ งๆ เพอ่ื แสดงให้เห็นหน้าที่ของแต่ละช้ินส่วนอย่างชัดเจน และยังรวมไปถึงการจัดโครงสร้างโปรเจ็กต์ ให้เปน็ สดั ส่วน เพอ่ื ใหง้ า่ ยต่อการพัฒนา Web Apps ด้วย MEAN Stack เห็นได้ว่าการเพิ่มทีละชิ้นส่วนรวมไปถึงจัดโครงสร้างโปรเจ็กต์เองทั้งหมด มีหลาย ขนั้ ตอนพอสมควร ใชเ้ วลาเริม่ ต้นโปรเจก็ ตใ์ หม่ค่อนขา้ งมาก เราจะกลับมาใช้ express-generator อีกครงั้ ตามเน้อื หาในบทที่ 1 เพื่อท�ำหนา้ ที่เร่มิ ตน้ สรา้ งโปรเจ็กต์ Express ใหก้ บั เรา แต่การใช้งานครั้งนีเ้ ราเรม่ิ รู้จักชนิ้ ส่วนพ้ืนฐานกนั มาบา้ งแลว้ กจ็ ะท�ำให้เข้าใจสิง่ ทไี่ ดม้ าจาก express-generator ชดั เจนย่ิงข้ึน จะมาดวู า่ express-generator เตรยี มโครงสรา้ งโปรเจก็ ตอ์ ะไรไวใ้ ห้บ้าง ตามข้ันตอน ดังตอ่ ไปนี้ 1. เริม่ ต้น ตอ้ งการสรา้ งโปรเจ็กต์ที่ช่อื ว่า HeloExpress เกบ็ ไว้ที่พาธ E:\\Projects (หรือ พาธตามทตี่ อ้ งการ) เชน่ เดิม โดยการปอ้ นคำ�สัง่ Command Line ดงั ตอ่ ไปนี้ Command Prompt 1 C:\\Users\\Thaivb>E: 2 E:\\>cd Projects 3 E:\\Projects>express HelloExpress - -view=pug คำ� สงั่ - - pug หมายถึง ใหโ้ ปรเจ็กต์ปัจจุบัน ใช้ส่วนแสดงผลโดยอาศัย Pug Engine รูปท่ี 4-33 แสดงการสร้างโปรเจ็กตท์ ่ีช่อื ว่า HelloExpress 80
CHAPTER 4 ท�ำ ความรจู้ ักกบั เสน้ ทาง (Route) จากรูปที่ 4-33 พบวา่ เม่ือ express-generator สรา้ งโปรเจก็ ต์ทช่ี ่อื ว่า HeloExpress ข้ึนมาในโฟลเดอร์ E:\\Projects เป็นโครงสรา้ งโปรเจ็กต์ทม่ี คี วามสมบรู ณใ์ นระดับหนึง่ และรัน โปรเจก็ ต์ไมไ่ ด้ มคี ำ� แนะนำ� ลำ� ดับแรกจาก express-generator บอกเลยว่า ÂÂ คำ�ส่ัง cd HelloExpress หมายถึง ให้ย้ายเข้าไปในโฟลเดอร์ของโปรเจ็กต์น้ี คือ โปรเจ็กต์ HeloExpress ÂÂ คำ�สงั่ npminstal หมายถงึ ใหด้ าวนโ์ หลดและตดิ ตง้ั ชน้ิ สว่ นตา่ งๆ(Dependencies) ตามรายการท่ีระบอุ ยใู่ นไฟล์ package.json Command Prompt 1 cd HelloExpress && npm install ผู้เขียนไม่ท�ำตามค�ำแนะน�ำข้างต้น แต่จะเข้าไปดูรายการไฟล์ที่ได้มาจาก express- generator ในพาธ E:\\Projects\\HelloExpress ก่อน เป็นรายการไฟล์ท่ีถูกจัดโครงสร้างมา เรยี บร้อยแลว้ รูปที ่ 4-34 แสดงรายการไฟลข์ องโปรเจ็กต์ HelloExpress จากรูปที่ 4-34 พบว่าโปรเจ็กต์ HeloExpress ไม่มีโฟลเดอรท์ ่ีชอ่ื ว่า node_modules เพราะว่าเรายังไม่ได้ส่ังให้ดาวน์โหลดช้ินส่วนต่างๆ นั่นเอง เป็นเพียงแค่ขั้นตอนการสร้าง โปรเจก็ ต์กึง่ ส�ำเรจ็ รปู ดว้ ย express-generator ข้ึนมาใหมเ่ ท่าน้นั ยงั รันโปรเจ็กต์นี้ไม่ได้ ScJraivpat 81
2. ต่อมา ผู้เขียนยังคงไม่ทำ�ตามคำ�แนะนำ�ข้ันต้นของ express-generator แต่เปิด โปรเจ็กต์ HeloExpress ขึ้นมาก่อนเลย สนใจไฟล์ package.json เป็นลำ�ดับแรก ดังรปู ที่ 4-35 รูปท ่ี 4-35 แสดงรายการ dependencies ในไฟล์ package.json จากรปู ที่ 4-35 พบว่า express-generator มกี ารก�ำหนดใหโ้ ปรเจ็กตป์ ัจจบุ ัน ใช้ชน้ิ ส่วน ทม่ี คี วามจำ� เปน็ ในขนั้ ตน้ มาใหเ้ รยี บรอ้ ยแลว้ เราไมต่ อ้ งปอ้ นคำ� สงั่ ดาวนโ์ หลดและตดิ ตง้ั ทลี ะชน้ิ ส่วนอกี ต่อไป ให้ทำ� ตามค�ำแนะน�ำในตอนตน้ เลย 3. ตอ่ มา ใหพ้ มิ พ์คำ�สั่ง cd HeloExpress ยา้ ยเข้ามาในโฟลเดอร์โปรเจ็กตป์ ัจจบุ ันกอ่ น จากน้ันพิมพ์คำ�ส่ัง npm instal เพ่ือดาวน์โหลดและติดต้ังทุกรายการเท่าที่ระบุอยู่ ในไฟล์ package.json Command Prompt 1 E:\\Projects>cd HelloExpress 2 E:\\Projects\\HelloExpress>npm install รปู ท ่ี 4-36 แสดงการดาวนโ์ หลดและติดตงั้ dependencies หลายรายการในเวลาเดยี วกัน 82
CHAPTER 4 ทำ�ความร้จู กั กบั เสน้ ทาง (Route) 4. ต่อมา จะพบว่ามีโฟลเดอร์ เพ่มิ เข้ามาใหม่ ช่อื ว่า node_ modules ภายในโฟลเดอร์น้ี ทำ�หน้าท่ีเก็บรายการไฟล์ Library ต่างๆ ท่ีเราเรียกใช้ ในโปรเจ็กต์น้ีน่ันเอง ห้าม เข้าไปแก้ไขรายการไฟล์ใน โฟลเดอร์น้เี ด็ดขาด ถือว่าโปร เจ็กต์ HelloExpress พร้อมรัน โปรเจก็ ตแ์ ลว้ รปู ท่ ี 4-37 แสดงรายการไฟลต์ ่างๆ ที่ถูกดาวน์โหลดเพ่ิมเตมิ เขา้ มา 5. โปรเจ็กต์ที่ได้จาก express-generator กำ�หนดให้ไฟล์ที่ชื่อ ว่า app.js ทำ�งาน เปน็ ลำ�ดับแรก (แตก ตา่ งจากของเดมิ คอื ไฟล์ index.js) รูปที่ 4-38 แสดงไฟล์ app.js ทำ�หน้าทเี่ ปน็ ไฟลล์ �ำ ดบั แรกของโปรเจ็กต์ 6. ตอ่ มา ทไี่ ฟล์app.js กจ็ ะปรบั มาใชส้ ว่ นแสดงผลของPug(varpug=require(‘pug’) และ app.set(‘view engine’, ‘pug’)) แล้ว และมกี ารกำ�หนดโครงสรา้ งโปรเจ็กต์ เตรยี มพรอ้ มไว้ใหแ้ ลว้ ดงั สครปิ ต์ต่อไปนี้ app.js 1 var express = require(‘express’); 2 var path = require(‘path’); 3 var pug = require(‘pug’); 4 var favicon = require(‘serve-favicon’); 5 var logger = require(‘morgan’); ScJraivpat 83
app.js (ต่อ) 8 var cookieParser = require(‘cookie-parser’); 9 var bodyParser = require(‘body-parser’); 10 var routes = require(‘./routes/index’); 11 var users = require(‘./routes/users’); 12 13 var app = express(); 14 15 app.set(‘views’, path.join(__dirname, ‘views’)); 16 app.set(‘view engine’, ‘pug’); 17 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 app.use(‘/users’, users); 26 27 app.use(function (req, res, next) { 28 var err = new Error(‘Not Found’); 29 err.status = 404; 30 next(err); 31 }); 32 33 if (app.get(‘env’) === ‘development’) { 34 app.use(function (err, req, res, next) { 35 res.status(err.status || 500); 36 res.render(‘error’, { 37 message: err.message, 38 error: err 39 }); 40 }); 41 } 42 43 app.use(function (err, req, res, next) { 44 res.status(err.status || 500); 45 res.render(‘error’, { 46 message: err.message, 47 error: {} 48 }); 49 }); 50 51 module.exports = app; 84
CHAPTER 4 ท�ำ ความรจู้ ักกับเสน้ ทาง (Route) 7. ตอ่ มา ไฟล์ส่วนแสดงผลของ Pug เกบ็ อยูใ่ นโฟลเดอร์ views มีนามสกุล .pug แบง่ แยกหน้าทีต่ ามท่เี ราคุ้นเคยกันเปน็ อยา่ งดี ดงั รูปท่ี 4-39 รูปที่ 4-39 ไฟล์สว่ นแสดงผลของ Pug ในโฟลเดอร์ views 8. โครงสร้างโปรเจ็กตท์ ไี่ ดม้ าถกู กำ�หนดให้แบง่ เส้นทาง Route ตัง้ แตเ่ ริ่มต้นโปรเจก็ ต์ กล่าวคอื hh ตวั แปร routes ทำ�หนา้ ที่แทนไฟล์ index.js ทีเ่ ก็บอยใู่ นโฟลเดอร์ routes เมอ่ื มี การร้องขอมาที่พาธ / hh ตัวแปร users ทำ�หน้าท่ีแทนไฟล์ users.js ท่ีเก็บอยู่ในโฟลเดอร์ routes เมื่อมี การร้องขอมาทพ่ี าธ /users app.js 1 var urosuetress==rereqquuiriere((‘.‘/.r/orouutetess/u/insedresx’)’);; 2 var 3… 4… …app.use(‘/’, routes); 5 6 7 app.use(‘/users’, users); 9. ต่อมา หน้าท่ขี องไฟล์ index.js (ทอี่ ยใู่ นโฟลเดอร์ routes) กค็ อื สั่งให้สว่ นแสดงผล ที่ชื่อว่า index.pug ร่วมกบั ไฟล์ layout.pug ซ่งึ เกบ็ อย่ใู นโฟลเดอร์ \\views แสดง ผลผา่ นทางเมธอด render() กจ็ ะมกี ารสง่ ขอ้ ความ “Express” ให้กับตัวแปรท่ีชื่อว่า title แนบเข้าไปด้วย ScJraivpat 85
\\routes\\index.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 rourteesr..greent(d‘/e’,r(fu‘inndcetiox’n, {(rteitqle,:re‘Esx,pnreexsts)’{}); 4 5 6 }); 7 8 module.exports = router; 10. สว่ นหน้าท่ีของไฟล์ users.js กค็ อื สงั่ ให้แสดงข้อความ “respond with a resource” \\routes\\users.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 rourteesr..gseetn(‘d/’(,‘rfeusnpcotinodn w(reithq,arerse,sonuerxct)e’{); 4 5 6 }); 7 8 module.exports = router; 11. ต่อมา สว่ นแสดงผลทีป่ รากฎในบราวเซอร์ ประกอบด้วย 2 สว่ น ดงั นี้ ÂÂ ไฟล์layout.pug ทำ�หนา้ ทเ่ี กบ็ โครงสรา้ งไฟลต์ ามมาตรฐานHTML5 เหน็ ไดว้ า่ มกี าร กำ�หนดใหใ้ ช้CSS ทเ่ี กบ็ อยใู่ นไฟล์style.css(ในโฟลเดอร์\\public\\stylesheets) ดว้ ย \\views\\layout.pug 1 doctype html 2 html head 3 title= title 4 bolindky(rel=’stylesheet’, href=’/stylesheets/style.css’) 5 6 7 block content ÂÂ ไฟล์index.pug ทำ�หนา้ ทแ่ี สดงเนอ้ื หาตามทไ่ี ดอ้ อกแบบใหก้ บั เวบ็ เพจหนา้ แรกของเวบ็ เรา 1 extends layout 2 3 block content 4 h1= title 5 p Welcome to #{title} 86
CHAPTER 4 ทำ�ความรู้จกั กบั เส้นทาง (Route) 12. ต่อมา ในกรณีที่ต้องการตกแต่งส่วนแสดงผลด้วย CSS ให้มาทำ�ในไฟล์ style.css ดังรปู ท่ี 4-40 รูปที่ 4-40 แสดงไฟล์ style.css \\public\\stylesheets\\style.css 1 body { fpoandt:d1in4gp:x5“0Lpuxc;ida Grande”, Helvetica, Arial, sans-serif; 2 3 4} 5 a{ color: #00B7FF; 6 7 8} การทดสอบโปรเจก็ ต์ท่ีได้จาก express-generator สามารถทดสอบรนั โปรเจ็กตด์ ้วยค�ำสงั่ npm start จากนนั้ ไปท่พี าธ / ก็จะไดห้ น้าแรก (เกิดจากไฟล์ layout.pug + index.pug) ที่เราคุ้นเคยกันเป็นอย่างดี ดังรปู ที่ 4-41 Command Prompt 1 npm start รปู ท ี่ 4-41 สว่ นแสดงผลของพาธ / ให้ลองไปที่พาธ /users ก็จะได้ข้อความตาม ท่ีก�ำหนดไว้ในไฟล์ users.js เพราะว่าไม่มีการส่ังให้ แสดงผลด้วยไฟล์ Pug ใดๆ ท้ังส้นิ มแี ต่ค�ำสั่งใหแ้ สดง ขอ้ ความธรรมดา ดงั รูปที่ 4-42 รปู ท่ ี 4-42 กรณีมาทพี่ าธ /users ScJraivpat 87
สรุปทา้ ยบท เราเรมิ่ รจู้ กั และนำ� ชน้ิ สว่ นพน้ื ฐานตา่ งๆ นำ� มาประกอบรวมกนั เปน็ WebApps แบบงา่ ยๆ ไดแ้ ลว้ ถอื เปน็ พน้ื ฐานทมี่ คี วามสำ� คญั เปน็ อยา่ งมาก เพราะสามารถจะนำ� ไปตอ่ ยอดในระดบั ตอ่ ไป 88
5Java script CHAPTER ทำ� งานกบั แบบฟอรม์ เน้ือหาของบทน้ีเป็นบทแรกที่เราจะสร้างโปรเจ็กต์ด้วย express-generator ก่อน เพ่ือให้ได้ โครงสรา้ งโปรเจก็ ตท์ ี่พร้อมใช้งานในระดบั หนงึ่ แลว้ น�ำ โปรเจ็กต์มาพัฒนาต่อเปน็ Web Apps ของเรา โดยท่ผี ู้เขียนจะเรม่ิ ตน้ ท่กี ารทำ�งานกบั แบบฟอรม์ (Form) โดยปกตแิ ล้วแบบฟอรม์ เปน็ หน้าเวบ็ เพจท่ีเราค้นุ เคยกันเป็นอยา่ งดี เชน่ หนา้ จอสมัคร สมาชิก, การตัง้ กระทู,้ การสั่งซอื้ สินคา้ เป็นต้น ลว้ นจัดอยู่ในประเภทแบบฟอร์มทัง้ สน้ิ กล่าวได้อีกนัยหน่ึงว่า แบบฟอร์ม ก็คือ หน้าจอท่ีเรากำ�หนดให้ผู้ใช้งานป้อนข้อมูลเข้า มาในหน้าเว็บเพจ จากน้นั เราจะน�ำ ข้อมลู ดังกล่าวไปใชง้ านในข้นั ตอนต่อไป พ้นื ฐานการทำ�งานกบั ฟอรม์ และการอ่านค่าโดยอาศัย body-parser การสร้างหน้าจอในข้ันต้นนี้ผู้เขียนต้องการแสดงให้เห็นวิธีการสร้างแบบฟอร์มข้ึนมา ในส่วนแสดงผล ทำ�หน้าที่รับข้อมูล 2 ช่อง และแสดงวิธีการตรวจสอบว่าผู้ใช้งานป้อนข้อมูล อะไรเข้ามา การตรวจสอบค่าท่ีผู้ใช้งานป้อนเข้ามาในแบบฟอร์ม เป็นหน้าท่ีของชิ้นส่วน (depen- dencies) ทชี่ ือ่ วา่ body-parser มีขนั้ ตอนดงั น้ี 1. เริ่มตน้ สร้างโปรเจ็กตท์ ่ชี ื่อวา่ usingform ดว้ ยคำ�ส่งั express usingform - -pug เก็บโปรเจ็กต์ไว้ที่พาธ E:\\Projects (หรือพาธตามที่ต้องการ) โดยการป้อนคำ�สั่ง ต่อไปนใ้ี น Command Prompt HTML .Net HTML
Command Prompt 1 C:\\Users\\thaivb>E: 2 E:\\>cd Projects 3 E:\\Projects>express usingform - -view=pug รูปที่ 5-1 แสดงการสรา้ งโปรเจก็ ต์ที่ชื่อวา่ usingform ด้วยค�ำ ส่ัง express usingform 2. ต่อมา หลังจากที่ไดโ้ ปรเจ็กต์ท่ีชื่อว่า usingform แล้ว ให้เขา้ ไปในโฟลเดอรข์ องโปร เจ็กตด์ ว้ ยค�ำ ส่งั cd usingform ดงั รปู ที่ 5-2 รปู ท่ี 5-2 แสดงการเขา้ มาทโ่ี ฟลเดอรข์ องโปรเจก็ ต์ usingform จากนั้นป้อนคำ�สั่ง npm install เพ่ือดาวน์โหลดชิ้นส่วนต่างๆ ตามท่ีถูกระบุในไฟล์ package.json ให้ครบทุกชิ้นส่วน ดงั รปู ท่ี 5-3 Command Prompt 1 E:\\Projects\\usingform>npm install รูปท่ี 5-3 แสดงการดาวนโ์ หลดและตดิ ตงั้ ชน้ิ สว่ นตา่ งๆ ตามทรี่ ะบใุ นไฟล์ package.json 90
CHAPTER 5 ท�ำ งานกับแบบฟอร์ม 3. ต่อมา ผู้เขียนเปิดโปรเจ็กต์ usingform ดทู ไี่ ฟล์package. json ถือว่าได้โปรเจ็กต์พร้อม พัฒนาต่อแลว้ ดังรปู ที่ 5-4 รูปท ี่ 5-4 แสดงโปรเจก็ ต์ usingform พร้อมใช้งาน ข้ันตอนการสร้างแบบฟอรม์ ในระดบั พน้ื ฐาน การท�ำ งานกับแบบฟอรม์ ล�ำ ดับแรกกค็ อื เราจะสรา้ งชอ่ งรบั ข้อมูลขน้ึ มา 2 ชอ่ ง เพ่ือให้ ผูใ้ ชง้ านปอ้ นขอ้ มลู เข้ามา การท�ำ งานมเี พยี งอยา่ งเดยี วนัน่ คอื ตรวจสอบว่า ผใู้ ช้งานปอ้ นข้อมลู อะไรเขา้ มา ตัวอย่างที่ 5-1 การสร้างแบบฟอร์มในระดบั พน้ื ฐาน มีขัน้ ตอนดังน้ี 1. ทีโ่ ฟลเดอร์ routes ให้เพิ่มไฟล์ Javascript ใหม่ ตั้งชือ่ วา่ forms.js ทำ�หน้าท่ีสรา้ ง แบบฟอร์ม กำ�หนดใหม้ ีช่องรบั ข้อความ 2 ชอ่ ง ดงั สครปิ ตต์ อ่ ไปน้ี สครปิ ต์ Javascript ท่ี 5-1 การสรา้ งแบบฟอรม์ ในระดับพ้นื ฐาน (\\routes\\forms.js) 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res, next) { 5 var frm = ‘<form action=”/” method=”post”>’ + 6 ‘FirstName : ‘ + 7 ‘<input type=”text” name=”txtFirstName” placeholder=”Please enter firstname” />’ + 8 ‘<br />’ + 9 ‘LastName : ‘ + 10 ‘<input type=”text” name=”txtLastName” placeholder=”Please enter lastname” />’ + 11 ‘<br />’ + 12 13 ‘<button type=”submit”>Submit</button>’ + ScJraivpat 91
สคริปต์ Javascript ที่ 5-1 การสรา้ งแบบฟอรม์ ในระดบั พ้ืนฐาน (\\routes\\forms.js) 14 ‘</form>’; 15 res.send(frm); 16 }); 17 18 module.exports = router; รปู ท่ี 5-5 แสดงการสร้างแบบ ฟอร์มเก็บไว้ในไฟล์ forms.js 2. ต่อมา ทไ่ี ฟล์ app.js เปน็ ไฟลท์ ี่ทำ�งานเปน็ ลำ�ดับแรก ให้เขยี นสคริปตด์ ังตอ่ ไปน้ี สคริปต์ Javascript ที่ 5-1 ข้นั ตอนการสร้างแบบฟอร์มในระดบั พืน้ ฐาน (\\app.js) 1 var express = require(‘express’); 2 var pug = require(‘pug’); 3 var path = require(‘path’); 4 var favicon = require(‘serve-favicon’); 5 var logger = require(‘morgan’); 6 var cookieParser = require(‘cookie-parser’); 7 var bodyParser = require(‘body-parser’); 8 9 var routes = require(‘./routes/index’); 10 var users = require(‘./routes/users’); 11 var forms = require(‘./routes/forms’) 12 13 var app = express(); 14 15 app.set(‘views’, path.join(__dirname, ‘views’)); 16 app.set(‘view engine’, ‘pug’); 17 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 92
CHAPTER 5 ทำ�งานกบั แบบฟอรม์ สครปิ ต์ Javascript ท่ี 5-1 ขนั้ ตอนการสรา้ งแบบฟอรม์ ในระดับพ้ืนฐาน (\\app.js) 24 app.use(‘/’, routes); 25 app.use(‘/users’, users); 26 app.use(‘/forms’, forms); 27 28 app.post(‘/’, function (req, res) { 29 var firstname = req.body.txtFirstName; 30 var lastname = req.body.txtLastName; 31 32 var fullname = ‘<a href=”/”>Home</a>’ + 33 ‘<br />’ + 34 ‘Hello : ‘ + firstname + ‘ ‘ + lastname; 35 36 res.send(fullname); 37 }); 38 39 module.exports = app; 3. ทา้ ยทส่ี ดุ ใหร้ นั โปรเจก็ ตด์ ว้ ยค�ำ สง่ั npm start (ในโฟลเดอร์โปรเจ็กต์ปัจจุบัน usingform) แล้วเปิดบราวเซอร์ขึ้นมา สามารถเข้ามาที่แบบฟอร์มได้ท่ีพาธ / forms ดงั รปู ที่ 5-6 รปู ที่ 5-6 ผลการรนั ตวั อยา่ งที่ 5-1 จากรูปที่ 5-6 ผู้เขียนทดสอบป้อนชื่อ-สกุล แล้วคลิกที่ปุ่ม Submit พบว่าเราสามารถ อา่ นค่าทผ่ี ้ใู ช้งานปอ้ นขอ้ มูลเขา้ มาได้แลว้ อธบิ ายการท�ำ งานของสครปิ ต์ 1. สร้างตัวแปรท่ีชื่อว่า bodyParser (var bodyParser) ข้ึนมา เป็นตัวแทน body- parser (require(‘body-parser’)) ทำ�หนา้ ท่อี ่านค่าจากแบบฟอรม์ ScJraivpat 93
app.js 1 var bodyParser = require(‘body-parser’); 2. ตอ่ มา สรา้ งตวั แปรทช่ี อ่ื วา่ forms ท�ำ หนา้ ทแ่ี ทนไฟล์ forms.js ทเ่ี กบ็ อยใู่ นโฟลเดอร์ /routes app.js 1 var routes = require(‘./routes/index’); 2 var users = require(‘./routes/users’); 3 var forms = require(‘./routes/forms’) 3. ต่อมา ก�ำ หนดใหต้ ัวแปร app มกี ารใชง้ าน bodyParser app.js 1 app.use(bodyParser.json()); 2 app.use(bodyParser.urlencoded({ extended: false })); 4. ต่อมา กำ�หนดว่าเมื่อมีการร้องขอมาท่ีพาธ /forms กำ�หนดให้ใช้พาธที่เก็บอยู่ใน ตัวแปร forms app.js 1 app.use(‘/’, routes); 2 app.use(‘/users’, users); 3 app.use(‘/forms’, forms); 5. ต่อมา ทีไ่ ฟล์ forms.js (ตัวแปรทีช่ ่ือวา่ forms เก็บอย่)ู หน้าท่คี อื เมอื่ ผู้ใช้งานเข้ามา ทพ่ี าธ /forms ถือว่าเปน็ การรอ้ งขอไฟล์แบบ get กจ็ ะสร้างแบบฟอรม์ ว่างๆข้ึนมา ในกรณนี ้ผี ู้เขยี นสร้างตวั แปรท่ีชื่อวา่ frm ข้นึ มาท�ำ หน้าท่ีเกบ็ แบบฟอรม์ ความสำ�คัญก็คือ เมื่อผู้ใช้งาน submit แบบฟอร์มแล้ว กำ�หนดให้ไปท่ีพาธ / (form action=”/”) ดว้ ยเมธอด post (method=”post”) \\routes\\forms.js 1 var express = require(‘express’); 2 var router = express.Router(); 3 4 router.get(‘/’, function (req, res, next) { 5 var frm = ‘<form action=”/” method=”post”>’ + 94
Search
Read the Text Version
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 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
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296