Skip to content

Commit ce7a238

Browse files
committed
add color swatcher
1 parent bcaf7df commit ce7a238

File tree

1 file changed

+94
-44
lines changed

1 file changed

+94
-44
lines changed

view/frontend/templates/product/listing/renderer.phtml

Lines changed: 94 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ $product = $block->getProduct()
2525
"numberToShow" => json_decode($block->escapeJs($block->getNumberSwatchesPerProduct()), true),
2626
"jsonConfig"=> json_decode($block->getJsonConfig(), true),
2727
"jsonSwatchConfig"=> json_decode($block->getJsonSwatchConfig(), true),
28-
"mediaCallback" => json_decode($block->escapeJs($block->escapeUrl($block->getMediaCallback())), true),
28+
"mediaCallback" => $block->getMediaCallback(),
2929
"jsonSwatchImageSizeConfig" => json_decode($block->getJsonSwatchSizeConfig(), true),
3030
"showTooltip"=> json_decode($block->escapeJs($configurableViewModel->getShowSwatchTooltip()), true)];
3131

32-
$configurableImages = $swatchData["jsonConfig"]['images'];
32+
$configurableImages = $swatchData["jsonConfig"];
3333
$swatchConfig = $swatchData["jsonConfig"];
34-
$swatchAttributes = $swatchData["jsonSwatchConfig"];
34+
$swatchAttributes = $swatchData["jsonSwatchConfig"];
35+
$mediaUrl = $swatchData["mediaCallback"];
3536
?>
3637
<?php /*
3738
<script type="text/x-magento-init">
@@ -72,51 +73,75 @@ $configurableImagesData = [];
7273
foreach ($configurableImages as $productId => $images) {
7374
$configurableImagesData[$productId] = $images;
7475
}
75-
76+
$lockBlock = $block->getLayout()->getBlock('header');
77+
$lock = $lockBlock->getData('print') ?? false;
78+
if (!$lock) {
7679
?>
7780
<script>
7881
var confGallery = <?=json_encode($configurableImagesData)?>;
7982
var catImage = '<?=htmlspecialchars($catImage)?>';
8083

84+
// Local cache for swatch images
85+
var swatchImageCache = {};
86+
8187
// Function to load gallery images via AJAX
82-
function loadGalleryImages(productId) {
83-
if (confGallery[productId]) {
84-
const images = confGallery[productId];
85-
let galleryHtml = '<div class="gallery" id="product-gallery"><div class="m-img" id="m-img">';
86-
87-
// Find and add main image
88-
images.forEach(function(image) {
89-
if (image.isMain) {
90-
galleryHtml += '<img src="' + image.img + '" src-full="' + image.full + '" alt="' + image.caption + '" id="mImg" width="700px" height="700px">';
91-
}
92-
});
93-
94-
galleryHtml += '</div><div class="thmb">';
95-
96-
// Add thumbnails
97-
images.forEach(function(image) {
98-
galleryHtml += '<img src="' + image.thumb + '" loading="lazy" src-full="' + image.full + '" alt="' + image.caption + '" class="thumb" onclick="document.getElementById(\'mImg\').src=\'' + image.img + '\'; document.getElementById(\'mImg\').setAttribute(\'src-full\', \'' + image.full + '\');">';
99-
});
100-
101-
galleryHtml += '</div></div>';
102-
103-
// Update the gallery container
104-
const galleryContainer = document.querySelector('.gallery-container');
105-
if (galleryContainer) {
106-
galleryContainer.innerHTML = galleryHtml;
107-
}
108-
}
88+
function loadSwatchImages(variantProductId) {
89+
var mediaUrl = "<?= $mediaUrl ?>?product_id=" + variantProductId + "&isAjax=true";
90+
91+
// Get the clicked swatch and find its product image
92+
var clickedSwatch = event.target;
93+
var productImage = clickedSwatch.closest('[id^="product-item-info_"]').querySelector('img.product-image-photo');
94+
95+
if (!productImage) {
96+
console.error('Product image not found');
97+
return;
98+
}
99+
100+
// Check if image is already cached
101+
if (swatchImageCache[variantProductId]) {
102+
// Apply loading effect for cached images too
103+
productImage.style.opacity = '0.6';
104+
productImage.src = swatchImageCache[variantProductId];
105+
setTimeout(() => {
106+
productImage.style.opacity = '1';
107+
}, 150);
108+
return;
109+
}
110+
111+
// Apply loading effect
112+
productImage.style.opacity = '0.6';
113+
productImage.style.transition = 'opacity 0.3s ease-in-out';
114+
115+
fetch(mediaUrl)
116+
.then(response => response.json())
117+
.then(data => {
118+
if (data && data.medium) {
119+
// Store in cache
120+
swatchImageCache[variantProductId] = data.medium;
121+
// Update image with fade effect
122+
productImage.src = data.medium;
123+
// Fade in the new image
124+
setTimeout(() => {
125+
productImage.style.opacity = '1';
126+
}, 100);
127+
}
128+
})
129+
.catch(error => {
130+
console.error('Error:', error);
131+
// Restore opacity on error
132+
productImage.style.opacity = '1';
133+
});
109134
}
110-
111-
// Load gallery if cat_image parameter is present
112-
if (catImage !== '') {
113-
loadGalleryImages(catImage);
135+
<?php
136+
$lockBlock->setData('print', true);
114137
}
138+
?>
139+
115140
</script>
116141

117142
<div class="swatch-opt" data-role="swatch-options"></div>
118143

119-
<a href="<?=$product->getProductUrl()?>">
144+
<!--<a href="<?=$product->getProductUrl()?>">-->
120145
<div class="product-options-wrapper" id="product-options-wrapper">
121146
<div class="fieldset" tabindex="0">
122147
<div class="swatch-opt" data-role="swatch-options" data-rendered="true">
@@ -134,18 +159,43 @@ if (catImage !== '') {
134159
<div class="swatch-attribute-options clearfix">
135160
<?php foreach ($swatchAttributes[$attributeId] as $optionId => $optionData): ?>
136161
<?php if (!is_array($optionData) || !isset($optionData['type'])) {
137-
continue;
138-
}
139-
?>
140-
141-
<div class="swatch-option <?=$optionData['type'] == 1 ? 'color' : 'text'?>"
162+
continue;
163+
}
164+
$swatchType = $optionData['type'] == 1 ? 'color' : 'text';
165+
if ($swatchType == 'text') : ?>
166+
<a href="<?=$product->getProductUrl()?>">
167+
<?php endif; ?>
168+
169+
<div class="swatch-option <?=$swatchType?>"
142170
data-option-type="<?=$escaper->escapeHtmlAttr($optionData['type'])?>"
143171
data-option-id="<?=$escaper->escapeHtmlAttr($optionId)?>"
144172
data-option-gallery-id="<?=$escaper->escapeHtmlAttr($optionToImage[$optionId])?>"
145173
data-option-label="<?=$escaper->escapeHtmlAttr($optionData['label'] ?? '')?>"
146-
style="<?=$optionData['type'] == 1 ? 'background:' . $escaper->escapeHtmlAttr($optionData['value']) . ' no-repeat center;' : ''?>">
147-
<?=$optionData['type'] == 0 ? $escaper->escapeHtml($optionData['value']) : ''?>
174+
<?php if ($swatchType == 'color'): ?>
175+
<?php
176+
$options = $swatchConfig['attributes'][$attributeId];
177+
178+
// Transpose options array to be indexed by option id
179+
$transposedOptions = [];
180+
if (isset($options['options']) && is_array($options['options'])) {
181+
foreach ($options['options'] as $option) {
182+
if (isset($option['id'])) {
183+
$transposedOptions[$option['id']] = $option;
184+
}
185+
}
186+
}
187+
188+
// Now $transposedOptions is indexed by option id
189+
// Example: $transposedOptions[57] contains all data for Purple option
190+
?>
191+
onclick="loadSwatchImages(<?=isset($transposedOptions[$optionId]['products'][0]) ? $transposedOptions[$optionId]['products'][0] : 'null'?>)"
192+
<?php endif;?>
193+
style="<?=$swatchType == 'color' ? 'background:' . $escaper->escapeHtmlAttr($optionData['value']) . ' no-repeat center;' : ''?>">
194+
<?=$swatchType == 'text' ? $escaper->escapeHtml($optionData['value']) : ''?>
148195
</div>
196+
<?php if ($swatchType == 'text'): ?>
197+
</a>
198+
<?php endif; ?>
149199
<?php endforeach; ?>
150200
</div>
151201
<input class="swatch-input super-attribute-select" name="super_attribute[<?=$attributeId?>]" type="text" value="" data-selector="super_attribute[<?=$attributeId?>]" data-validate="{required: true}" aria-required="true">
@@ -155,5 +205,5 @@ if (catImage !== '') {
155205
</div>
156206
</div>
157207
</div>
158-
</a>
208+
<!--</a>-->
159209

0 commit comments

Comments
 (0)