<script>
(function() {
'use strict';
const qs = (sel, ctx = document) => ctx.querySelector(sel);
const qa = (sel, ctx = document) => Array.from(ctx.querySelectorAll(sel));
const formatPrice = n => n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
const parsePrice = txt => {
if (!txt) return 0;
let c = txt.trim().replace(/[₽€£¥\s]/g, '');
if (c.includes(',') && c.includes('.')) c = c.replace(/,/g, '');
else if (c.includes(',')) c = c.replace(',', '.');
const n = parseFloat(c.replace(/[^\d.]/g, ''));
return isNaN(n) ? 0 : n;
};
const TEMPLATE = `<div class="common-price-wrapper" style="display:none;opacity:0;transition:opacity .3s">
<div class="common-price-title t-descr t-descr_xxs"></div>
<div class="common-price-num t-name t-name_md">
<span class="col-summ"></span>
</div>
</div>`;
function processCard(card, context = 'unknown') {
if (card.dataset.priceProcessed) return;
const pw = qs('.t-catalog__card__price-wrapper, .t-store__card__price-wrapper', card);
if (!pw) return;
pw.insertAdjacentHTML('afterend', TEMPLATE);
const priceEl = qs('.js-product-price', card);
const summEl = qs('.col-summ', card);
if (priceEl && summEl) {
summEl.textContent = priceEl.textContent.trim();
}
card.dataset.priceProcessed = '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 || popup.dataset.popupProcessed) return;
if (!qs('.js-product-price', popup)) return;
const pw = qs('.t-catalog__prod-popup__price-wrapper, .t-store__prod-popup__price-wrapper', popup);
if (pw) pw.insertAdjacentHTML('afterend', TEMPLATE);
const priceEl = qs('.js-product-price', popup);
const summEl = qs('.col-summ', popup);
if (priceEl && summEl) summEl.textContent = priceEl.textContent.trim();
popup.dataset.popupProcessed = 'true';
}
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;
let processedCount = 0;
containers.forEach(container => {
const cards = qa('.t-store__card, .t-catalog__card, .js-product-relevant', container);
cards.forEach(card => {
processCard(card, 'POPUP RELEVANTS');
if (!card.dataset.priceProcessed) processedCount++;
});
});
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);
} else {
console.warn('Relevants Timeout');
}
};
setTimeout(check, interval);
}
function handleQty(e) {
const target = e.target.closest('.t-catalog__prod__quantity-input, .t-store__prod__quantity-input, .t-catalog__prod__quantity__minus-wrapper, .t-catalog__prod__quantity__plus-wrapper, .t-store__prod__quantity__minus-wrapper, .t-store__prod__quantity__plus-wrapper, .js-product-controls-wrapper');
if (!target) return;
const block = target.closest('.js-product');
if (!block) return;
setTimeout(() => {
const input = qs('.t-catalog__prod__quantity-input, .t-store__prod__quantity-input', block);
const num = input ? (parseInt(input.value, 10) || 1) : 1;
const priceEl = qs('.js-product-price', block);
const currEl = qs('[class*="price-currency"]', block);
const summEl = qs('.col-summ', block);
const wrap = block.querySelector('.common-price-wrapper');
if (!priceEl || !summEl) return;
const val = parsePrice(priceEl.textContent);
const curr = currEl?.textContent.trim() || '₽';
const total = val * num;
// Убрали Math.round. toFixed(2) защищает от артефактов JS (напр. 2800.6600000000003),
// а parseFloat возвращает "естественный" вид (1400.33, 456.3, 456)
const valF = parseFloat(val.toFixed(2));
const totalF = parseFloat(total.toFixed(2));
if (num > 1) {
summEl.textContent = `${formatPrice(valF)} ${curr} × ${num} = ${formatPrice(totalF)} ${curr}`;
if (wrap) { wrap.style.display = 'block'; requestAnimationFrame(() => wrap.style.opacity = '1'); }
} else {
summEl.textContent = `${formatPrice(valF)} ${curr}`;
if (wrap) { wrap.style.opacity = '0'; setTimeout(() => wrap.style.display = 'none', 300); }
}
}, 150);
}
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 popupReady = false;
setInterval(() => {
const popup = qs('.t-popup.t-popup_show');
if (popup && !popupReady) {
if (qs('.js-product-price', popup)) {
processPopup();
popupReady = true;
}
} else if (!popup) {
popupReady = false;
}
}, 250);
document.addEventListener('click', (e) => {
if (e.target.closest('a[href*="/tproduct/"]')) {
setTimeout(() => {
processPopup();
waitForPopupRelevants();
}, 300);
}
});
document.addEventListener('click', handleQty, true);
document.addEventListener('input', handleQty, true);
document.addEventListener('change', handleQty, true);
if (qs('.t-store__prod-snippet__container')) {
setTimeout(() => {
document.querySelectorAll('.common-price-wrapper').forEach(el => el.remove());
const pw = qs('.t-catalog__prod-popup__price-wrapper, .t-store__prod-popup__price-wrapper, .t-catalog__card__price-wrapper, .t-store__card__price-wrapper');
if (pw) pw.insertAdjacentHTML('afterend', TEMPLATE);
const priceEl = qs('.js-product-price');
const summEl = qs('.col-summ');
if (priceEl && summEl) summEl.textContent = priceEl.textContent.trim();
}, 300);
}
});
})();
</script>
<style>
.common-price-num {
font-size: 14px;
margin-top: 5px;
font-weight: 400;
margin-bottom: 5px;
}
.js-catalog-prod-price.t-catalog__prod-popup__price {
font-size: 26px;
}
</style>