### 透過 YouTube 資源,學習別人如何製作 ToDoList
- [教學連結](https://www.youtube.com/watch?v=G0jO8kUrg-I)
### 透過 linear-gradient,實現背景漸變效果:
```
// HTML :
<div class="container"></div>
```
- 針對 container 設定 CSS。
- 我學到了什麼: min-height: 100vh; -> 表示設定最低高度為當前瀏覽器的 100%
- 我學到了什麼: [linear-gradient](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient) -> 為背景顏色屬性,可透過兩種顏色設定行為及控制角度來達到背景顏色的操作設計。
```
// CSS:
.container {
width: 100%;
min-height: 100vh;
background: linear-gradient(135deg, #153677, #4e085f);
padding: 10px;
}
```
### 背景概況如下:
- 有些情況,我們單純只想用顏色混搭當作背景的話
我們是不需要透過插入圖片來完成顏色混搭,透過 linear-gradient 也可做到!

### 繼續完成程式碼:
- 這邊我們在建立一個 .todo-app
裡面有一個 h2 title , 旁邊可以放置一個自己的圖片當作 logo。
「請注意,請放置沒有版權使用問題的圖片。」

```
// HTML:
<div class="container">
<div class="todo-app">
<h2>
To-Do-List <img class="logo" src="./img/icon.avif" alt="logo" />
</h2>
</div>
</div>
```
- todo-app 設定 styling
```
// CSS:
.todo-app {
width: 100%;
max-width: 540px;
background-color: #fff;
margin: 100px auto 20px;
padding: 40px 30px 70px;
border-radius: 10px;
}
```
- 設定 title & img
```
// CSS:
.todo-app h2 {
color: #002765;
display: flex;
align-items: center;
margin-bottom: 20px;
}
img {
border-radius: 50%;
}
.todo-app h2 img {
width: 60px;
margin-left: 10px;
}
```

### 設定 輸入欄位 & 按鈕:
```
// HTML:
<div class="container">
<div class="todo-app">
<h2>
To-Do-List <img class="logo" src="./img/icon.avif" alt="logo" />
</h2>
<div class="row">
<!-- 設置 row -->
<input type="text" id="input-box" placeholder="Add your text" />
<button>Add</button>
</div>
</div>
</div>
```

- .row 設定 styling
```
// CSS:
.row {
display: flex;
align-items: center;
justify-content: space-between;
background: #edeef0;
border-radius: 30px;
padding-left: 20px;
margin-bottom: 25px;
}
```

- 這邊我們可以注意到我們的 input 欄位跟 backgroud 看起來有點怪怪的,我們將針對 input 做一些 style 調整。
```
// CSS:
input {
flex: 1;
border: none;
/* 取消外框 */
outline: none;
/* transparent - 可透過這個設定來使該元素的背景透明,至於父元素之上 */
background: transparent;
padding: 10px;
}
```
- 修改以後:
- 我學到了什麼: 取消外框 - `outline: none;`
- 我學到了什麼: ` background: transparent;` 當下背景透明

### 針對按鈕做樣式設計:
- 我學到了什麼: `cursor: pointer` -> 用戶游標指向在元素上,可產生一個手指的圖示
```
// CSS:
button {
border: none;
/* 取消外框 */
outline: none;
padding: 16px 50px;
background: #ff5945;
color: #fff;
font-size: 16px;
/* cursor: pointer , 用戶游標指向在元素上,可產生一個手指的圖示 */
cursor: pointer;
border-radius: 40px;
}
```
- 成果圖示:

### 於 .todo-app 下設置 id="list-container"
```
// CSS:
<div class="container">
<div class="todo-app">
<h2>
To-Do-List <img class="logo" src="./img/icon.avif" alt="logo" />
</h2>
<div class="row">
<input type="text" id="input-box" placeholder="Add your text" />
<button>Add</button>
</div>
<!-- list-container -->
<ul id="list-container">
<li>Task 1</li>
<li>Task 2</li>
<li>Task 3</li>
</ul>
</div>
</div>
```
### 針對 ul 撰寫 style:
- 細節 # 透過 background-image 設定 uncheck image
::before 偽元素實現 style
```
// CSS:
ul li {
list-style-type: none;
font-size: 17px;
padding: 12px 8px 12px 50px;
/* 此設定可以阻止 user 選取內容 */
user-select: none;
cursor: pointer;
position: relative;
}
/* li 前面(::before)添加偽元素 */
ul li::before {
content: "";
position: absolute;
height: 28px;
width: 28px;
border-radius: 50%;
background-image: url(/img/unchecked.png);
background-size: cover;
background-position: center;
top: 8px;
left: 8px;
}
```

### ul.checked 樣式預先設置
```
// HTML:
<ul id="list-container">
<li class="checked">Task 1</li>
<li>Task 2</li>
<li>Task 3</li>
</ul>
```
- 設計 li 刪除線樣式
```
// CSS:
/* li 刪除線樣式 */
ul li.checked {
color: #555;
text-decoration: line-through;
}
```

- 設計 li.checked 完成的圖示:
- 可以運用::before 技巧。
```
ul li.checked::before {
background-image: url(/img/checked.png);
}
```
- 在此就可以看到:
- 完成與未完成的完整區別樣貌。

### 前置樣式設定完成,後續將執行 JavaScript 撰寫:
1. 先回到 HTML 檔案,將剛剛設計的 ul > li 區塊給他註解起來。
```
// HTML:
<ul id="list-container">
<!-- <li class="checked">Task 1</li>
<li>Task 2</li>
<li>Task 3</li> -->
</ul>
```
2. 開啟 js 檔案,撰寫 JavaScript:
- 如要使 buuton 產生按鈕事件效果
手動在標籤旁加入 'onclick' 並導入 addTask()
```
// JS:
// 指向 #input-box 欄位
const inputBox = document.getElementById("input-box");
// 指向 ul 區塊
const listContainer = document.getElementById("list-container");
// 加入待辦
btn.addEventListener("click", function () {
if (inputBox.value === "") {
alert("You must write something!");
} else {
let li = document.createElement("li"); // 宣告一個 li 變數,添加一個 li
li.innerHTML = inputBox.value; // li 標籤裡的內容,根據我們所輸入的內容
listContainer.appendChild(li); // DOM 操作,用於添加子元素的語法 , 對象是 li
}
// 優化設定,輸入內容後消除輸入欄位文字:
inputBox.value = "";
});
```
- 學習點: `document.createElement("li")`
此語法用於建構在網頁上產生一個 elements Tag
- 並且,我們所添加的 li 內容都來自於我們所輸入的待辦事項內容:
- 也就是: `li.innerHTML = inputBox.value; `
透過,innerHTML 方式。
- 上述行為完成,指定 ul id,添加一個子元素行為:
`listContainer.appendChild(li); `

### 我們需要在 list 內容旁添加一個 「刪除圖示」
- 在 else 後面添加 span
```
// JS:
btn.addEventListener("click", function () {
if (inputBox.value === "") {
alert("You must write something!");
} else {
let li = document.createElement("li");
li.innerHTML = inputBox.value;
listContainer.appendChild(li);
// 除了 li 內容,我們也須針對內容旁邊增加一個 delete 圖示
let span = document.createElement("span");
span.innerHTML = "\u00d7";
li.appendChild(span);
}
inputBox.value = "";
});
```

- 留意一下這個地方:
`span.innerHTML = "\u00d7"; `
- 這段 code "\u00d7" -> 使用了 (HTML symbols)是一些特殊的字符
### 接著,我們針對這個字符來設計 CSS
```
// CSS:
ul li span {
position: absolute;
top: 5px;
right: 0;
width: 40px;
font-size: 22px;
color: #555;
line-height: 40px;
text-align: center;
border-radius: 50%;
}
// 添加滑鼠移動樣式:
ul li span:hover {
background: #edeef0;
}
```

### 刪除待辦事項
1. 點擊該區域,如果獲取標籤屬性為「LI」,則切換元素
- 這邊的 **checked** 就是我們在 CSS 預先寫好的刪除線樣式。
```
e.target.classList.toggle("checked");
```
2. 點擊該區域(SPAN),則會移除父層元素(LI) -> 此方法即可將待辦給刪除
```
e.target.parentElement.remove();
```
```
listContainer.addEventListener("click", function (e) {
if (e.target.nodeName == "LI") {
e.target.classList.toggle("checked");
} else if (e.target.nodeName === "SPAN") {
e.target.parentElement.remove();
}
});
```

### localStorage 瀏覽器資料儲存
- 完成了待辦清單,不過這邊還有一些小小的問題
關閉了瀏覽器以後,待辦就會被清除了,這邊需要透過一個方法
讓資料可以存在於這個瀏覽器上。
- localStorage , setItem
- 增加本地儲存空間:
- 資料儲存方式,為 'key','value'
- 如下所示, key = 'data' -> 自定義 name
- value = -> listContainer.innerHTML
```
function saveData() {
localStorage.setItem("data", listContainer.innerHTML);
}
```
### 從瀏覽器了解 setItem , key & value
- 右鍵 -> 開發者工具 -> Application -> 左側 localStorage
可以看到我們暫存的資料庫,點下去並且就可以去看到右邊的
key & value ~

- 設定完 localStorage setItem 還需要在 listContainer
導入 saveData(),添加此函式的用意在於
我們執行了任何動作,都會透過行為紀錄於 listContainer
這個區塊的資料變化也就是 setItem 對應的 value
```
listContainer.addEventListener("click", function (e) {
if (e.target.nodeName == "LI") {
("checked")
e.target.classList.toggle("checked");
saveData();
} else if (e.target.nodeName === "SPAN") {
e.target.parentElement.remove();
saveData();
}
});
```
### localStorage getItem 撈取 key value
- 由下所示:
這段 code 表示我的待辦區塊資料顯示,會源自於
`localStorage.getItem("data");`
透過 listContainer.innerHTML 方式。
```
function showTask() {
listContainer.innerHTML = localStorage.getItem("data");
}
showTask();
```
- 最後在 JS Code 最後一行寫上 `showTask();`
該 ToDoList 專案就完成。
- 藉由此方式可實現瀏覽時緩存資料的行為
我們最後做了什麼事,瀏覽器就清楚地幫我們記錄起來,
### 更多參考資料:
- [localStorage 筆記 - 鐵人賽痞客邦](https://ithelp.ithome.com.tw/articles/10308554?sc=iThelpR)
- [認識瀏覽器的神秘儲存空間 - localStorage](https://5xruby.tw/posts/localstorage)