### 透過 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 也可做到! ![](https://hackmd.io/_uploads/Skx4S4h2n.png) ### 繼續完成程式碼: - 這邊我們在建立一個 .todo-app 裡面有一個 h2 title , 旁邊可以放置一個自己的圖片當作 logo。 「請注意,請放置沒有版權使用問題的圖片。」 ![](https://hackmd.io/_uploads/rkz2wN2nn.png) ``` // 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; } ``` ![](https://hackmd.io/_uploads/BkWw6Nh23.png) ### 設定 輸入欄位 & 按鈕: ``` // 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> ``` ![](https://hackmd.io/_uploads/rkjXRV3hh.png) - .row 設定 styling ``` // CSS: .row { display: flex; align-items: center; justify-content: space-between; background: #edeef0; border-radius: 30px; padding-left: 20px; margin-bottom: 25px; } ``` ![](https://hackmd.io/_uploads/BkJWyrnnh.png) - 這邊我們可以注意到我們的 input 欄位跟 backgroud 看起來有點怪怪的,我們將針對 input 做一些 style 調整。 ``` // CSS: input { flex: 1; border: none; /* 取消外框 */ outline: none; /* transparent - 可透過這個設定來使該元素的背景透明,至於父元素之上 */ background: transparent; padding: 10px; } ``` - 修改以後: - 我學到了什麼: 取消外框 - `outline: none;` - 我學到了什麼: ` background: transparent;` 當下背景透明 ![](https://hackmd.io/_uploads/r1vGZSn32.png) ### 針對按鈕做樣式設計: - 我學到了什麼: `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; } ``` - 成果圖示: ![](https://hackmd.io/_uploads/Skkx9Bn3h.png) ### 於 .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; } ``` ![](https://hackmd.io/_uploads/rkod-U2n2.png) ### 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; } ``` ![](https://hackmd.io/_uploads/H1hXzLn32.png) - 設計 li.checked 完成的圖示: - 可以運用::before 技巧。 ``` ul li.checked::before { background-image: url(/img/checked.png); } ``` - 在此就可以看到: - 完成與未完成的完整區別樣貌。 ![](https://hackmd.io/_uploads/Bkt7mL322.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); ` ![](https://hackmd.io/_uploads/HJASkPh33.png) ### 我們需要在 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 = ""; }); ``` ![](https://hackmd.io/_uploads/Sy6SWvhhn.png) - 留意一下這個地方: `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; } ``` ![](https://hackmd.io/_uploads/SkmuXwh33.png) ### 刪除待辦事項 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(); } }); ``` ![](https://hackmd.io/_uploads/B1dG6t33n.png) ### 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 ~ ![](https://hackmd.io/_uploads/SyiHU9n32.png) - 設定完 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)