From 3204d35e53c4699db68a4251133f618655d5a801 Mon Sep 17 00:00:00 2001 From: many2many <6168830@qq.com> Date: Mon, 30 Sep 2024 08:10:21 +0800 Subject: [PATCH] add examples --- .../chapter02/042-live user filter/index.html | 22 +++ .../chapter02/042-live user filter/script.js | 38 +++++ .../chapter02/042-live user filter/style.css | 94 ++++++++++++ .../chapter02/065-hangman game/index.html | 49 ++++++ examples/chapter02/065-hangman game/script.js | 125 +++++++++++++++ examples/chapter02/065-hangman game/style.css | 143 ++++++++++++++++++ 6 files changed, 471 insertions(+) create mode 100644 examples/chapter02/042-live user filter/index.html create mode 100644 examples/chapter02/042-live user filter/script.js create mode 100644 examples/chapter02/042-live user filter/style.css create mode 100644 examples/chapter02/065-hangman game/index.html create mode 100644 examples/chapter02/065-hangman game/script.js create mode 100644 examples/chapter02/065-hangman game/style.css diff --git a/examples/chapter02/042-live user filter/index.html b/examples/chapter02/042-live user filter/index.html new file mode 100644 index 0000000..7852434 --- /dev/null +++ b/examples/chapter02/042-live user filter/index.html @@ -0,0 +1,22 @@ + + + + + + + Live User Filter + + +
+
+

Live User Filter

+ Search by name and/or location + +
+ +
+ + + diff --git a/examples/chapter02/042-live user filter/script.js b/examples/chapter02/042-live user filter/script.js new file mode 100644 index 0000000..ff5d3ad --- /dev/null +++ b/examples/chapter02/042-live user filter/script.js @@ -0,0 +1,38 @@ +const result = document.getElementById("result"); +const filter = document.getElementById("filter"); +const listItems = []; + +const filterData = (searchTerm) => { + listItems.forEach((item) => { + if (item.innerText.toLowerCase().includes(searchTerm.toLowerCase())) { + item.classList.remove("hide"); + } else { + item.classList.add("hide"); + } + }); +}; + +const getData = async () => { + const res = await fetch("https://randomuser.me/api?results=50"); + const { results } = await res.json(); + result.innerHTML = ""; + results.forEach((user) => { + const li = document.createElement("li"); + listItems.push(li); + li.innerHTML = ` + ${user.name.first} +
+

${user.name.first} ${user.name.last}

+

${user.location.city}, ${user.location.country}

+
+ `; + result.appendChild(li); + }); +}; + +getData(); + +filter.addEventListener("input", (e) => filterData(e.target.value)); diff --git a/examples/chapter02/042-live user filter/style.css b/examples/chapter02/042-live user filter/style.css new file mode 100644 index 0000000..44d54ac --- /dev/null +++ b/examples/chapter02/042-live user filter/style.css @@ -0,0 +1,94 @@ +@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"); + +* { + box-sizing: border-box; +} + +body { + background-color: #f8f9fd; + font-family: "Roboto", sans-serif; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + overflow: hidden; + margin: 0; +} + +.container { + border-radius: 5px; + box-shadow: 3px 3px 10px rgba(0, 0, 0, 0.2); + overflow: hidden; + width: 300px; +} + +.title { + margin: 0; +} + +.subtitle { + display: inline-block; + margin: 5px 0 20px; + opacity: 0.8; +} + +.header { + background-color: #3e57db; + color: #fff; + padding: 30px 20px; +} + +.header input { + background-color: rgba(0, 0, 0, 0.3); + border: 0; + border-radius: 50px; + color: #fff; + font-size: 14px; + padding: 10px 15px; + width: 100%; +} + +.header input:focus { + outline: none; +} + +.user-list { + background-color: #fff; + list-style-type: none; + margin: 0; + padding: 0; + max-height: 400px; + overflow-y: auto; +} + +.user-list li { + display: flex; + padding: 20px; +} + +.user-list img { + border-radius: 50%; + object-fit: cover; + height: 50px; + width: 50px; +} + +.user-list .user-info { + margin-left: 10px; +} + +.user-list .user-info h4 { + margin: 0 0 10px; +} + +.user-list .user-info p { + font-size: 12px; +} + +.user-list li:not(:last-of-type) { + border-bottom: 1px solid #eee; +} + +.user-list li.hide { + display: none; +} diff --git a/examples/chapter02/065-hangman game/index.html b/examples/chapter02/065-hangman game/index.html new file mode 100644 index 0000000..96d8a02 --- /dev/null +++ b/examples/chapter02/065-hangman game/index.html @@ -0,0 +1,49 @@ + + + + + + + Hangman + + +

Hangman

+

Find the hidden word - Press a letter

+
+ + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + +
+

You have already entered this letter

