owned this note
owned this note
Published
Linked with GitHub
# Web學習筆記(Javascirpt 一)
# Javascript
## 數字尋找 Binary Search + Selection Sort
``` JavaScript
<script>
debugger
var lines = []
function solve(lines){
let [n, m] = lines[0].split(' ')
let arr = []
let k = 0
for (i=0; i<n; i++) {
arr[i] = Number(lines[i+1])
}
n = Number(n)
// Selection Sort
for (i=0; i<arr.length; i++) {
for(j=i+1; j<arr.length; j++) {
if (Number(arr[i]) > Number(arr[j])) {
k = Number(arr[i])
arr[i] = arr[j]
arr[j] = k
}
}
}
console.log(arr)
for(let i=n+1; i<lines.length; i++) {
let q = Number(lines[i])
console.log(search(arr, q))
}
}
function search(arr, q){
let num = -1, low = 0, high = arr.length - 1, midNum = 0
while(low <= high) {
midNum = Math.floor((low + high) / 2)
if(arr[midNum] === q) {
num = midNum
break
}
if(arr[midNum] > q) {
high = midNum - 1
}else {
low = midNum + 1
}
}
if(num === -1) {
return "找不到資料!"
}else {
return num
}
}
solve(['10 3','1', '4', '3', '5', '2', '6', '8', '7', '9', '10', '5', '11', '100', '10'])
//console.log(solve('5','A','B','B','A','B'))
</script>
```
## DOM
### toggle
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Color Toggle</title>
<style type="text/css">
.purple {
background: purple;
}
</style>
</head>
<body>
<button>CLICK ME</button>
<script type="text/javascript" src="toggle.js"></script>
</body>
</html>
```
```javascript
//document.querySelector("")搜索第一個元素
var button = document.querySelector("button");
var isPurple = false
//監聽物件,第一個是監聽事件的類型第二個是希望事件發生時執行的指令
/*button.addEventListener("click", function(){
if(isPurple){
document.body.style.background = "white"
}else {
document.body.style.background = "purple"
}
})*/
button.addEventListener("click", function(){
//document.body.classList.toggle切換類
//檢查當元素上沒有這個CSS類時就新增這個CSS類
//如果已有就把她刪除
document.body.classList.toggle("purple");
});
```

## 圖片預覽練習
### 結構
**imgExercise.html**
```HTML
<!DOCTYPE html>
<html>
<head>
<title>imgExercise</title>
</head>
<body>
<form runat="server">
<input onchange="showimg()" accept="image/*" type='file' id="imgInp">
<img id="blah" src="#" alt="your image" style= "display:none">
<button onclick="closeimg" id="imgclose">close</button>
</form>
</body>
<script type="text/javascript" src="imgExercise.js"></script>
</html>
```
**imgExercise.js**
```javascript
let showimg = document.getElementById("imgInp")
let img = document.getElementById("blah")
let button = document.getElementById("imgclose")
imgclose.addEventListener("click", function() {
document.getElementById('imgInp').style.display='none'
})
showimg.addEventListener("change" , function() {
const [file] = showimg.files
if (file) {
blah.src = URL.createObjectURL(file)
img.style.display='inline-block'
}
})
```
### 成品

## ScoreKeeper
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Score Keeper</title>
<link rel="stylesheet" type="text/css" href="scorekeeper.css">
</head>
<body>
<h1><span id="p1Display">0</span> to <span id="p2Display">0</span></h1>
<p>Playing to: <span>5</span></p>
<input type="number">
<button id="p1">Player One</button>
<button id="p2">Player Two</button>
<button id="reset">Reset</button>
<script type="text/javascript" src="scorekeeper.js"></script>
</body>
</html>
```
```javascript
var p1Button = document.querySelector("#p1");
var p2Button = document.getElementById("p2");
var resetButton = document.getElementById("reset");
var p1Display = document.querySelector("#p1Display");
var p2Display = document.querySelector("#p2Display");
var numInput = document.querySelector("input");
var winningScoreDisplay = document.querySelector("p span");
var p1Score = 0;
var p2Score = 0;
var gameOver = false;
var winningScore = 5;
p1Button.addEventListener("click", function(){
if(!gameOver){
p1Score++;
if(p1Score === winningScore){
p1Display.classList.add("winner");
gameOver = true;
}
p1Display.textContent = p1Score;
}
});
p2Button.addEventListener("click", function(){
if(!gameOver){
p2Score++;
if(p2Score === winningScore){
p2Display.classList.add("winner");
gameOver = true;
}
p2Display.textContent = p2Score;
}
});
resetButton.addEventListener("click", function(){
reset();
});
function reset(){
p1Score = 0;
p2Score = 0;
p1Display.textContent = 0;
p2Display.textContent = 0;
//重製CSS狀態
p1Display.classList.remove("winner");
p2Display.classList.remove("winner");
gameOver = false;
}
//change屬性:當內容變更才會有反應
numInput.addEventListener("change", function(){
//使用this只接受這個事件的輸入
winningScoreDisplay.textContent = this.value;
winningScore = Number(this.value);
reset();
});
```
```CSS
.winner {
color:green;
}
```
### 成品

