Hi @StevenT_A7 ! Thanks so much for your reply!
I tried implementing your suggestion by wrapping my logic in activateColorSwatches() and calling it on both DOMContentLoaded and facet:updated.
Unfortunately, it still doesn’t work after applying a filter. The swatches only work on the first page load or if I manually refresh the filtered page.
I’m placing this code inside a custom .liquid file called card-product-variant-selection-custom.liquid, which controls the behavior of the product cards on collection pages. So the JavaScript is tied to how the swatches behave in the product grid, not on the product detail page.
I also added mouseenter and mouseleave events to trigger image changes on hover, but hover doesn’t work at all — neither before nor after filtering.
Here’s the full script I’m using:
function activateColorSwatches() {
console.log('[Vegayn] Activating swatches...');
document.querySelectorAll('.grid.product-grid').forEach(function(productGrid) {
var sectionId = productGrid.getAttribute('data-section-id');
var variantDataMap = window['variantDataMap' + sectionId.replace(/-/g, '_')];
if (!variantDataMap) return;
productGrid.querySelectorAll('input[type="radio"][data-section-id="' + sectionId + '"]').forEach(function(radio) {
const card = radio.closest(`.card-product-custom-div[data-section-id="${sectionId}"]`);
const variantId = radio.getAttribute('data-variant-id');
const variantData = variantDataMap[variantId];
if (!variantData || !card) return;
const productImageElement = card.querySelector('.card__media img');
if (!productImageElement) return;
// Click = change image permanently
radio.addEventListener('change', function () {
updateImage(productImageElement, variantData.imageUrl);
updateLinks(card, variantData.productUrl);
});
// Hover = temporary image change
radio.addEventListener('mouseenter', function () {
productImageElement.setAttribute('data-original-src', productImageElement.src);
productImageElement.setAttribute('data-original-srcset', productImageElement.srcset);
updateImage(productImageElement, variantData.imageUrl);
});
radio.addEventListener('mouseleave', function () {
const originalsrc=productImageElement.getAttribute('data-original-src');
const originalSrcset = productImageElement.getAttribute('data-original-srcset');
if (originalSrc && originalSrcset) {
productImageElement.src=originalSrc;
productImageElement.srcset = originalSrcset;
}
});
});
});
}
function updateImage(imgElement, imageUrl) {
const dynamicSrcset = [
imageUrl + '?width=165 165w',
imageUrl + '?width=360 360w',
imageUrl + '?width=533 533w',
imageUrl + '?width=720 720w',
imageUrl + '?width=940 940w',
imageUrl + '?width=1066 1066w'
].join(', ');
imgElement.srcset = dynamicSrcset;
imgElement.src=imageUrl;
}
function updateLinks(card, newUrl) {
card.querySelectorAll('a[id^="CardLink-"], a[id^="StandardCardNoMediaLink-"]').forEach(function(link) {
link.href = newUrl;
});
}
document.addEventListener('DOMContentLoaded', activateColorSwatches);
document.addEventListener('facet:updated', activateColorSwatches);
Is there a better event I should be listening for? Or a different approach you’d recommend when working inside a dynamically updated product grid?
Any insights would be super appreciated!
Thank you again!