Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ <h1>Animation Nation</h1>
<p id="stats"></p>
</div>

<div class="search-container">
<input
type="text"
id="searchInput"
placeholder="Search by art name or author..."
/>
</div>

<div class="card-container">
<ul class="flex" id="cards">
<!-- Content is generated dynamically -->
Expand Down
180 changes: 83 additions & 97 deletions public/includes.js
Original file line number Diff line number Diff line change
@@ -1,107 +1,93 @@
// Load the cards.json file using Fetch API
fetch('./public/cards.json')
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // Parse the JSON file content
})
.then((cards) => {
/* Shuffles cards' order */
function shuffle(o) {
for (
let j, x, i = o.length;
i;
j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x
);
return o;
}

/** Creates cards from the array above */
const getCardContents = (cardList) => {
return shuffle(cardList).map((c) => [
`<li class="card">` +
`<a href='${c.pageLink}'>` +
`<img class="art-image" src='${c.imageLink}' alt='${c.artName}' />` +
`</a>` +
`<a class="art-title" href='${c.pageLink}'><h3 >${c.artName}</h3></a>` +
`<p class='author'><a href="${c.githubLink}" target="_blank"><i class="fab fa-github"></i> ${c.author}</a> </p>` +
`</li>`
]);
};

/* Injects cards list HTML into the DOM */
let contents = getCardContents(cards);
document.getElementById('cards').innerHTML = contents;
document.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("searchInput");
const cardsContainer = document.getElementById("cards");
const statsElement = document.getElementById("stats");
const goToTopBtn = document.querySelector(".go-to-top");

/* Adds scroll to top arrow button */
window.onscroll = function () {
if (window.scrollY > 100) {
goToTopBtn.classList.add('active');
} else {
goToTopBtn.classList.remove('active');
}
};
let masterCardList = [];

// Adds the click event to the button
const goToTopBtn = document.querySelector('.go-to-top');
goToTopBtn.addEventListener('click', function () {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});

// Get element by id "stats" and set the innerHTML to the following
document.getElementById(
'stats'
).innerHTML = `Showcasing ${cards.length} artworks`;
})
.catch((error) => {
console.error('Error fetching the cards.json file:', error);
});

// 🎨 Hacktoberfest Card Data
const cardList = [
{
artName: "HACKTOBERFEST",
pageLink: "index.html",
imageLink: "hacktoberfest-logo.png",
author: "Takunda",
githubLink: "https://github.com/Enock12234"
function shuffle(o) {
const array = [...o];
for (
let j, x, i = array.length;
i;
j = parseInt(Math.random() * i), x = array[--i], (array[i] = array[j]), (array[j] = x)
);
return array;
}
];

// 🔀 Optional shuffle function (add if not defined)
function shuffle(array) {
return array.sort(() => 0.5 - Math.random());
}

// 🖼️ Generate HTML cards
const getCardContents = (cardList) => {
return shuffle(cardList)
.map((c) => `
const renderCards = (cardsToRender) => {
if (cardsToRender.length === 0 && searchInput.value !== "") {
cardsContainer.innerHTML = '<p class="no-results">No artworks found.</p>';
return;
}
const html = cardsToRender
.map(
(card) => `
<li class="card">
<a href='${c.pageLink}'>
<img class="art-image" src='${c.imageLink}' alt='${c.artName}' />
</a>
<a class="art-title" href='${c.pageLink}'>
<h3>${c.artName}</h3>
<a href='${card.pageLink || "#"}'>
<img class="art-image" src='${card.imageLink || ""}' alt='${
card.artName || "Untitled"
}' />
</a>
<a class="art-title" href='${card.pageLink || "#"}'><h3>${
card.artName || "Untitled"
}</h3></a>
<p class='author'>
<a href="${c.githubLink}" target="_blank">
<i class="fab fa-github"></i> ${c.author}
</a>
<a href="${card.githubLink || "#"}" target="_blank">${
card.author || "Unknown"
}</a>
</p>
</li>
`)
.join('');
};
`
)
.join("");
cardsContainer.innerHTML = html;
};

// 🧩 Inject into the DOM
document.addEventListener('DOMContentLoaded', () => {
const container = document.getElementById("cardContainer");
if (container) {
container.innerHTML = getCardContents(cardList);
}
});
const handleSearch = () => {
const query = searchInput.value.toLowerCase().trim();

if (query === "") {
renderCards(shuffle(masterCardList));
return;
}

const filteredList = masterCardList.filter((card) => {
if (!card) return false;
const artName = (card.artName || "").toLowerCase();
const author = (card.author || "").toLowerCase();
return artName.includes(query) || author.includes(query);
});

renderCards(filteredList);
};

fetch("./public/cards.json")
.then((response) => response.json())
.then((data) => {
masterCardList = data.filter((card) => card);
statsElement.innerHTML = `Showcasing ${masterCardList.length} artworks`;

renderCards(shuffle(masterCardList));

searchInput.addEventListener("input", handleSearch);
})
.catch((error) => {
console.error("Error loading artworks:", error);
cardsContainer.innerHTML =
'<p class="no-results">Error: Could not load artworks.</p>';
});

window.onscroll = function () {
if (window.scrollY > 100) {
goToTopBtn.classList.add("active");
} else {
goToTopBtn.classList.remove("active");
}
};

goToTopBtn.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: "smooth" });
});
});
51 changes: 50 additions & 1 deletion public/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ ul {
}

.card-container {
padding-top: 50px;
padding-top: 120px;
}


Expand Down Expand Up @@ -229,4 +229,53 @@ ul {
/* Handles on scrollbar hover */
::-webkit-scrollbar-thumb:hover {
background: rgb(88, 194, 250);
}

.search-container {
position: fixed;
top: 120px;
left: 0;
right: 0;

z-index: 999;

padding: 15px 0;
background: #1a1a1ade;
border-bottom: 2px solid var(--main-20);

display: flex;
justify-content: center;
}

#searchInput {
width: 90%;
max-width: 400px;
padding: 12px;

border: 1px solid var(--main-40);
border-radius: 8px;
background-color: #2c2c2c;
color: #f1f1f1;
font-size: 1rem;
font-family: 'Comfortaa';

transition: border-color 0.3s, box-shadow 0.3s;
}

#searchInput:focus {
outline: none;
border-color: var(--main);
box-shadow: 0 0 8px var(--main-50);
}

#searchInput::placeholder {
color: #888;
}

.no-results {
color: #888;
font-size: 1.2rem;
width: 100%;
text-align: center;
padding: 50px 0;
}