## Todo
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Todo List Demo</title>
<link rel="stylesheet" type="text/css" href="todos.css">
</head>
<body>
<ul>
<li>Wash Cat</li>
<li>Feed Cat</li>
<li>Feed Cat to Dog</li>
</ul>
<script type="text/javascript" src="todos.js"></script>
</body>
</html>
```
```javascript
var lis = document.querySelectorAll("li");
for(var i = 0; i < lis.length; i++){
//mouseover當鼠標指向目標
lis[i].addEventListener("mouseover", function(){
//加入selected CSS類型
this.classList.add("selected");
});
//mouseout當鼠標離開目標
lis[i].addEventListener("mouseout", function(){
//重製selected CSS類
this.classList.remove("selected");
});
lis[i].addEventListener("click", function(){
this.classList.toggle("done");
});
}
```
```CSS
.done {
text-decoration: line-through;
opacity: 0.5;
}
.selected {
color: green;
}
```
### 成品

## colorGame
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Color Game</title>
<link rel="stylesheet" type="text/css" href="colorGame.css">
</head>
<body>
<h1>
The Great
<br>
<span id="colorDisplay">RGB</span>
<br>
Color Game
</h1>
<div id="stripe">
<button id="reset">New Colors</button>
<span id="message"></span>
<button class="mode">Easy</button>
<button class="mode selected">Hard</button>
</div>
<div id="container">
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
<div class="square"></div>
</div>
<script type="text/javascript" src="colorGame.js"></script>
</body>
</html>
```
```CSS
body {
background-color: #232323;
margin: 0;
font-family: "Montserrat", "Avenir";
}
.square {
width: 30%;
background: purple;
padding-bottom: 30%;
float: left;
margin: 1.66%;
border-radius: 15%;
transition: background 0.6s;
-webkit-transition: background 0.6s;
-moz-transition: background 0.6s;
}
#container {
margin: 20px auto;
max-width: 600px;
}
h1 {
text-align: center;
line-height: 1.1;
font-weight: normal;
color: white;
background: steelblue;
margin: 0;
text-transform: uppercase;
padding: 20px 0;
}
#colorDisplay {
font-size: 200%;
}
#message {
display: inline-block;
width: 20%;
}
#stripe {
background: white;
height: 30px;
text-align: center;
color: black;
}
.selected {
color: white;
background: steelblue;
}
button {
border: none;
background: none;
text-transform: uppercase;
height: 100%;
font-weight: 700;
color: steelblue;
letter-spacing: 1px;
font-size: inherit;
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
outline: none;
}
button:hover {
color: white;
background: steelblue;
}
```
```javascript
var numSquares = 6;
var colors = [];
var pickedColor;
var squares = document.querySelectorAll(".square");
var colorDisplay = document.getElementById("colorDisplay");
var messageDisplay = document.querySelector("#message");
var h1 = document.querySelector("h1");
var resetButton = document.querySelector("#reset");
var modeButtons = document.querySelectorAll(".mode");
init();
function init(){
setupModeButtons();
setupSquares();
reset();
}
function setupModeButtons(){
for(var i = 0; i < modeButtons.length; i++){
modeButtons[i].addEventListener("click", function(){
modeButtons[0].classList.remove("selected");
modeButtons[1].classList.remove("selected");
this.classList.add("selected");
this.textContent === "Easy" ? numSquares = 3: numSquares = 6;
reset();
});
}
}
function setupSquares(){
for(var i = 0; i < squares.length; i++){
//add click listeners to squares
squares[i].addEventListener("click", function(){
//讓clickedColor變成現在所選的方塊顏色
var clickedColor = this.style.background;
//compare color to pickedColor
//如果選的顏色跟答案相同
if(clickedColor === pickedColor){
messageDisplay.textContent = "Correct!";
resetButton.textContent = "Play Again?"
changeColors(clickedColor);
h1.style.background = clickedColor;
} else {
//錯誤的話就將該方塊變成背景色
this.style.background = "#232323";
messageDisplay.textContent = "Try Again"
}
});
}
}
function reset(){
colors = generateRandomColors(numSquares);
//pick a new random color from array
pickedColor = pickColor();
//change colorDisplay to match picked Color
colorDisplay.textContent = pickedColor;
resetButton.textContent = "New Colors"
messageDisplay.textContent = "";
//change colors of squares
for(var i = 0; i < squares.length; i++){
if(colors[i]){
squares[i].style.display = "block"
squares[i].style.background = colors[i];
} else {
squares[i].style.display = "none";
}
}
h1.style.background = "steelblue";
}
resetButton.addEventListener("click", function(){
reset();
})
//讓所有方塊顏色變成選中的顏色
function changeColors(color){
//loop through all squares
for(var i = 0; i < squares.length; i++){
//change each color to match given color
squares[i].style.background = color;
}
}
function pickColor(){
var random = Math.floor(Math.random() * colors.length);
return colors[random];
}
//隨機產生顏色
function generateRandomColors(num){
//make an array
var arr = []
//repeat num times
for(var i = 0; i < num; i++){
//get random color and push into arr
arr.push(randomColor())
}
//return that array
return arr;
}
//隨機顏色
function randomColor(){
//pick a "red" from 0 - 255
var r = Math.floor(Math.random() * 256);
//pick a "green" from 0 -255
var g = Math.floor(Math.random() * 256);
//pick a "blue" from 0 -255
var b = Math.floor(Math.random() * 256);
return "rgb(" + r + ", " + g + ", " + b + ")";
}
```
### 成品


