Jump to content

Add carousel controls for product preview in product category pages.

Go to solution Solved by DesignerLeo,

Recommended Posts

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 by Polivantage
Link to comment
  • Solution
Posted (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 by Polivantage
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

×
×
  • Create New...

Squarespace Webinars

Free online sessions where you’ll learn the basics and refine your Squarespace skills.

Hire a Designer

Stand out online with the help of an experienced designer or developer.