Сейчас узнаем, какой подарок выпадет именно Вам
Крутите колесо
Как добавить выбор цвета материала в карточке товара

Как добавить выбор цвета материала в карточке товара

1
Создали товар в каталоге:
  • добавили ему варианты товара, ключевое для нас свойство "Материал обивки" как на скрине 1
2
Создали для этого товара дополнительную опцию "Цвет обивки" (одиночный выбор) и заполнили её как скрине 2
3
Добавили на страницу блок TE200, задали ему класс uc-data-material и заполнили его как на скрине 3
4
Вставили код на страницу в блок Т123
Блок TE200 и блок с кодом должны присутствовать и в продуктовом футере тоже
Mo-ti Level Up
Видео инструкции по добавлению кода и работе с Zero Block.
Как добавить выбор цвета материала в карточке товара
Фрагмент видео
Библиотека для примера
 <script>
(function() {
    'use strict';
    
    const materialTitle = "Материал обивки";
    const materialColorTitle = "Цвет обивки";
    
    const qs = (sel, ctx = document) => ctx.querySelector(sel);
    const qa = (sel, ctx = document) => Array.from(ctx.querySelectorAll(sel));

    const normalize = (str) => (str || '').toString().trim().toLowerCase().replace(/\s+/g, ' ');

    function processCard(card, context = 'unknown') {
        if (card.dataset.materialProcessed) return;
        card.dataset.materialProcessed = 'true';

        const colorOption = qa('.js-product-option', card).find(opt => {
            const nameEl = qs('.js-product-option-name', opt);
            return nameEl && normalize(nameEl.textContent) === normalize(materialColorTitle);
        });

        if (!colorOption) {
            qa('.js-product-option', card).forEach(opt => opt.classList.add('show-option'));
            return;
        }

        const materialEdition = qs(`.js-product-edition-option[data-edition-option-id="${materialTitle}"]`, card);
        if (!materialEdition) {
            buildColorPicker(card, colorOption, null);
            return;
        }

        const materialSelect = qs('select', materialEdition);
        if (!materialSelect) {
            buildColorPicker(card, colorOption, null);
            return;
        }

        buildColorPicker(card, colorOption, materialSelect.value);

        materialSelect.addEventListener('change', function() {

            const existing = colorOption.querySelector('.uc-color-picker');
            if (existing) existing.remove();

            buildColorPicker(card, colorOption, this.value);
        });
    }

    function buildColorPicker(card, colorOption, materialValue) {

        let materialName = '';
        if (materialValue) {
            materialName = normalize(materialValue);
        }

        const dataBlocks = qa('.uc-data-material');
        if (dataBlocks.length === 0) return;

        const colorData = [];

        dataBlocks.forEach(dataBlock => {
            const dataCards = qa('.t-card__col', dataBlock);
            dataCards.forEach(dc => {
                const titleEl = qs('.t-card__title', dc);
                if (!titleEl) return;

                const titleText = normalize(titleEl.textContent);
                if (titleText !== materialName) return;

                const imgEl = qs('.t-bgimg', dc);
                const descrEl = qs('.t-card__descr', dc);

                colorData.push({
                    image: imgEl ? (imgEl.getAttribute('data-original') || imgEl.src || '') : '',
                    name: titleEl.textContent.trim(),
                    description: descrEl ? descrEl.textContent.trim() : ''
                });
            });
        });

        if (colorData.length === 0) return;

        const existing = colorOption.querySelector('.uc-color-picker');
        if (existing) existing.remove();

        const picker = document.createElement('div');
        picker.className = 'uc-color-picker';

        colorData.forEach((item, index) => {
            const imgWrap = document.createElement('div');
            imgWrap.className = 'uc-color-item' + (index === 0 ? ' active-color' : '');
            imgWrap.setAttribute('data-name', item.name);
            imgWrap.setAttribute('data-description', item.description);

            const img = document.createElement('img');
            img.src = item.image;
            img.alt = item.name+' '+item.description;
            img.title = item.name+' '+item.description;

            imgWrap.appendChild(img);
            picker.appendChild(imgWrap);
        });

        colorOption.appendChild(picker);

        const firstItem = colorData[0];
        const optionName = qs('.js-product-option-name', colorOption);
        const selectEl = qs('select', colorOption);

        if (optionName) {
            optionName.setAttribute('data-description', firstItem.description);
        }

        if (selectEl) {
            const firstOpt = selectEl.querySelector('option');
            if (firstOpt) {
                firstOpt.textContent = firstItem.description;
                firstOpt.value = firstItem.description;
            }
          
            selectEl.dispatchEvent(new Event('change', { bubbles: true }));
        }

        picker.addEventListener('click', function(e) {
            const item = e.target.closest('.uc-color-item');
            if (!item) return;

            qa('.uc-color-item', picker).forEach(el => el.classList.remove('active-color'));
            item.classList.add('active-color');

            const name = item.getAttribute('data-name');
            const description = item.getAttribute('data-description');

            if (optionName) {
                optionName.setAttribute('data-description', description);
            }

            if (selectEl) {
                const firstOpt = selectEl.querySelector('option');
                if (firstOpt) {
                    firstOpt.textContent = description;
                    firstOpt.value = description;
                }
                selectEl.dispatchEvent(new Event('change', { bubbles: true }));
            }
        });
    }

    function processGrid(container) {
        if (!container) return;
        const cards = qa('.t-catalog__card, .t-store__card, .js-product-relevant', container);
        cards.forEach(card => processCard(card, 'GRID'));
    }

   
    function processPopup() {
        const popup = qs('.t-popup.t-popup_show');
        if (!popup) return;

   
        const cards = qa('.t-catalog__card, .t-store__card, .js-product', popup);
        cards.forEach(card => {
            delete card.dataset.materialProcessed;
            processCard(card, 'POPUP');
        });
    }

   
    function processPopupRelevants() {
        const popup = qs('.t-popup.t-popup_show');
        if (!popup) return false;

        const containers = popup.querySelectorAll(
            '.t-store__relevants-grid-cont, .js-store-relevants-grid-cont, .t-catalog__relevants-grid-cont, .js-catalog-relevants-grid-cont'
        );
        if (containers.length === 0) return false;

        containers.forEach(container => {
            const cards = qa('.t-store__card, .t-catalog__card, .js-product-relevant', container);
            cards.forEach(card => {
                delete card.dataset.materialProcessed;
                processCard(card, 'POPUP RELEVANTS');
            });
        });

        return true;
    }

    function waitForPopupRelevants() {
        let attempts = 0;
        const maxAttempts = 15;
        const interval = 200;

        const check = () => {
            attempts++;
            if (processPopupRelevants()) return;
            if (attempts < maxAttempts) {
                setTimeout(check, interval);
            }
        };
        setTimeout(check, interval);
    }

   
    document.addEventListener('DOMContentLoaded', () => {
        qa('.js-catalog-grid-cont, .js-store-grid-cont').forEach(grid => {
            grid.addEventListener('tStoreRendered', () => processGrid(grid));
        });

        qa('.t-catalog__relevants-grid-cont, .js-catalog-relevants-grid-cont, .t-store__relevants-grid-cont, .js-store-relevants-grid-cont').forEach(grid => {
            grid.addEventListener('tStoreRendered', () => processGrid(grid));
        });

        setTimeout(() => {
            qa('.t-catalog__relevants-grid-cont, .js-catalog-relevants-grid-cont, .t-store__relevants-grid-cont, .js-store-relevants-grid-cont').forEach(processGrid);
        }, 1500);

        setTimeout(() => {
            qa('.js-catalog-grid-cont, .js-store-grid-cont, .t-catalog__relevants-grid-cont, .js-catalog-relevants-grid-cont, .t-store__relevants-grid-cont, .js-store-relevants-grid-cont').forEach(processGrid);
        }, 500);


        let lastPopupState = false;
        setInterval(() => {
            const popup = qs('.t-popup.t-popup_show');
            const currentPopupState = !!popup;

            if (currentPopupState && !lastPopupState) {
                processPopup();
                waitForPopupRelevants();
            }
            lastPopupState = currentPopupState;
        }, 250);


        document.addEventListener('click', (e) => {
            if (e.target.closest('a[href*="/tproduct/"]')) {
                setTimeout(() => {
                    processPopup();
                    waitForPopupRelevants();
                }, 300);
            }
        });


        if (qs('.t-store__prod-snippet__container')) {
            setTimeout(() => {
                const cards = qa('.js-product');
                cards.forEach(card => {
                    delete card.dataset.materialProcessed;
                    processCard(card, 'SNIPPET');
                });
            }, 300);
        }
    });

})();
</script> <style>


.uc-data-material{
    display: none;
}

.js-product-option-name[data-description]+div {
    display: none;
}


.js-product-option-name[data-description]:after {
    content: attr(data-description);
    margin-left: 5px;
}


.uc-color-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 10px;
}

.uc-color-item {
    width: 90px;
    height: 90px;
    overflow: hidden;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.2s, transform 0.2s;
    position: relative;
}

.uc-color-item:hover {
    transform: scale(1.05);
}

.uc-color-item.active-color {
    box-shadow: 0 0 0 1px rgba(0,0,0);
}

.uc-color-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}


.show-option {
    display: block !important;
}
</style>
Джинджер
001
Джинджер
002
Джинджер
003
Джинджер
004
Велетто
001
Велетто
002
Велетто
003
Велетто
004
Мадрас
001
Мадрас
002
Мадрас
003
Мадрас
004
Пальма
001
Пальма
002
Пальма
003
Пальма
004
Пальма
005
Бум
001
Бум
002
Бум
003
Бум
004
Бум
005
Бум
006
Бум
007
Бум
008
Бум
009
Бум
010
Бум
011
Бум
012
Made on
Tilda