# JQuery
## To-Do List
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Todo List</title>
<link rel="stylesheet" type="text/css" href="todoslist.css">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,700,500' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.css">
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="container">
<h1>To-Do List</h1>
<input type="text" placeholder="Add New Todo">
<ul>
<li><span>X</span> Go To Potions Class</li>
<li><span>X</span> Buy New Robes</li>
<li><span>X</span> Visit Hagrid</li>
</ul>
</div>
<script type="text/javascript" src="todoslist.js"></script>
</body>
</html>
```
```CSS
#container {
width: 360px;
margin: 0 auto;
border: 2px solid;
}
.completed {
color: gray;
text-decoration: line-through;
}
```
```javascript
//on適用於當前以及未來的元素
//監聽ul裡面的li
//如果只使用click之後新增的元素就不會被監聽
$("ul").on("click","li", function(){
$(this).toggleClass("completed");
});
$("ul").on("click", "span", function(event){
//.parent()父元素
//指向span標籤的父元素做出淡出效果
$(this).parent().fadeOut(500,function(){ //延遲500毫秒後再做動作
//對現在指向的物件做刪除
$(this).remove();
});
//event.stopPropagation阻止click事件冒泡到父元素
//也就是說當我典籍span的內容時他不會觸發除了span標籤以外的事件
event.stopPropagation();
})
//將input的輸入型態都轉成text
//keypress只針對能夠輸出文字符號的按鍵有效如ESC這種是無效的
//keydown的話就是只要是鍵盤案下的瞬間無論任何按鍵都能取得對應的鍵盤代碼
//keyup功能與keydown相同只是觸發時間是在放開鍵盤的瞬間所以不會連續觸發
$("input[type='text']").keypress(function(event){
//event.which回傳該事件下哪個按鍵被按下
if(event.which === 13){
//取得輸入的資料
var todotext = $(this).val();
$(this).val("");
//.append()被選中的元素結尾插入指定內容
$("ul").append("<li><span>X</span>" + todotext + "</li>");
}
})
```
### 成品

## To-Do List改良
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Todo List</title>
<link rel="stylesheet" type="text/css" href="todoslist.css">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,700,500' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.css">
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="container">
<h1>To-Do List <i class="fa fa-plus"></i></h1>
<input type="text" placeholder="Add New Todo">
<ul>
<li><span><i class="fa fa-trash"></i></span> Go To Potions Class</li>
<li><span><i class="fa fa-trash"></i></span> Buy New Robes</li>
<li><span><i class="fa fa-trash"></i></span> Visit Hagrid</li>
</ul>
</div>
<script type="text/javascript" src="todoslist.js"></script>
</body>
</html>
```
```CSS
h1 {
background: #2980b9;
color: white;
margin: 0;
padding: 10px 20px;
text-transform: uppercase;
font-size: 24px;
font-weight: normal;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
.fa-plus {
float: right;
}
body {
font-family: Roboto;
background: -webkit-linear-gradient(90deg, #2BC0E4 10%, #EAECC6 90%); /* Chrome 10+, Saf5.1+ */
background: -moz-linear-gradient(90deg, #2BC0E4 10%, #EAECC6 90%); /* FF3.6+ */
background: -ms-linear-gradient(90deg, #2BC0E4 10%, #EAECC6 90%); /* IE10 */
background: -o-linear-gradient(90deg, #2BC0E4 10%, #EAECC6 90%); /* Opera 11.10+ */
background: linear-gradient(90deg, #2BC0E4 10%, #EAECC6 90%); /* W3C */
}
li {
background: #fff;
height: 40px;
/*設定行高*/
line-height: 40px;
color: #666;
}
/*nth-child(2n)選擇li這個表格的第2個換顏色*/
li:nth-child(2n){
background: #f7f7f7;
}
span {
background: #e74c3c;
height: 40px;
margin-right: 20px;
text-align: center;
color: white;
width: 0;
/*display: inline-block填滿空間*/
display: inline-block;
/*做0.2秒的線性轉場*/
transition: 0.2s linear;
/*元素透明度*/
opacity: 0;
}
/*:hover屬性就是當滑鼠移至某元件時某元件該如何反應*/
li:hover span {
width: 40px;
opacity: 1.0;
}
input {
font-size: 18px;
color: #2980b9;
background-color: #f7f7f7;
width: 100%;
padding: 13px 13px 13px 20px;
/*自動調整填充padding*/
box-sizing: border-box;
border: 3px solid rgba(0,0,0,0);
}
input:focus{
background: #fff;
border: 3px solid #2980b9;
}
#container {
width: 360px;
margin: 100px auto;
background: #f7f7f7;
box-shadow: 0 0 3px rgba(0,0,0,0.1);
}
.completed {
color: gray;
text-decoration: line-through;
}
```
```javascript
//on適用於當前以及未來的元素
//監聽ul裡面的li
//如果只使用click之後新增的元素就不會被監聽
$("ul").on("click","li", function(){
//切換css類別
$(this).toggleClass("completed");
});
$("ul").on("click", "span", function(event){
//.parent()父元素
//指向span標籤的父元素做出淡出效果
$(this).parent().fadeOut(500,function(){ //延遲500毫秒後再做動作
//對現在指向的物件做刪除
$(this).remove();
});
//event.stopPropagation阻止click事件冒泡到父元素
//也就是說當我典籍span的內容時他不會觸發除了span標籤以外的事件
event.stopPropagation();
})
//將input的輸入型態都轉成text
//keypress只針對能夠輸出文字符號的按鍵有效如ESC這種是無效的
//keydown的話就是只要是鍵盤案下的瞬間無論任何按鍵都能取得對應的鍵盤代碼
//keyup功能與keydown相同只是觸發時間是在放開鍵盤的瞬間所以不會連續觸發
$("input[type='text']").keypress(function(event){
//event.which回傳該事件下哪個按鍵被按下
if(event.which === 13){
//取得輸入的資料
var todotext = $(this).val();
$(this).val("");
//.append()被選中的元素結尾插入指定內容
$("ul").append("<li><span><i class='fa fa-trash'></i></span>" + todotext + "</li>");
}
})
$(".fa-plus").click(function(){
//fadeToggle淡出動畫切換
$("input[type='text']").fadeToggle();
});
```
### 成品