+
+ + + diff --git a/examples/chapter02/065-hangman game/script.js b/examples/chapter02/065-hangman game/script.js new file mode 100644 index 0000000..68dfb0f --- /dev/null +++ b/examples/chapter02/065-hangman game/script.js @@ -0,0 +1,125 @@ +const wordElement = document.getElementById("word"); +const wrongLettersElement = document.getElementById("wrong-letters"); +const playAgainButton = document.getElementById("play-button"); +const popup = document.getElementById("popup-container"); +const notification = document.getElementById("notification-container"); +const finalMessage = document.getElementById("final-message"); +const finalMessageRevealWord = document.getElementById( + "final-message-reveal-word" +); +const figureParts = document.querySelectorAll(".figure-part"); + +const words = [ + "application", + "programming", + "interface", + "wizard", + "element", + "prototype", + "callback", + "undefined", + "arguments", + "settings", + "selector", + "container", + "instance", + "response", + "console", + "constructor", + "token", + "function", + "return", + "length", + "type", + "node", +]; +let selectedWord = words[Math.floor(Math.random() * words.length)]; + +let playable = true; + +const correctLetters = []; +const wrongLetters = []; + +function displayWord() { + wordElement.innerHTML = ` + ${selectedWord + .split("") // to array + .map( + (letter) => ` + + ${correctLetters.includes(letter) ? letter : ""} + + ` + ) + .join("")} + `; // to string + const innerWord = wordElement.innerText.replace(/\n/g, ""); + if (innerWord === selectedWord) { + finalMessage.innerText = "Congratulations! You won! 😃"; + finalMessageRevealWord.innerText = ""; + popup.style.display = "flex"; + playable = false; + } +} + +function updateWrongLettersElement() { + wrongLettersElement.innerHTML = ` + ${wrongLetters.length > 0 ? "

Wrong

" : ""} + ${wrongLetters.map((letter) => `${letter}`)} + `; + figureParts.forEach((part, index) => { + const errors = wrongLetters.length; + index < errors + ? (part.style.display = "block") + : (part.style.display = "none"); + }); + if (wrongLetters.length === figureParts.length) { + finalMessage.innerText = "Unfortunately you lost. 😕"; + finalMessageRevealWord.innerText = `...the word was: ${selectedWord}`; + popup.style.display = "flex"; + playable = false; + } +} + +function showNotification() { + notification.classList.add("show"); + setTimeout(() => { + notification.classList.remove("show"); + }, 2000); +} + +window.addEventListener("keypress", (e) => { + if (playable) { + const letter = e.key.toLowerCase(); + if (letter >= "a" && letter <= "z") { + if (selectedWord.includes(letter)) { + if (!correctLetters.includes(letter)) { + correctLetters.push(letter); + displayWord(); + } else { + showNotification(); + } + } else { + if (!wrongLetters.includes(letter)) { + wrongLetters.push(letter); + updateWrongLettersElement(); + } else { + showNotification(); + } + } + } + } +}); + +playAgainButton.addEventListener("click", () => { + playable = true; + correctLetters.splice(0); + wrongLetters.splice(0); + selectedWord = words[Math.floor(Math.random() * words.length)]; + displayWord(); + updateWrongLettersElement(); + popup.style.display = "none"; +}); + +// Init +displayWord(); diff --git a/examples/chapter02/065-hangman game/style.css b/examples/chapter02/065-hangman game/style.css new file mode 100644 index 0000000..7a19031 --- /dev/null +++ b/examples/chapter02/065-hangman game/style.css @@ -0,0 +1,143 @@ +@import url("https://fonts.googleapis.com/css2?family=DotGothic16&display=swap"); + +:root { + --primary-color: #1f2f61; + --secondary-color: #224ca4; + --light-color: #a7c2da; +} + +* { + box-sizing: border-box; +} + +body { + background-color: var(--primary-color); + color: var(--light-color); + font-family: "DotGothic16", sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 80vh; + overflow: hidden; + margin: 0; +} + +h1 { + margin: 20px 0 0; + letter-spacing: 0.5rem; + text-transform: uppercase; +} + +h2, +h3 { + letter-spacing: 0.2rem; +} + +.game-container { + padding: 20px 30px; + position: relative; + margin: auto; + height: 350px; + width: 450px; +} + +.figure-container { + fill: transparent; + stroke: var(--light-color); + stroke-width: 4px; + stroke-linecap: round; +} + +.wrong-letters-container { + position: absolute; + top: 20px; + right: 20px; + display: flex; + flex-direction: column; + text-align: right; +} + +.wrong-letters-container p { + margin: 0 0 5px; +} + +.wrong-letters-container span { + font-size: 24px; +} + +.word { + display: flex; + position: absolute; + bottom: 10px; + left: 50%; + transform: translateX(-50%); +} + +.letter { + border-bottom: 3px solid var(--secondary-color); + display: inline-flex; + font-size: 30px; + align-items: center; + justify-content: center; + margin: 0 3px; + height: 50px; + width: 20px; +} + +.popup-container { + background-color: rgba(0, 0, 0, 0.3); + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: none; + align-items: center; + justify-content: center; +} + +.popup { + background-color: var(--secondary-color); + border-radius: 5px; + box-shadow: 0 15px 10px 3px rgba(0, 0, 0, 0.1); + padding: 20px; + text-align: center; +} + +.popup button { + cursor: pointer; + background-color: var(--light-color); + color: var(--secondary-color); + border: 0; + margin-top: 20px; + padding: 12px 20px; + font-size: 16px; + font-family: inherit; + border-radius: 5px; +} + +.popup button:active { + transform: scale(0.98); +} + +.popup button:focus { + outline: none; +} + +.notification-container { + background-color: rgba(0, 0, 0, 0.3); + border-radius: 10px 10px 0 0; + padding: 15px 20px; + position: absolute; + bottom: -60px; + transition: transform 0.3s ease-in-out; +} + +.notification-container.show { + transform: translateY(-60px); +} + +.notification-container p { + margin: 0; +}