# 0414 網頁中的互動及行為
###### tags: `JavaScript`
- [投影片連結](https://hackmd.io/@pastleo/H17nXC9ru#/)
- [隨堂練習包](https://drive.google.com/file/d/119Y4C1RKUiOLr3KjsFZq_mpFmyChxS9s/view)
* 直接使用 VScode 的 Live Server
* 在 Ruby 裡面執行一個 Server
```shell=
$ ruby -run -ehttpd . -p8000
## 如果沒有成功的話可以安裝套件 webrick (ruby 3.0 之後沒有內建)
$ gem install webrick
```
## 瀏覽器內建的 DOM API
- Vanilla JavaScript
- 只使用瀏覽器內建的 DOM API 執行 JavaScript
- 所有框架的底層都是 DOM API
### 在網頁中加入 JavaScript 程式碼
- 使用 `script` tag
- 最好放在 `head` 或 `body` 裡面
```html=
<script>
<!-- JS程式碼 -->
</script>
```
- 使用 console.log 確認沒有有執行成功
- 也可以用 debugger
``` javascript
<body>
<script>
console.log(123)
</script>
</body>
```

### 監聽事件 `.addEventListener()`
- 告訴這個元件,之後收到什麼事件後做什麼事情
- `.addEventListener()` 方法可以用來綁定元素的事件處理函數
- 第一個參數 eventType 是事件名稱( 範例中為 ``'click'`` )
- 第二個參數 listener 是事件處理函數( 範例中為 `function(){...}` )
- 監聽型態:
- ==主詞.動詞("事件", Callback Function)==
- 網頁裡的元素.監聽("監聽的事件", 要叫元素做的事情)
例:
```javascript=
<style>
body {
background: #353535;
margin: 0;
}
body.light {
background: #d4c370;
}
</style>
<script>
document.body.addEventListener('click', function() {
document.body.classList.toggle('light')
// toggle 讓 class 有 light 跟沒 light
// 因為有無 class 是在 CSS 中是不一樣的樣式
})
</script>
```
- 元素選取方式
1. `document.body` : 選取檔案裡的 `body`
2. [`.classlist`](#classList) : class 清單 (因為可以有很多 class)
- `document.body.classList` : 選取檔案裡的 `body` 的 class 清單
3. `document.body.className` : 選取檔案裡的 `body` 的 class 名稱
4. `.getElementById("id 名稱")` : 用 ID 選取物件
- `document.getElementById("cat")` : 選取檔案裡 ID 叫 cat 的元素
5. ``.textContent = ''`` : 標籤裡面的內容
6. ``.innerHTML = ''`` : 標籤裡的內容(再套用 HTML)
7. ``.querySelector( CSS 選取器 )`` : 用 CSS 選取器指定元素(只會選到第一個)
8. ``.querySelectorAll( CSS 選取器 )`` : 要跑 forEach 迴圈)
- 監聽的事件
1. ``"click"``: 「點擊」這件事(滑鼠點下去的時候)
2. ``"DOMContentLoaded"`` : 當整個網頁被讀取後會觸發後面的事件
- [MDN 的解釋](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event)
4. [事件型態 - 可以監聽的事件](https://www.fooish.com/javascript/dom/event.html)
- Callback function
- ``.toggle()``
- 狀態對調(沒有的時候 add, 有的時候 remove)
- ``.add()``
- 加上某個東西
- ``.remove()``
- 移除某個東西
- ``.createElement('HTML element')``
- 新增一個元素(要找個東西接它)
- ``parent.appendChild('element')``
- 把它塞到某個元素的最後一個子元素位置
- ``.insertAdjacentElement('位置', 'element')``
- 可自行設定要把元素塞到哪裡
- [手冊說明](https://developer.mozilla.org/zh-TW/docs/Web/API/Element/classList)

- 由於網頁是由上往下讀取,所以 script 的位置會影響到程式執行與否,因此加上 DOMContentLoaded 事件,可以把整個 HTML 讀完才執行 JS
```html=
<script>
//↓請你把全部html讀完再來執行JS的程式
document.addEventListener('DOMContentLoaded', function() {
//放要執行的JS程式↓
document.getElementById('toggle').addEventListener('click', function(){
document.body.classList.toggle('light')
})
})
</script>
```
### classList
* add 新增
* 新增一個或多個類別
* 已經存在的不會再新增
* remove 移除
* 刪除
* toggle 切換
* 當 Div 上沒有這個CSS的時候,就新增給他,有的話就刪掉他
* contains 是否存在
* 檢查是否存在某個CSS
* 回傳布林值
## JS 的等號
- [JS的雙等號跟三等號:寬鬆模式 VS 嚴謹模式](https://medium.com/schaoss-blog/%E5%89%8D%E7%AB%AF%E4%B8%89%E5%8D%81-13-js-%E7%82%BA%E4%BB%80%E9%BA%BC%E5%88%A4%E6%96%B7%E7%9B%B8%E7%AD%89%E6%99%82%E4%B8%8D%E7%94%A8%E8%83%BD%E9%9B%99%E7%AD%89%E8%99%9F-d02fbf91492f)
```javascript=
1 == '1' // true // JS 背後自動轉型態
1 === '1' // false // 數字不等於字串
```
## 有關 window
- window 是預設的 namespace
- 瀏覽器剛發明的時候沒有分頁的概念,所以當初的 window 就是表示整個瀏覽器
- Date 處理時間相關,是個class,等於window.Date 所以隨時可以使用Date
- ``(new Date()).toString()``
- 現在的時間並將他轉成字串
- location
- 網址列
- window.location
- 取得敘述網址列的物件
- window.location.href
- 印出現在當下的網址列
- window.location.href = '指定的網址列'
- 使用 JS 觸發換頁的動作
---
* debugger
* 會使程式停在擺放`debugger`的那行,且可透過檢查確認這時候的變數,並可用 console 試著執行要嘗試的程式
---
* `parent.appendChild(el)`
* 把傳進去的 el 傳入 parent 裡面的最後面
* el = element 縮寫
範例:
```html=
document.querySelector('.right').appendChild(timeDiv)
```
timeDiv 就會被傳到 `class='right'` 這個 div 裡最後面
如圖的台北標準時間那幾行

## innerHTML
- 可以替換 html 資料
- 避免放入使用者輸入的資料
---
`prompt()`
顯示一個對話框,對話框中包含一條文字,用來提示用戶輸入文字。
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt)
---
## insertAdjacentElement
- 指定位置
## jQuery
$ / $()
為解決早期 DOM API 相容性的問題
```javascript=
document.querySelector() = $()
```
- [jQuery API 列表](https://api.jquery.com/)
- 引入 jQuery
- [jQuery 官網](https://code.jquery.com/)
- 點擊 3.0.0 minified

console 檢查
$.fn.jquery
```javascript=
document.addEventListener('DOMContentLoaded', function(){...})
// 等於 下方的 jQuery 用法
$(document).ready(function(){...})
document.querySelector('').addEventListener('click',function(){...})
// 等於 下方的 jQuery 用法
$('').click(function(){...})
```
### 計時器功能 (瀏覽器內建功能)
```javascript=
timer = setInterval(function(){...}, 時間) // 每隔多久時間跳一次
// 單位為 1 ms 毫秒
clearInterval(timer)
timeout = setTimeout(function(){...}, 時間 // 等待多久時間啟動
// 單位為 1 ms 毫秒
clearTimeout(timeout)
```
投影幕的概念
- .slideDown
- .slideUp
- .append()
- .prepend()
- .prependTo() 放最前面
- .appendTo() 放最後面
```javascript=
$('.dots div:last-child').prependTo($('.dots'))
把最後一個div放進.dots這個div裡面的最前面
$('.dots').prepend($('.dots div:last-child'))
讓.dots這個div裡的最後一個div移到最前面
```
[Math.floor 說明](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Math/floor)
## 你可能不需要 jQuery !!!
- ==IE 已死 !!! Die!!! Die!!! Die!!!==
- 純粹把 DOM API 包起來增加效能,沒有本質上的改變
- [查查看人家怎麼改](http://youmightnotneedjquery.com/)
---
## 題外話
* 西瓜不建議用 this ,因為在 JS 裡不能馬上分辨 this 是指哪個物件,同時環境越來越複雜的時候,會搞不清this在指誰
* 但建議要理解 this ,面試會問,而且若是接手到以前的專案也有機會碰到
* 清除瀏覽器快取(Cache),查看最真實正確的網站狀況
* 開發者工具 -> Network -> Disable cache 打勾

* Vue.js 跟 React.js:JS框架,更好的模組化,處理各種行為
* html 文字:DOM 將他實體化放在瀏覽器的樣子
---
## 下面是西瓜老師提供的範例 & Info
### Callback
[MDN](https://developer.mozilla.org/zh-TW/docs/Glossary/Callback_function)
```javascript=
function afterOneSecond(callback) {
setTimeout(function() {
callback();
}, 1000)
}
afterOneSecond(function() {
console.log('callback called')
})
```