# Paperjs
## Exercise
### 結構
```HTML
<!DOCTYPE html>
<html>
<head>
<title>Circles</title>
<script type="text/javascript" src="paper-full.js"></script>
<link rel="stylesheet" type="text/css" href="circles.css">
<script type="text/paperscript" canvas="myCanvas">
for(var x = 0; x < 1000; x+=100){
for(var y = 0; y < 1000; y+=100){
//new Point(x,0),10)設定point的x座標以及y座標還有圓半徑
new Path.Circle(new Point(x,y),10).fillColor = "purple";
}
}
</script>
</head>
<body>
<canvas id="myCanvas" resize></canvas>
</body>
</html>
```
```CSS
canvas {
width: 100%;
height: 100%;
background: black;
}
body, html {
height: 100%;
margin: 0;
}
```
* JS內容就是使用Paper.js內的物件 *
### 成品

## circle
### 結構
```html
<!DOCTYPE html>
<html>
<head>
<title>Circles</title>
<script type="text/javascript" src="paper-full.js"></script>
<link rel="stylesheet" type="text/css" href="circles.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/howler/1.1.28/howler.js"></script>
<script type="text/paperscript" canvas="myCanvas">
//建立keyData物件
var keyData = {
q: {
//new一個Howl的物件
sound: new Howl({
urls: ['sounds/bubbles.mp3']
}),
color: '#1abc9c'
},
w: {
sound: new Howl({
urls: ['sounds/clay.mp3']
}),
color: '#2ecc71'
},
e: {
sound: new Howl({
urls: ['sounds/confetti.mp3']
}),
color: '#3498db'
},
r: {
sound: new Howl({
urls: ['sounds/corona.mp3']
}),
color: '#9b59b6'
},
t: {
sound: new Howl({
urls: ['sounds/dotted-spiral.mp3']
}),
color: '#34495e'
},
y: {
sound: new Howl({
urls: ['sounds/flash-1.mp3']
}),
color: '#16a085'
},
u: {
sound: new Howl({
urls: ['sounds/flash-2.mp3']
}),
color: '#27ae60'
},
i: {
sound: new Howl({
urls: ['sounds/flash-3.mp3']
}),
color: '#2980b9'
},
o: {
sound: new Howl({
urls: ['sounds/glimmer.mp3']
}),
color: '#8e44ad'
},
p: {
sound: new Howl({
urls: ['sounds/moon.mp3']
}),
color: '#2c3e50'
},
a: {
sound: new Howl({
urls: ['sounds/pinwheel.mp3']
}),
color: '#f1c40f'
},
s: {
sound: new Howl({
urls: ['sounds/piston-1.mp3']
}),
color: '#e67e22'
},
d: {
sound: new Howl({
urls: ['sounds/piston-2.mp3']
}),
color: '#e74c3c'
},
f: {
sound: new Howl({
urls: ['sounds/prism-1.mp3']
}),
color: '#95a5a6'
},
g: {
sound: new Howl({
urls: ['sounds/prism-2.mp3']
}),
color: '#f39c12'
},
h: {
sound: new Howl({
urls: ['sounds/prism-3.mp3']
}),
color: '#d35400'
},
j: {
sound: new Howl({
urls: ['sounds/splits.mp3']
}),
color: '#1abc9c'
},
k: {
sound: new Howl({
urls: ['sounds/squiggle.mp3']
}),
color: '#2ecc71'
},
l: {
sound: new Howl({
urls: ['sounds/strike.mp3']
}),
color: '#3498db'
},
z: {
sound: new Howl({
urls: ['sounds/suspension.mp3']
}),
color: '#9b59b6'
},
x: {
sound: new Howl({
urls: ['sounds/timer.mp3']
}),
color: '#34495e'
},
c: {
sound: new Howl({
urls: ['sounds/ufo.mp3']
}),
color: '#16a085'
},
v: {
sound: new Howl({
urls: ['sounds/veil.mp3']
}),
color: '#27ae60'
},
b: {
sound: new Howl({
urls: ['sounds/wipe.mp3']
}),
color: '#2980b9'
},
n: {
sound: new Howl({
urls: ['sounds/zig-zag.mp3']
}),
color: '#8e44ad'
},
m: {
sound: new Howl({
urls: ['sounds/moon.mp3']
}),
color: '#2c3e50'
}
}
var circles = []
//onKeyDown當鍵盤按下就執行...
//這是內建在paper.js下的方程式
function onKeyDown(event){
//建立視窗最邊緣的點
var maxPoint = new Point(view.size.width, view.size.height);
//建立一個隨機座標
var randomPoint = Point.random();
//將最大座標與隨機座標相乘得到在範圍內隨機座標
var point = maxPoint * randomPoint;
//設定newCircle為隨機座標半徑為10的圓
var newCircle = new Path.Circle(point,500)
//對keyData物件裡面的按鍵顏色做改變
newCircle.fillColor = keyData[event.key].color
//播放keyData物件裡的音樂
keyData[event.key].sound.play();
//將newCircle加進circles陣列裡面
circles.push(newCircle);
}
//在座標300,300的地方顯示一個半徑100的圓型顏色為紅色
var animatedCircle = new Path.Circle(new Point(300,300), 100);
animatedCircle.fillColor = "red";
//onFrame每偵執行
function onFrame(event){
for(var i = 0; i < circles.length; i++){
//更改顏色
circles[i].fillColor.hue += 1;
//設定圓的縮小速度為.9
circles[i].scale(.9)
}
}
</script>
</head>
<body>
<canvas id="myCanvas" resize></canvas>
</body>
</html>
```
```css
canvas {
width: 100%;
height: 100%;
background: black;
}
body, html {
height: 100%;
margin: 0;
}
```
* js文黨的部分是引用paper.js裡面下載的paper-full.js *
### 成品
* GIF無聲音內容實際有聲 *

