diff --git a/Infinite Post Scroll/index.html b/Infinite Post Scroll/index.html new file mode 100644 index 00000000..74f23231 --- /dev/null +++ b/Infinite Post Scroll/index.html @@ -0,0 +1,28 @@ + + + + + + + My Blog + + +

My Blog

+
+ +
+
+
+
+
+
+
+ + + diff --git a/Infinite Post Scroll/script.js b/Infinite Post Scroll/script.js new file mode 100644 index 00000000..a27732f3 --- /dev/null +++ b/Infinite Post Scroll/script.js @@ -0,0 +1,73 @@ +const postsContainer = document.getElementById("posts-container"); +const loading = document.getElementById("loader"); +const filter = document.getElementById("filter"); + +let limit = 5; +let page = 1; +let isLoading = false; + +async function getPosts() { + const res = await fetch( + `https://jsonplaceholder.typicode.com/posts?_limit=${limit}&_page=${page}` + ); + const data = await res.json(); + return data; +} + +function capitalize(text) { + return text.charAt(0).toUpperCase() + text.slice(1); +} + +async function showPosts() { + const posts = await getPosts(); + posts.forEach((post) => { + const postEl = document.createElement("div"); + postEl.classList.add("post"); + postEl.innerHTML = ` +
${post.id}
+
+

${capitalize(post.title)}

+

${capitalize(post.body)}

+
+ `; + postsContainer.appendChild(postEl); + }); +} + +function showLoading() { + isLoading = true; + loader.classList.add("show"); + setTimeout(() => { + loader.classList.remove("show"); + setTimeout(() => { + page++; + showPosts(); + }, 300); + isLoading = false; + }, 1000); +} + +function filterPosts(e) { + console.log("running"); + const term = e.target.value.toUpperCase(); + const posts = document.querySelectorAll(".post"); + posts.forEach((post) => { + const title = post.querySelector(".post-title").innerText.toUpperCase(); + const body = post.querySelector(".post-body").innerText.toUpperCase(); + if (title.indexOf(term) > -1 || body.indexOf(term) > -1) { + post.style.display = "flex"; + } else { + post.style.display = "none"; + } + }); +} + +window.addEventListener("scroll", () => { + const { scrollTop, scrollHeight, clientHeight } = document.documentElement; + if (scrollTop + clientHeight >= scrollHeight - 5 && !isLoading) showLoading(); +}); + +filter.addEventListener("input", filterPosts); + +// Init +showPosts(); diff --git a/Infinite Post Scroll/style.css b/Infinite Post Scroll/style.css new file mode 100644 index 00000000..a02a235f --- /dev/null +++ b/Infinite Post Scroll/style.css @@ -0,0 +1,130 @@ +@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"); + +:root { + --main-color: #9cd4fa; + --secondary-color: #5da7e1; + --light-color: #eef7fc; + --dark-color: #171830; +} + +* { + box-sizing: border-box; +} + +body { + background-color: var(--main-color); + background-image: linear-gradient(315deg, var(--main-color) 0%, var(--light-color) 100%); + color: var(--dark-color); + font-family: "Roboto", sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; + margin: 0; + padding-bottom: 100px; +} + +h1 { + margin-bottom: 0; + text-align: center; +} + +.filter-container { + margin-top: 20px; + width: 80vw; + max-width: 800px; +} + +.filter { + width: 100%; + padding: 12px; + border-radius: 1rem; + font-size: 1rem; + border: none; +} + +.filter:focus { + outline: none; +} + +.post { + position: relative; + background-color: var(--light-color); + box-shadow: 0 2px 4px rgba(0,0,0,0.3); + border-radius: 1rem; + padding: 20px; + margin: 40px 0; + display: flex; + width: 80vw; + max-width: 800px; +} + +.post .post-title { + margin: 0; +} + +.post .post-body { + margin: 15px 0 0; + line-height: 1.3; +} + +.post .post-info { + margin-left: 20px; +} + +.post .number { + position: absolute; + top: -15px; + left: -15px; + font-size: 15px; + width: 40px; + height: 40px; + border-radius: 50%; + background-color: var(--secondary-color); + color: var(--light-color); + display: flex; + align-items: center; + justify-content: center; + padding: 7px 10px; +} + +.loader { + opacity: 0; + display: flex; + position: fixed; + bottom: 50px; + transition: opacity 0.3s ease-in; +} + +.loader.show { + opacity: 1; +} + +.circle { + background-color: var(--light-color); + width: 10px; + height: 10px; + border-radius: 50%; + margin: 5px; + animation: bounce 0.5s ease-in infinite; +} + +.circle:nth-of-type(2) { + animation-delay: 0.1s; + opacity: 0.8; +} + +.circle:nth-of-type(3) { + animation-delay: 0.2s; + opacity: 0.6; +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(0); + } + 50% { + transform: translateY(-10px); + } +} \ No newline at end of file