1import kebabCase from "https://cdn.jsdelivr.net/npm/lodash-es/kebabCase.js"; 2 3let blogPostsObject = blogPosts; 4 5const postsContainer = document.querySelector(".posts"); 6const filterBtns = document.querySelector(".tags-container"); 7const paginations = document.querySelector(".paginations"); 8 9let activeBtn = document.querySelector(".filter.active"); 10let tag = activeBtn.dataset.tag; 11let currentPage = 1; 12let displayPost; 13 14function setDisplayPost(tag) { 15 if (tag === "all") { 16 displayPost = blogPostsObject; 17 } else { 18 displayPost = blogPostsObject.filter((post) => { 19 return ( 20 post.tags === tag || 21 (Array.isArray(post.tags) && post.tags.includes(tag)) 22 ); 23 }); 24 } 25} 26 27function renderPosts(postsArray, currentPage) { 28 const pageLimit = 9; 29 // Clear the container first 30 postsContainer.innerHTML = ""; 31 32 // Error handling: Display a message if no posts are available 33 if (postsArray.length === 0) { 34 postsContainer.innerHTML = "<p>No posts available</p>"; 35 createPaginationLinks(postsArray); // Still update pagination to show no pages 36 return; 37 } 38 39 // Loop through the postsArray and create the HTML for each post 40 postsArray 41 .slice((currentPage - 1) * pageLimit, currentPage * pageLimit) 42 .forEach((post) => { 43 // Create the HTML structure using template literals 44 const postElement = ` 45 <a href="/posts/${kebabCase( 46 post.title 47 )}" class="text-decoration-none text-reset mb-3"> 48 <div> 49 <div class="d-flex flex-column gap-2"> 50 <div> 51 <img 52 src="${post.image}" 53 class="img-fluid placeholder rounded-4" 54 alt="" 55 /> 56 </div> 57 <div> 58 <h5 class="text-rfs-24">${post.title}</h5> 59 <p style="max-width: 350px" class="text-rfs-20 font-primary-400"> 60 ${ 61 post.subtitle.length > 100 62 ? post.subtitle.substring(0, 100) + "..." 63 : post.subtitle 64 } 65 </p> 66 </div> 67 </div> 68 </div> 69 </a> 70 `; 71 72 // Append the generated post element to the container 73 postsContainer.innerHTML += postElement; 74 }); 75 createPaginationLinks(postsArray); 76} 77 78function createPaginationLinks(postArray) { 79 let paginationHtml = ""; 80 paginations.innerHTML = ""; 81 paginationHtml += ` 82 <li class="page-item item"> 83 <button class="page-link prev" ${ 84 currentPage === 1 ? "disabled" : "" 85 }>Previous</button> 86 </li> 87 `; 88 if (postArray.length < 9) { 89 paginationHtml += ` 90 <li class="page-item item active"> 91 <a class="page-link" href="#" data-page="1">1</a> 92 </li> 93 `; 94 } else { 95 let totalNumberOfPages = Math.ceil(postArray.length / 9); 96 for (let i = 1; i <= totalNumberOfPages; i++) { 97 paginationHtml += ` 98 <li class="page-item item ${currentPage === i ? "active" : ""}"> 99 <a class="page-link" href="#" data-page="${i}">${i}</a> 100 </li> 101 `; 102 } 103 paginationHtml += ` 104 <li class="page-item item "> 105 <button class="page-link next" ${ 106 currentPage === totalNumberOfPages ? "disabled" : "" 107 }>Next</button> 108 </li> 109 `; 110 } 111 112 paginations.innerHTML = paginationHtml; 113} 114 115filterBtns.addEventListener("click", (event) => { 116 if (event.target.matches("button")) { 117 const change = activeBtn === event.target; 118 if (!change) { 119 activeBtn.classList.remove("active"); 120 event.target.classList.add("active"); 121 activeBtn = event.target; 122 tag = event.target.dataset.tag; 123 setDisplayPost(tag); 124 currentPage = 1; 125 renderPosts(displayPost, currentPage); 126 } 127 } 128}); 129 130paginations.addEventListener("click", (e) => { 131 if (e.target.matches("a")) { 132 e.preventDefault(); 133 currentPage = parseInt(e.target.dataset.page); 134 createPaginationLinks(displayPost); 135 renderPosts(displayPost, currentPage); 136 } else if (e.target.matches(".prev")) { 137 currentPage -= 1; 138 createPaginationLinks(displayPost); 139 renderPosts(displayPost, currentPage); 140 } else if (e.target.matches(".next")) { 141 currentPage += 1; 142 createPaginationLinks(displayPost); 143 renderPosts(displayPost, currentPage); 144 } 145}); 146
147setDisplayPost(tag); 148renderPosts(displayPost, currentPage);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.