# Node.Js
## Express
* 使用前要先安裝Express模組 *
### 結構
```javascript
//這是在Node.js裡的物件
//使用require功能取得express物件
var express = require("express");
var app = express();
//使用get請求 req == require, res == response
app.get("/", function(req, res){
res.send("Hi there");
});
//process.env.PORT讀取當前目錄下的PORT
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server gas started!!")
});
//res.send伺服器端將資料返回到用戶端
app.get("/dog", function(req, res){
console.log("SOMEONE MADE A REQUEST TO /DOGE!!!")
res.send("MEOW");
});
app.get("/bye", function(req, res){
res.send("Goodbye!!");
});
//加入":"讓她變成一個變量這樣就不是固定位置
app.get("/r/:subredditName/comments/:id/:title/", function(req, res){
res.send("WELCOME TO THE COMMENT PAGE!");
});
app.get("/r/:subredditName", function(req, res){
//req.params將命名過的參數以字串的形式存放
var subreddit = req.params.subredditName
//.toUpperCase將字變成大寫
res.send("WELCOME TO THE !" + subreddit.toUpperCase() + " SUBREDDIT");
});
```
### 成品

## Express作業
### 結構
```javascript
var express = require("express");
var app = express();
app.get("/", function(req, res){
res.send("Hi there, welcome to my assignmenti!");
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server gas started!!")
});
app.get("/spseak/:animal", function(req, res){
//建立sounds物件
var sounds = {
pig: "Oink",
cow: "Moo",
dog: "Woof Woof!",
cat: "I haave you human",
goldfish: "..."
};
//toLowerCase轉換成小寫
var animal = req.params.animal.toLowerCase();
var sound = sounds[animal];
res.send("The " + animal + " says " + sound);
});
app.get("/repeat/:message/:times", function(req, res){
var message = req.params.message;
//將他數字化
var times = Number(req.params.times);
var result = "";
for(let i = 0; i < times; i++){
result += message + " ";
}
res.send(result);
});
//"*"將不存在的路徑導向這裡
app.get("*", function(req, res){
res.send("Sorry ,page not found...What are you doing wuth your life?")
});
```
### 成品

