DesignerLeo Posted July 17 Share Posted July 17 (edited) Hi, I am trying to add carousel controls, just as they are on individual product pages, onto the image previews of products inside shop categories. So that as you browse products, you can also preview all the individual images without actually going into the product page. Ideally it would be done with JS and maybe some CSS. I was able to identify the carousel controls class, on product page, as "ProductItem-gallery-carousel-controls" However, document.getElementsByClassName('ProductItem-gallery-carousel-controls')[0]; Returns only a valid element if they are already present. How do i create this exact element, or rather clone it (from where?), without it actually being loaded? Thanks, Leo. P.S. In case you are interested https://www.polivantage.com/shop/ <- thats where the carousel controls should go on every image (and subcategories) https://www.polivantage.com/shop/p/cloudy-zip-hoodie <- thats where i can identify the arrows (example product) Edited July 17 by Polivantage Link to comment
Solution DesignerLeo Posted July 18 Author Solution Share Posted July 18 (edited) here is the solution: (replace exampleProductUrl with a product page that has at least 2 images - in my case it is https://www.polivantage.com/shop/p/infinity but yours would be custom to your site) <!--Add Product image arrows in shop categories--> <script> document.addEventListener('DOMContentLoaded', function() { const subString = 'shop'; const subStringTwo = 'shop/p/'; const getURL = window.location.href; const exampleProductUrl = "https://www.polivantage.com/shop/p/infinity"; if (getURL.includes(subString) && !getURL.includes(subStringTwo)) { const headerActions = document.querySelector('.header-actions'); let isTouch = false; function checkHeader() { const styles = window.getComputedStyle(headerActions); isTouch = styles.getPropertyValue('display') !== 'flex'; } function fetchAndCacheProductHtml(url) { if (!isTouch) { const cachedHtml = localStorage.getItem('cachedProductHtml'); if (cachedHtml) { cloneImageArrows(cachedHtml); } else { fetch(url) .then(response => response.text()) .then(html => { localStorage.setItem('cachedProductHtml', html); cloneImageArrows(html); }) .catch(error => { console.error('Error fetching product HTML:', error); }); } } else { fetch(url) .then(response => response.text()) .then(html => { cloneImageArrows(html); }) .catch(error => { console.error('Error fetching product HTML:', error); }); } } function cloneImageArrows(html) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = html; const elementToClone = tempDiv.querySelector('.ProductItem-gallery-carousel-controls'); const products = document.querySelectorAll('.product-lists-item'); products.forEach((product, index) => { const allImages = product.querySelectorAll('.grid-item-image'); if (allImages.length >= 2) { const clonedElement = elementToClone.cloneNode(true); const productImage = product.querySelector('.grid-image'); productImage.prepend(clonedElement); clonedElement.id = `carousel${index + 1}`; clonedElement.classList.add('carousel', 'categoryArrows'); const leftArrow = clonedElement.querySelector('.ProductItem-gallery-prev'); const rightArrow = clonedElement.querySelector('.ProductItem-gallery-next'); leftArrow.classList.add('arrowButton', 'arrowPrev'); rightArrow.classList.add('arrowButton', 'arrowNext'); leftArrow.type = 'button'; rightArrow.type = 'button'; function adjustImageArrows() { if (!isTouch) { leftArrow.style.position = 'absolute'; leftArrow.style.left = '-14%'; leftArrow.style.transform = 'scale(0.333)'; rightArrow.style.position = 'absolute'; rightArrow.style.right = '-14%'; rightArrow.style.transform = 'scale(0.333)'; } else { leftArrow.style.position = 'absolute'; leftArrow.style.left = '0%'; leftArrow.style.transform = 'scale(1.2)'; rightArrow.style.position = 'absolute'; rightArrow.style.right = '0%'; rightArrow.style.transform = 'scale(1.2)'; } } adjustImageArrows(); productImage.addEventListener('click', function(event) { const clickedArrow = event.target.closest('.arrowButton'); if (!clickedArrow) return; event.preventDefault(); const direction = clickedArrow.classList.contains('arrowPrev') ? 'left' : 'right'; handleArrowClick(direction, allImages); }); function handleArrowClick(direction, images) { const imagesArray = Array.from(images); const currentImage = imagesArray.find(image => image.style.display === 'block' || image.style.opacity === '1'); let currentIndex = imagesArray.indexOf(currentImage); let newIndex; if (direction === 'left') { newIndex = currentIndex > 0 ? currentIndex - 1 : imagesArray.length - 1; } else { newIndex = currentIndex < imagesArray.length - 1 ? currentIndex + 1 : 0; } currentImage.style.display = 'none'; //currentImage.style.opacity = '0'; currentImage.classList.remove('active'); imagesArray[newIndex].style.display = 'block'; //imagesArray[newIndex].style.opacity = '1'; imagesArray[newIndex].classList.remove('grid-image-hover'); imagesArray[newIndex].classList.add('active'); } window.addEventListener('resize', function(event) { const prevIsTouch = isTouch; checkHeader(); if (isTouch !== prevIsTouch) { adjustImageArrows(); } }); } }); } checkHeader(); fetchAndCacheProductHtml(exampleProductUrl); } }); </script> and some css: .carousel { z-index: 9999; position: absolute; width: 100%; height: 100%; display: flex; align-items: center; } .grid-item-image { color: transparent; transition: opacity 1s ease-in-out !important; } .grid-item-image.active { opacity: 100% !important; } Edited July 18 by Polivantage tuanphan 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment