PageSourceSearch

https://cubbes.app/js/blog.js

js cubbes.app collected 2026-09-24 12:55:53 UTC 4,451 bytes, 148 lines download raw bytes

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.