# EJS
* EJS 的全名是「Embedded Javascript」,顧名思義就是內嵌式的樣板引擎,可以將邏輯與內容直接嵌入到 HTML 頁面上,也就是 EJS 可以讓我們利用 JavaScript 生成 HTML 頁面 。而 EJS 學習上相對簡單,因為它沒有如何組織内容的教條;也没有再造一套迭代和控制流語法。我們只要本身會 HTML 和 JavaScript 即可上手! *
- 在使用EJS以及EXPRESS之前都要先安裝相關的檔案
- npm install express --save
- npm install ejs --save
## EJS範例
### 結構
```javascript
var express = require("express");
var app = express();
app.get("/", function(req, res){
res.render("home.ejs");
})
app.get("/fallinlovewith/:thing", function(req, res){
var thing = req.params.thing;
//將views裡面的love.ejs的thing存放這裡的thing的資料
res.render("love.ejs", {thing: thing});
})
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server is listening!!!");
});
```
```ejs
<h1>This is the Home page!!</h1>
```
```ejs
<!--<%= %>被它包含地被視為javascript-->
<!--接收app.js的資料-->
<h1>You fell in love with: <%=thing.toUpperCase()%></h1>
<p>P.S. this is the love.ejs</p>
```
### 成品

## Post
## 結構
```javascript
var express = require("express");
var app = express();
app.get("/", function(req, res){
res.render("home.ejs");
})
app.get("/fallinlovewith/:thing", function(req, res){
var thing = req.params.thing;
//將views裡面的love.ejs的thing存放這裡的thing的資料
res.render("love.ejs", {thing: thing});
})
app.get("/post", function(req, res){
var posts = [
{title: "Post 1", author: "Susy"},
{title: "My adorable pet bunny", author: "Charlie"},
{title: "Can you believe this pomsky?", author: "Colt"},
]
res.render("posts.ejs", {posts: posts});
})
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server is listening!!!");
});
```
```EJS
<!--<%= %>被它包含地被視為javascript-->
<!--接收app.js的資料-->
<h1>You fell in love with: <%=thing.toUpperCase()%></h1>
<!--<%= %>是將裡面的js內容直接傳回到html
但是如果只是要做邏輯指令就不要加等於改成<% %>-->
<%if(thing.toLowerCase() === "rusty"){ %>
<p>GOOD CHICE! RUSTY IS THE BEST!</p>
<% } else { %>
<p>Bad choice! You should have said Rusty!</p>
<% } %>
<p>P.S. this is the love.ejs</p>
```
```EJS
<h1>The Posts Page</h1>
<% for(var i = 0; i < posts.length; i++){%>
<li><%= posts[i].title %> - <strong><%= posts[i].author %></strong></li>
<% } %>
<% posts.forEach(function(post){ %>
<li><%= post.title %> - <strong><%= post.author %></strong></li>
<% }) %>
```
### 成品

## 練習
### 結構
**app.js**
```javascript
var express = require("express");
var app = express();
//app.use傳遞一個包含靜態資源的目錄給express.static
//也就是說在public目錄下的檔案都可以使用
app.use(express.static("public"));
//宣告view engine的模板庫為ejs
//當設定好了之後我在eres.render就可以直接輸出檔名不用加.ejs
app.set('view engine', 'ejs');
app.get("/", function(req, res){
res.render("home");
})
app.get("/fallinlovewith/:thing", function(req, res){
var thing = req.params.thing;
//將views裡面的love.ejs的thing存放這裡的thing的資料
res.render("love", {thing: thing});
})
app.get("/post", function(req, res){
var posts = [
{title: "Post 1", author: "Susy"},
{title: "My adorable pet bunny", author: "Charlie"},
{title: "Can you believe this pomsky?", author: "Colt"},
]
res.render("posts", {posts: posts});
})
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server is listening!!!");
});
```
* home.js
```ejs
<link rel="stylesheet" href="app.css">
<h1>This is the Home page!!</h1>
```
* love.js
```ejs
<link rel="stylesheet" href="/app.css">
<!--<%= %>被它包含地被視為javascript-->
<!--接收app.js的資料-->
<h1>You fell in love with: <%=thing.toUpperCase()%></h1>
<!--<%= %>是將裡面的js內容直接傳回到html
但是如果只是要做邏輯指令就不要加等於改成<% %>-->
<%if(thing.toLowerCase() === "rusty"){ %>
<p>GOOD CHICE! RUSTY IS THE BEST!</p>
<% } else { %>
<p>Bad choice! You should have said Rusty!</p>
<% } %>
<p>P.S. this is the love.ejs</p>
```
* post.js
```ejs
<link rel="stylesheet" href="/app.css">
<h1>The Posts Page</h1>
<% for(var i = 0; i < posts.length; i++){%>
<li><%= posts[i].title %> - <strong><%= posts[i].author %></strong></li>
<% } %>
<% posts.forEach(function(post){ %>
<li><%= post.title %> - <strong><%= post.author %></strong></li>
<% }) %>
```
* app.css
```css
body {
background: yellow;
color: purple;
}
```
### 成品

