From fc1280428580e4747d69a00194509a1bba70c6e7 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Fri, 29 May 2026 12:04:54 +0200 Subject: [PATCH] fix(extra-features): Fixed the sync product image/gallery --- .../product-gallery/_product-thumbs.scss | 43 ++-- .../js/product/components/ProductGallery.js | 223 +++++++++++------- falcon/_dev/js/theme/index.js | 17 +- 3 files changed, 161 insertions(+), 122 deletions(-) diff --git a/falcon/_dev/css/product/components/product-gallery/_product-thumbs.scss b/falcon/_dev/css/product/components/product-gallery/_product-thumbs.scss index 216cde1..7553cb4 100644 --- a/falcon/_dev/css/product/components/product-gallery/_product-thumbs.scss +++ b/falcon/_dev/css/product/components/product-gallery/_product-thumbs.scss @@ -1,27 +1,34 @@ @use "sass:map"; .product-thumbs { - margin-right: -#{map.get($spacers, 1)}; - margin-left: -#{map.get($spacers, 1)}; + margin-right: -#{map.get($spacers, 1)}; + margin-left: -#{map.get($spacers, 1)}; - &__elem { - padding: 0 map.get($spacers, 1); - cursor: pointer; - opacity: .3; - transition: .3s ease opacity; - @include make-col(4); - - &:focus, - &:hover { - opacity: 0.6; + &.swiper-vertical { + max-height: 600px; + } + &.swiper-horizontal { + max-height: 200px; } - &.swiper-slide-thumb-active { - opacity: 1; - } + &__elem { + padding: 0 map.get($spacers, 1); + cursor: pointer; + opacity: 0.3; + transition: 0.3s ease opacity; + @include make-col(4); - @include media-breakpoint-up(sm) { - @include make-col(3); + &:focus, + &:hover { + opacity: 0.6; + } + + &.swiper-slide-thumb-active { + opacity: 1; + } + + @include media-breakpoint-up(sm) { + @include make-col(3); + } } - } } diff --git a/falcon/_dev/js/product/components/ProductGallery.js b/falcon/_dev/js/product/components/ProductGallery.js index 61f50b0..cade7de 100644 --- a/falcon/_dev/js/product/components/ProductGallery.js +++ b/falcon/_dev/js/product/components/ProductGallery.js @@ -1,101 +1,148 @@ class ProductGallery { - constructor({ - thumbsSliderSelector = '.js-product-thumbs', - mainSliderSelector = '.js-product-main-images', - modalSliderSelector = '.js-modal-gallery', - galleryModalSelector = '.js-product-images-modal', - } = {}) { - this.thumbsSliderSelector = thumbsSliderSelector; - this.mainSliderSelector = mainSliderSelector; - this.modalSliderSelector = modalSliderSelector; - this.galleryModalSelector = galleryModalSelector; - this.mainSliderSwiperInstance = null; - this.modalSliderSwiperInstance = null; - } - - init() { - this.mainSliderSwiperInstance = null; - this.modalSliderSwiperInstance = null; - this.initProductImageSlider(); - this.initModalGallerySlider(); - } - - async initProductImageSlider() { - const thumbsElem = document.querySelector(this.thumbsSliderSelector); - const galleryTopElem = document.querySelector(this.mainSliderSelector); - - if (!thumbsElem && !galleryTopElem) { - return; + constructor({ + thumbsSliderSelector = ".js-product-thumbs", + mainSliderSelector = ".js-product-main-images", + modalSliderSelector = ".js-modal-gallery", + galleryModalSelector = ".js-product-images-modal", + } = {}) { + this.thumbsSliderSelector = thumbsSliderSelector; + this.mainSliderSelector = mainSliderSelector; + this.modalSliderSelector = modalSliderSelector; + this.galleryModalSelector = galleryModalSelector; + this.mainSliderSwiperInstance = null; + this.modalSliderSwiperInstance = null; } - const galleryThumbs = new prestashop.SwiperSlider(thumbsElem, { - breakpoints: { - 320: { - slidesPerView: 3, - }, - 576: { - slidesPerView: 4, - }, - }, - watchSlidesVisibility: true, - watchSlidesProgress: true, - }); - - const galleryThumbsInstance = await galleryThumbs.initSlider(); - - const mainSlider = new prestashop.SwiperSlider(galleryTopElem, { - spaceBetween: 10, - navigation: { - nextEl: galleryTopElem.querySelector('.swiper-button-next'), - prevEl: galleryTopElem.querySelector('.swiper-button-prev'), - }, - thumbs: { - swiper: galleryThumbsInstance, - }, - }); - - const mainSliderInstance = await mainSlider.initSlider(); - - this.mainSliderSwiperInstance = mainSliderInstance; - } - - initModalGallerySlider() { - const gallerySliderElem = document.querySelector(this.modalSliderSelector); - - if (!gallerySliderElem) { - return; + init() { + this.mainSliderSwiperInstance = null; + this.modalSliderSwiperInstance = null; + this.initProductImageSlider(); + this.initModalGallerySlider(); } - const handleModalOpen = async () => { - if (this.modalSliderSwiperInstance) { - gallerySliderElem.style.opacity = 0; + syncThumbsHeight() { + const mainImages = document.querySelector(".product-main-images"); + const thumbs = document.querySelector(this.thumbsSliderSelector); + if (!mainImages || !thumbs) return; - // DIRTY HACK - setTimeout(() => { - this.modalSliderSwiperInstance.update(); - this.modalSliderSwiperInstance.slideTo(this.mainSliderSwiperInstance ? this.mainSliderSwiperInstance.activeIndex : 0, 0); - gallerySliderElem.style.opacity = 1; - }, 200); - } else { - const modalSlider = new prestashop.SwiperSlider(gallerySliderElem, { - slidesPerView: 1, - spaceBetween: 10, - initialSlide: this.mainSliderSwiperInstance ? this.mainSliderSwiperInstance.activeIndex : 0, - navigation: { - nextEl: gallerySliderElem.querySelector('.swiper-button-next'), - prevEl: gallerySliderElem.querySelector('.swiper-button-prev'), - }, + if (thumbs.classList.contains("swiper-vertical")) { + const h = mainImages.offsetHeight; + if (h > 0) { + thumbs.style.height = h + "px"; + } + } else { + thumbs.style.height = ""; + } + } + + async initProductImageSlider() { + const thumbsElem = document.querySelector(this.thumbsSliderSelector); + const galleryTopElem = document.querySelector(this.mainSliderSelector); + + if (!thumbsElem && !galleryTopElem) { + return; + } + + const galleryThumbs = new prestashop.SwiperSlider(thumbsElem, { + direction: "horizontal", // default + breakpoints: { + 0: { + direction: "horizontal", + slidesPerView: 3, + }, + 768: { + direction: "vertical", + slidesPerView: 5, + }, + 992: { + direction: "horizontal", + slidesPerView: 3, + }, + 1200: { + direction: "vertical", + slidesPerView: 5, + }, + }, + watchSlidesVisibility: true, + watchSlidesProgress: true, + spaceBetween: 10, }); - const modalSliderInstance = await modalSlider.initSlider(); + const galleryThumbsInstance = await galleryThumbs.initSlider(); - this.modalSliderSwiperInstance = modalSliderInstance; - } - }; + galleryThumbsInstance.on("resize", () => this.syncThumbsHeight()); + galleryThumbsInstance.on("breakpoint", () => this.syncThumbsHeight()); - // TO REFACTO LATER WITH BS5 REMOVE JQUERY! - $(this.galleryModalSelector).on('show.bs.modal', handleModalOpen); - } + const mainSlider = new prestashop.SwiperSlider(galleryTopElem, { + spaceBetween: 10, + navigation: { + nextEl: galleryTopElem.querySelector(".swiper-button-next"), + prevEl: galleryTopElem.querySelector(".swiper-button-prev"), + }, + thumbs: { + swiper: galleryThumbsInstance, + }, + }); + + const mainSliderInstance = await mainSlider.initSlider(); + + this.mainSliderSwiperInstance = mainSliderInstance; + this.syncThumbsHeight(); + } + + initModalGallerySlider() { + const gallerySliderElem = document.querySelector( + this.modalSliderSelector, + ); + + if (!gallerySliderElem) { + return; + } + + const handleModalOpen = async () => { + if (this.modalSliderSwiperInstance) { + gallerySliderElem.style.opacity = 0; + + // DIRTY HACK + setTimeout(() => { + this.modalSliderSwiperInstance.update(); + this.modalSliderSwiperInstance.slideTo( + this.mainSliderSwiperInstance + ? this.mainSliderSwiperInstance.activeIndex + : 0, + 0, + ); + gallerySliderElem.style.opacity = 1; + }, 200); + } else { + const modalSlider = new prestashop.SwiperSlider( + gallerySliderElem, + { + slidesPerView: 1, + spaceBetween: 10, + initialSlide: this.mainSliderSwiperInstance + ? this.mainSliderSwiperInstance.activeIndex + : 0, + navigation: { + nextEl: gallerySliderElem.querySelector( + ".swiper-button-next", + ), + prevEl: gallerySliderElem.querySelector( + ".swiper-button-prev", + ), + }, + }, + ); + + const modalSliderInstance = await modalSlider.initSlider(); + + this.modalSliderSwiperInstance = modalSliderInstance; + } + }; + + // TO REFACTO LATER WITH BS5 REMOVE JQUERY! + $(this.galleryModalSelector).on("show.bs.modal", handleModalOpen); + } } export default ProductGallery; diff --git a/falcon/_dev/js/theme/index.js b/falcon/_dev/js/theme/index.js index 5cd4d84..a1319c9 100644 --- a/falcon/_dev/js/theme/index.js +++ b/falcon/_dev/js/theme/index.js @@ -13,6 +13,7 @@ import "@js/theme/components/quickview"; import "@js/theme/components/product"; import "@js/theme/components/cart/cart"; import "@js/theme/components/cart/block-cart"; +import "@js/theme/components/product-miniature-form.js"; import usePasswordPolicy from "@js/theme/components/usePasswordPolicy"; import prestashop from "prestashop"; @@ -66,22 +67,6 @@ function initStickyHeader() { } } -// Sync product thumbs height with main images height -function syncThumbsHeight() { - const mainImages = document.querySelector(".product-main-images"); - const thumbs = document.querySelector(".product-thumbs.swiper"); - // Only apply if Swiper is vertical - if (mainImages && thumbs && thumbs.classList.contains("swiper-vertical")) { - thumbs.style.maxHeight = mainImages.offsetHeight + "px"; - thumbs.style.height = mainImages.offsetHeight + "px"; - } else { - return; - } -} - -window.addEventListener("load", syncThumbsHeight); -window.addEventListener("resize", syncThumbsHeight); - $(() => { initStickyHeader(); accLinksTriggerActive();