From 412c2a554718a5e7c6210590528d4a54011bccc6 Mon Sep 17 00:00:00 2001 From: Camilledenoray Date: Thu, 11 Jun 2026 18:40:52 +0200 Subject: [PATCH] Index > JS > add arrow key navigation + go to prev/next project after/before first/last picture --- assets/js/project-slideshow.js | 151 +++++++++++++++++++++++++++------ assets/js/project-toggle.js | 4 + 2 files changed, 131 insertions(+), 24 deletions(-) diff --git a/assets/js/project-slideshow.js b/assets/js/project-slideshow.js index 65420db..0996b3b 100644 --- a/assets/js/project-slideshow.js +++ b/assets/js/project-slideshow.js @@ -1,34 +1,137 @@ document.addEventListener("DOMContentLoaded", () => { + // Éléments statiques : calculés une seule fois au chargement const prevButtons = document.querySelectorAll("button.prev"); const nextButtons = document.querySelectorAll("button.next"); - nextButtons.forEach((nextButton) => { - nextButton.addEventListener("click", () => { - const activePicture = nextButton - .closest(".project-slideshow") - .querySelector("picture.active"); - const targetPicture = - activePicture.nextElementSibling && - activePicture.nextElementSibling.tagName === "PICTURE" - ? activePicture.nextElementSibling - : nextButton.closest(".project-slideshow").querySelector("picture"); + const projects = document.querySelectorAll(".projects-index .project"); + const firstProject = projects[0]; + const lastProject = projects[projects.length - 1]; + + const firstPictureFirstProject = firstProject.querySelector( + ".project-slideshow picture:first-of-type", + ); + const firstPictureLastProject = lastProject.querySelector( + ".project-slideshow picture:first-of-type", + ); + const lastPictureLastProject = lastProject.querySelector( + ".project-slideshow picture:last-of-type", + ); + + // Fonctions de navigation : les éléments « courants » sont re-requêtés + // à chaque appel pour refléter l'état actuel du DOM. + + function goToNextPicture() { + const activePicture = document.querySelector( + ".project.selected .project-slideshow > picture.active", + ); + const lastPicture = document.querySelector( + ".project.selected .project-slideshow > picture:last-of-type", + ); + const selectedProject = document.querySelector(".project.selected"); + const nextProject = selectedProject.nextElementSibling; + const firstPictureNextProject = nextProject?.querySelector( + ".project-slideshow picture:first-of-type", + ); + + if (activePicture !== lastPicture) { activePicture.classList.remove("active"); - targetPicture.classList.add("active"); - }); + activePicture.nextElementSibling.classList.add("active"); + } else { + selectedProject.classList.remove("selected"); + activePicture.classList.remove("active"); + if (selectedProject !== lastProject) { + nextProject.classList.add("selected"); + firstPictureNextProject.classList.add("active"); + } else { + firstProject.classList.add("selected"); + firstPictureFirstProject.classList.add("active"); + } + } + } + + function goToPrevPicture() { + const activePicture = document.querySelector( + ".project.selected .project-slideshow > picture.active", + ); + const firstPicture = document.querySelector( + ".project.selected .project-slideshow > picture:first-of-type", + ); + const selectedProject = document.querySelector(".project.selected"); + const prevProject = selectedProject.previousElementSibling; + const lastPicturePrevProject = prevProject?.querySelector( + ".project-slideshow picture:last-of-type", + ); + + if (activePicture !== firstPicture) { + activePicture.classList.remove("active"); + activePicture.previousElementSibling.classList.add("active"); + } else { + selectedProject.classList.remove("selected"); + activePicture.classList.remove("active"); + if (selectedProject !== firstProject) { + prevProject.classList.add("selected"); + lastPicturePrevProject.classList.add("active"); + } else { + lastProject.classList.add("selected"); + lastPictureLastProject.classList.add("active"); + } + } + } + + function goToPrevProject() { + const activePicture = document.querySelector( + ".project.selected .project-slideshow > picture.active", + ); + const selectedProject = document.querySelector(".project.selected"); + const prevProject = selectedProject.previousElementSibling; + const firstPicturePrevProject = prevProject?.querySelector( + ".project-slideshow picture:first-of-type", + ); + + activePicture.classList.remove("active"); + selectedProject.classList.remove("selected"); + if (selectedProject !== firstProject) { + prevProject.classList.add("selected"); + firstPicturePrevProject.classList.add("active"); + } else { + lastProject.classList.add("selected"); + firstPictureLastProject.classList.add("active"); + } + } + + function goToNextProject() { + const activePicture = document.querySelector( + ".project.selected .project-slideshow > picture.active", + ); + const selectedProject = document.querySelector(".project.selected"); + const nextProject = selectedProject.nextElementSibling; + const firstPictureNextProject = nextProject?.querySelector( + ".project-slideshow picture:first-of-type", + ); + + activePicture.classList.remove("active"); + selectedProject.classList.remove("selected"); + if (selectedProject !== lastProject) { + nextProject.classList.add("selected"); + firstPictureNextProject.classList.add("active"); + } else { + firstProject.classList.add("selected"); + firstPictureFirstProject.classList.add("active"); + } + } + + nextButtons.forEach((nextButton) => { + nextButton.addEventListener("click", goToNextPicture); }); prevButtons.forEach((prevButton) => { - prevButton.addEventListener("click", () => { - const slideshow = prevButton.closest(".project-slideshow"); - const activePicture = slideshow.querySelector("picture.active"); - const pictures = [...slideshow.querySelectorAll("picture")]; - const targetPicture = - activePicture.previousElementSibling && - activePicture.previousElementSibling.tagName === "PICTURE" - ? activePicture.previousElementSibling - : pictures[pictures.length - 1]; - activePicture.classList.remove("active"); - targetPicture.classList.add("active"); - }); + prevButton.addEventListener("click", goToPrevPicture); + }); + + document.addEventListener("keyup", (event) => { + if (event.key === "ArrowRight") goToNextPicture(); + if (event.key === "ArrowLeft") goToPrevPicture(); + if (event.key === "ArrowUp") goToPrevProject(); + if (event.key === "ArrowDown") goToNextProject(); }); }); diff --git a/assets/js/project-toggle.js b/assets/js/project-toggle.js index 71ad426..cf1669b 100644 --- a/assets/js/project-toggle.js +++ b/assets/js/project-toggle.js @@ -21,6 +21,10 @@ allProjects.forEach((currentProject) => { } }); + currentProject + .querySelectorAll("picture") + .forEach((picture) => picture.classList.remove("active")); + currentProject.querySelector("picture:first-child").classList.add("active"); currentProject.classList.toggle("selected"); Router.setParam("project", currentProject.dataset.slug);