## 作業二
### 結構
* app.js
```javascript
var express = require("express");
var app = express();
//body-parser主要是對post請求解析
var bodyParser = require('body-parser');
//bodyParser.urlencoded用來解析req.body的數據
//通常是用來解析from表單的數據
//如果設置為false那麼對URL-encoded的數據解析將採用querystring
//如果設置為true那麼採用qs庫允許將父對象和數組編碼為url編碼格式允許使用url編碼的json體驗
app.use(bodyParser.urlencoded({ extended: true }));
app.set("view engine", "ejs");
var friends = ["Tony", "Miranda", "Justin", "Pierre", "Lily"];
app.get("/", function(req, res){
res.render("home");
});
app.post("/addfriend", function(req, res){
var newFriend = req.body.newfriend;
friends.push(newFriend);
res.redirect("/friends");
});
app.get("/friends", function(req, res){
res.render("friends", {friends: friends});
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("Server is listening!!!");
});
```
* friends.ejs
```ejs
<h1>Friends List Goes Here!</h1>
<% friends.forEach(function(friend){%>
<li><%= friend %></li>
<% }); %>
<form method="POST" action="/addfriend" >
<input type="text" name="newfriend" placeholder="name">
<button>I made a new friend!"</button>
</form>
```
* home.ejs
```ejs
<h1>HOME PAGE!!</h1>
```
### 成品

