diff --git a/layouts/partials/projects.html b/layouts/partials/projects.html
index b397713..74f5644 100644
--- a/layouts/partials/projects.html
+++ b/layouts/partials/projects.html
@@ -2,16 +2,31 @@
{{ T "projects" }}
{{ range .Site.Data.tags }}
-
+
+
{{ .title }}
+
{{ end }}
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/main.js b/static/main.js
index 034edb3..90ad4b6 100644
--- a/static/main.js
+++ b/static/main.js
@@ -110,6 +110,28 @@ function calculateAge(selector){
obj.textContent = age;
}
+// tag filtering
+document.querySelectorAll(".tag-checkbox").forEach(element => {
+ element.addEventListener("change", function(){
+ showSelectedProjects(element.value, element.checked);
+ });
+});
+
+function showSelectedProjects(category, show = true){
+ if(category){
+ document.querySelectorAll(`.${category}`).forEach(project => {
+ project.classList.toggle("hidden", !show);
+ });
+ }
+ else{
+ console.error("func showSelectedProjects(): Missing category name.");
+ }
+}
+
+function isCategoryEnabled(category){
+ return document.querySelector(`#tag-${category}`).checked;
+}
+
// load projects from api
// content api: https://api.michivonah.ch/?limit=8&page=1
async function loadContent(endpoint = "https://api.michivonah.ch", limit = 6, page = 1){
@@ -151,18 +173,24 @@ async function getProjectCard(data){
year: "numeric"
});
+ const link = document.createElement("a");
+ link.href = url;
+ link.title = title;
+ link.alt = title;
+
const container = document.createElement("div");
container.classList = "project-card fade-up";
container.classList.add(category);
+ if(!isCategoryEnabled(category)) container.classList.add("hidden");
//container.style.animation = "fade-up var(--baseDuration) linear";
//container.style.backgroundImage = `url(${image})`;
const cardFirst = document.createElement("div");
cardFirst.classList = "card-first";
- const emptyText = document.createElement("p");
- cardFirst.appendChild(emptyText);
const cardImage = document.createElement("img");
cardImage.src = image;
+ cardImage.alt = title;
+ cardImage.title = title;
cardFirst.appendChild(cardImage);
const cardSecond = document.createElement("div");
@@ -177,8 +205,9 @@ async function getProjectCard(data){
cardSecond.appendChild(cardTitle);
cardSecond.appendChild(cardDate);
- container.appendChild(cardFirst);
- container.appendChild(cardSecond);
+ link.appendChild(cardFirst);
+ link.appendChild(cardSecond);
+ container.appendChild(link);
return container;
}
@@ -186,18 +215,20 @@ async function getProjectCard(data){
async function loadMoreContent(wrapperSelector, amount, endpoint = "https://api.michivonah.ch", btnSelector = ".project-load-btn"){
const wrapper = document.querySelector(wrapperSelector);
const page = ((wrapper.childElementCount <= 0) ? 1 : (wrapper.childElementCount / amount) + 1);
+ const loader = document.querySelector('.project-loader-wrapper');
// just for debugging purposes
//console.log(`children: ${wrapper.childElementCount} limit: ${amount} page: ${page}`);
// error validation -> only load more content when page num is valid
if (page % 1 == 0){
+ loader.classList.remove('hidden');
await showProjects('.project-list', await loadContent(endpoint, amount, page));
+ loader.classList.add('hidden');
}
else{
// hide button if no more content is available
- //if (event.target.tagName == "BUTTON") event.target.style.display = "none";
- document.querySelector(btnSelector).style.opacity = 0;
+ document.querySelector(btnSelector).classList.add('hidden');
}
}
\ No newline at end of file
diff --git a/static/style.css b/static/style.css
index 52aab92..0ab32c8 100644
--- a/static/style.css
+++ b/static/style.css
@@ -385,6 +385,7 @@ nav.small .nav-links a:last-child:focus{
border-radius: var(--baseRadius);
transition: var(--baseTransition);
border: 2px solid var(--primary);
+ cursor: pointer;
}
.tag input{
@@ -424,6 +425,10 @@ nav.small .nav-links a:last-child:focus{
opacity: 1;
}
+.project-load-btn.hidden{
+ opacity: 0;
+}
+
.project-load-btn:hover{
padding: 10px 40px;
background: var(--secondary);
@@ -431,6 +436,27 @@ nav.small .nav-links a:last-child:focus{
cursor: pointer;
}
+.no-projects{
+ font-size: 1.8rem;
+ font-weight: 600;
+ display: none;
+}
+
+.no-projects i{
+ font-size: 3rem;
+}
+
+/* show no projects message, when no project exists that isn't hidden and loader is hidden */
+.project-list:not(:has(.project-card:not(.hidden))) + .no-projects:not(:has(+ .project-loader-wrapper:not(.hidden))){
+ display: block;
+}
+
+/* hide load more btn when no projects are shown */
+.project-list:not(:has(.project-card:not(.hidden))) ~ .project-load .project-load-btn{
+ display: none;
+}
+
+
/* Card animation: https://uiverse.io/suleymanlaarabidev/perfect-husky-88 */
.project-card{
width: 30%;
@@ -456,6 +482,16 @@ nav.small .nav-links a:last-child:focus{
--fontWeightP: 600;
}
+.project-card a{
+ color: inherit;
+ text-decoration: none;
+ font-style: inherit;
+}
+
+.project-card.hidden{
+ display: none;
+}
+
.card-first img{
position: absolute;
top: 50%;
@@ -571,6 +607,88 @@ nav.small .nav-links a:last-child:focus{
}
}
+/* PROJECTS LOADER */
+/* credits: https://uiverse.io/AbanoubMagdy1/evil-bullfrog-30 */
+.project-loader-wrapper{
+ width: 100%;
+ height: calc(var(--size) * 2);
+ margin: 0 0 var(--size) 0;
+ display: flex;
+ justify-content: center;
+ align-content: center;
+ align-items: center;
+
+ --size: 2.5rem;
+ --factor: 2.5;
+ --duration: 2s;
+}
+
+.project-loader-wrapper.hidden{
+ display: none;
+}
+
+.project-loader{
+ width: var(--size);
+ height: var(--size);
+ position: relative;
+ animation: circleLoader var(--duration) linear infinite;
+}
+
+.project-loader-circle{
+ width: calc(var(--size) / var(--factor));
+ height: calc(var(--size) / var(--factor));
+ background: var(--primary);
+ border-radius: 50%;
+ position: absolute;
+}
+
+.project-loader-circle:nth-child(1){
+ top: 0;
+ left: 0;
+}
+
+.project-loader-circle:nth-child(2){
+ top: 0;
+ right: 0;
+}
+
+.project-loader-circle:nth-child(3){
+ bottom: 0;
+ left: 0;
+}
+
+.project-loader-circle:nth-child(4){
+ bottom: 0;
+ right: 0;
+}
+
+@keyframes circleLoader{
+ 0%{
+ scale: 1;
+ rotate: 0deg;
+ }
+
+ 20%, 25%{
+ scale: 1.3;
+ rotate: 90deg;
+ }
+
+ 45%, 50%{
+ scale: 1;
+ rotate: 180deg;
+ }
+
+ 70%, 75%{
+ scale: 1.3;
+ rotate: 270deg;
+ }
+
+ 95%, 100%{
+ scale: 1;
+ rotate: 360deg;
+ }
+}
+
/* CONTACT */
.contact{
display: flex;