* 如果要POST請求BODY裡面的內容必須先在commendline輸入npm install body-parser --save 安裝body-parser套件
## YelpCarmp
### 結構
- app.js
```javascript
var express = require("express");
var app = express();
app.set("view engine", "ejs");
app.get("/", function(req, res){
res.render("landing");
});
app.get("/campgrounds", function(req, res){
var campgrounds = [
{name: "Salmon Creek", image:"https://s3-ap-northeast-1.amazonaws.com/thegate/2019/06/13/17/29/28/Shima-onsen-lake-okushima-Top.jpg"},
{name: "Granite Hill", image:"https://e.share.photo.xuite.net/winnie199064/1ec093a/11600393/545581617_m.jpg"},
{name: "Mountain Goat's Rest", image:"https://pic.pimg.tw/jay7134/1484674030-1921788632.jpg"}
]
res.render("campgrounds", {campgrounds:campgrounds});
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The YelpCamp Sever Has Started!");
});
```
- landion.ejs
```html
<h1>Landing Page!</h1>
<p>Welcome to YelpCamp</p>
<a href="/campgrounds">View All Campgrounds</a>
```
- campgrounds.ejs
```ejs
<h1>This is the camprounds page!</h1>
<% campgrounds.forEach(function(campground){ %>
<div>
<h4><%= campground.name %></h4>
<!--這邊的圖片可以直接使用建立的物件這樣就不用一個一個貼圖片網址-->
<img src="<%= campground.image %>">
</div>
<% }); %>
```
### 成品
{%youtube WF24xHGLmG4 %}
## YelpCarmp2
### 結構
* app.js
```javascript
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var campgrounds = [
{name: "Salmon Creek", image:"https://s3-ap-northeast-1.amazonaws.com/thegate/2019/06/13/17/29/28/Shima-onsen-lake-okushima-Top.jpg"},
{name: "Granite Hill", image:"https://e.share.photo.xuite.net/winnie199064/1ec093a/11600393/545581617_m.jpg"},
{name: "Mountain Goat's Rest", image:"https://pic.pimg.tw/jay7134/1484674030-1921788632.jpg"}
]
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.get("/", function(req, res){
res.render("landing");
});
app.get("/campgrounds", function(req, res){
res.render("campgrounds", {campgrounds:campgrounds});
});
//對campground發送一個POST請求
app.post("/campgrounds", function(req, res){
//接收new.ejs所傳送出來的資料
var name = req.body.name;
var image = req.body.image;
var newCampground = {name: name, image: image}
//將newCampground物件的東西推進新增到campgrounds物件裡
campgrounds.push(newCampground);
//重新轉向
res.redirect("/campgrounds");
});
//執行new.ejs的動作內容
app.get("/campgrounds/new", function(req, res){
res.render("new.ejs");
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The YelpCamp Sever Has Started!");
});
```
* landion.ejs
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<h1>Landing Page!</h1>
<p>Welcome to YelpCamp</p>
<a href="/campgrounds">View All Campgrounds</a>
<%- include ('partials/footer') ;%>
```
* campgrounds.ejs
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<h1>This is the camprounds page!</h1>
<a href="/campgrounds/new">Add New Campground</a>
<% campgrounds.forEach(function(campground){ %>
<div>
<h4><%= campground.name %></h4>
<!--這邊的圖片可以直接使用建立的物件這樣就不用一個一個貼圖片網址-->
<img src="<%= campground.image %>">
</div>
<% }); %>
<%- include ('partials/footer') ;%>
```
* new.ejs
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<h1>Create a New Campground</h1>
<!--對campgrounds執行POST請求-->
<form action="/campgrounds" method= "POST">
<input type="text" name="name"placeholder= "name">
<input type="text" name= "image"placeholder= "imge url">
<button>Submit!</button>
</form>
<a href="/campgrounds">Go Back</a>
<%- include ('partials/footer') ;%>
```
### 成品
{%youtube WF24xHGLmG4 %}
## YelpCarmp美化
### 結構
**app.js**
```javascript
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var campgrounds = [
{name: "Salmon Creek", image:"https://s3-ap-northeast-1.amazonaws.com/thegate/2019/06/13/17/29/28/Shima-onsen-lake-okushima-Top.jpg"},
{name: "Granite Hill", image:"https://e.share.photo.xuite.net/winnie199064/1ec093a/11600393/545581617_m.jpg"},
{name: "Mountain Goat's Rest", image:"https://pic.pimg.tw/jay7134/1484674030-1921788632.jpg"},
{name: "Salmon Creek", image:"https://s3-ap-northeast-1.amazonaws.com/thegate/2019/06/13/17/29/28/Shima-onsen-lake-okushima-Top.jpg"},
{name: "Granite Hill", image:"https://e.share.photo.xuite.net/winnie199064/1ec093a/11600393/545581617_m.jpg"},
{name: "Mountain Goat's Rest", image:"https://pic.pimg.tw/jay7134/1484674030-1921788632.jpg"},
{name: "Salmon Creek", image:"https://s3-ap-northeast-1.amazonaws.com/thegate/2019/06/13/17/29/28/Shima-onsen-lake-okushima-Top.jpg"},
{name: "Granite Hill", image:"https://e.share.photo.xuite.net/winnie199064/1ec093a/11600393/545581617_m.jpg"},
{name: "Mountain Goat's Rest", image:"https://pic.pimg.tw/jay7134/1484674030-1921788632.jpg"}
]
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine", "ejs");
app.get("/", function(req, res){
res.render("landing");
});
app.get("/campgrounds", function(req, res){
res.render("campgrounds", {campgrounds:campgrounds});
});
//對campground發送一個POST請求
app.post("/campgrounds", function(req, res){
//接收new.ejs所傳送出來的資料
var name = req.body.name;
var image = req.body.image;
var newCampground = {name: name, image: image}
//將newCampground物件的東西推進新增到campgrounds物件裡
campgrounds.push(newCampground);
//重新轉向
res.redirect("/campgrounds");
});
//執行new.ejs的動作內容
app.get("/campgrounds/new", function(req, res){
res.render("new.ejs");
});
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The YelpCamp Sever Has Started!");
});
```
**landion.ejs**
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<h1>Landing Page!</h1>
<p>Welcome to YelpCamp</p>
<a href="/campgrounds">View All Campgrounds</a>
<%- include ('partials/footer') ;%>
```
**campgrounds.ejs**
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<div class="containter">
<header class="jumbotron">
<div class="container">
<h1>Welcome To YelpCamp</h1>
<p>View our hand-picked campground from all over the world</p>
<p>
<a class="btn btn-primary btn-large" href="/campgrounds/new">Add New Campground</a>
</p>
</div>
</header>
<div class="row text-center" style="display:flex; flex-wrap: wrap;">
<% campgrounds.forEach(function(campground){ %>
<div class="col-md-3 col-md-6">
<div class="thumbnail">
<div class="caption">
<h4><%= campground.name %></h4>
</div>
<!--這邊的圖片可以直接使用建立的物件這樣就不用一個一個貼圖片網址-->
<img src="<%= campground.image %>">
</div>
</div>
<% }); %>
</div>
</div>
<%- include ('partials/footer') ;%>
```
**new.ejs**
```ejs
<!--影片中的include語法是舊版的語法-->
<!--現在新版的include方法是下面這種-->
<%- include ('partials/header'); %>
<div class="container">
<div class="row">
<h1 style="text-align: center;">Create a New Campground</h1>
<!--對campgrounds執行POST請求-->
<div style="width: 30%; margin: 25px auto;">
<form action="/campgrounds" method= "POST">
<div class="form-group">
<input class="form-control" type="text" name="name"placeholder= "name">
</div>
<div class="form-group">
<input class="form-control" type="text" name= "image"placeholder= "imge url">
</div>
<div class="form-group">
<button class="btn btn-lg btn-primary btn-block">Submit!</button>
</div>
</form>
<a href="/campgrounds">Go Back</a>
</div>
</div>
</div>
<%- include ('partials/footer') ;%>
```
**header.ejs**
```ejs
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<title>YelpCamp</title>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">YelpCamp</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="/">Login</a></li>
<li><a href="/">Sign Up</a></li>
<li><a href="/">Logout</a></li>
</ul>
</div>
</div>
</nav>
```
**footer.ejs**
```ejs
<p>TradeMark YelpCamp 2020</p>
</body>
</html>
```
### 成品
**首頁**

**內容**

**新增頁**
