<!--
Скрипт от Арсена: акция 1+1=3 для ВСЕХ товаров каталога.
Вставьте код целиком в Footer или в блок T123 перед </body>.
-->
<style>
.promo113-notice {
box-sizing: border-box;
width: 100%;
margin: 15px 0;
padding: 14px 16px;
color: #1f5132;
background: #eef8f1;
border: 1px solid #b9ddc4;
border-radius: 6px;
font-size: 14px;
line-height: 1.45;
}
.promo113-notice__title {
display: block;
margin-bottom: 4px;
font-size: 15px;
font-weight: 700;
}
.promo113-notice__line {
display: block;
}
</style>
<script>
(function () {
'use strict';
if (window.__promo113V2Loaded) {
console.warn('[PROMO113] Скрипт уже подключён. Удалите его дубликат.');
return;
}
window.__promo113V2Loaded = true;
/* ==================== НАСТРОЙКИ ==================== */
// В ЭТОЙ ВЕРСИИ УЧАСТВУЮТ ВСЕ ТОВАРЫ В КОРЗИНЕ.
// 1. ЦЕНА третьего товара после применения акции.
const PROMO_PRODUCT_PRICE = 1;
const CURRENCY_LABEL = '₽';
const MONEY_LOCALE = 'ru-RU';
// 2. ТЕКСТ БАННЕРА В КОРЗИНЕ.
// {product}, {price}, {discount} и {currency} скрипт подставит сам.
const BANNER_TITLE = 'Акция 1+1=3 применена';
const BANNER_LINE = 'Третий товар: {product} за {price} {currency}';
const BANNER_DISCOUNT_LINE = 'Ваша скидка: −{discount} {currency}';
const BANNER_FOOTER = 'Акция действует один раз на заказ. Промокоды не суммируются.';
// 3. true - скрывать и сбрасывать промокод, пока акция активна.
const BLOCK_PROMOCODES = true;
/* ==================================================== */
const SCRIPT_VERSION = '2.0.0';
const CART_ROOT_SELECTOR = '.t706';
const CART_CONTROL_SELECTOR = [
'.t706__product-plus',
'.t706__product-minus',
'.t706__product-del',
'.t706__product-deleted__timer__return',
'.t706__product-quantity-inp'
].join(',');
let promoActive = false;
let promoDiscount = 0;
let promoItem = null;
let running = false;
let saveHookInstalled = false;
let originalSaveCart = null;
let cartObserver = null;
let observerFrame = 0;
let bootAttempt = 0;
function parseNumber(value) {
if (typeof value === 'number') return Number.isFinite(value) ? value : 0;
let normalized = String(value == null ? '' : value)
.replace(/[\s\u00a0]/g, '')
.replace(/[^\d,.-]/g, '');
const comma = normalized.lastIndexOf(',');
const dot = normalized.lastIndexOf('.');
if (comma !== -1 && dot !== -1) {
const decimalSeparator = comma > dot ? ',' : '.';
const thousandsSeparator = decimalSeparator === ',' ? /\./g : /,/g;
normalized = normalized.replace(thousandsSeparator, '');
if (decimalSeparator === ',') normalized = normalized.replace(',', '.');
} else if (comma !== -1) {
normalized = /,\d{1,2}$/.test(normalized)
? normalized.replace(',', '.')
: normalized.replace(/,/g, '');
} else if (dot !== -1 && !/\.\d{1,2}$/.test(normalized)) {
normalized = normalized.replace(/\./g, '');
}
const number = Number(normalized);
return Number.isFinite(number) ? number : 0;
}
function roundMoney(value) {
return Math.round((parseNumber(value) + Number.EPSILON) * 100) / 100;
}
function getQuantity(product) {
return Math.max(0, parseNumber(product.quantity || 0));
}
function getUnitPrice(product) {
return Math.max(0, parseNumber(product.price || 0));
}
function isActiveProduct(product) {
return product && product.deleted !== 'yes' && getQuantity(product) > 0;
}
function getProducts() {
return window.tcart && Array.isArray(window.tcart.products)
? window.tcart.products
: [];
}
function migrateOldVersion(product) {
const oldOriginalPrice = parseNumber(product._promo113OriginalPrice);
if (oldOriginalPrice > 0) {
product.price = oldOriginalPrice;
}
delete product._promo113OriginalPrice;
delete product._promo113OriginalAmount;
}
function resetProductAmounts(products) {
products.forEach(function (product) {
if (!product) return;
migrateOldVersion(product);
if (!isActiveProduct(product)) return;
product.amount = roundMoney(getUnitPrice(product) * getQuantity(product));
});
}
function collectPromoItems(products) {
const items = [];
products.forEach(function (product, productIndex) {
if (!isActiveProduct(product)) return;
const quantity = Math.floor(getQuantity(product));
const price = getUnitPrice(product);
if (price <= PROMO_PRODUCT_PRICE) return;
for (let i = 0; i < quantity; i++) {
items.push({
productIndex: productIndex,
name: String(product.name || 'Товар'),
price: price
});
}
});
return items;
}
function getPromoItem(items) {
if (items.length < 3) return null;
// Акция срабатывает только ОДИН раз: выбираем самый дешёвый товар.
return items.slice().sort(function (a, b) {
return a.price - b.price;
})[0];
}
function applyDiscountToAmount(products, item) {
if (!item || !products[item.productIndex]) return 0;
const product = products[item.productIndex];
const discount = roundMoney(Math.max(0, item.price - PROMO_PRODUCT_PRICE));
const baseAmount = roundMoney(getUnitPrice(product) * getQuantity(product));
// ВАЖНО: меняется только сумма строки. Цена единицы всегда остаётся исходной.
product.amount = roundMoney(Math.max(PROMO_PRODUCT_PRICE, baseAmount - discount));
return discount;
}
function getPromocodeInputs() {
return Array.from(document.querySelectorAll([
'input[name="promocode"]',
'input[name="promo"]',
'input[name*="promocode" i]',
'.t-inputpromocode',
'.t706__cartwin-promocode-input'
].join(',')));
}
function clearAppliedPromocode() {
if (!window.tcart) return;
delete window.tcart.promocode;
delete window.tcart.prodamount_discountsum;
delete window.tcart.prodamount_withdiscount;
if (window.cartCalculator && 'appliedPromocode' in window.cartCalculator) {
window.cartCalculator.appliedPromocode = null;
}
}
function setPromocodeState(blocked) {
if (!BLOCK_PROMOCODES) return;
if (blocked) clearAppliedPromocode();
getPromocodeInputs().forEach(function (input) {
const wrapper = input.closest([
'.t-inputpromocode__wrapper',
'.t-input-group',
'.t-form__promocode',
'.t706__cartwin-promocode',
'.t706__cartwin-promocode-wrapper'
].join(','));
if (blocked && input.value) input.value = '';
if (input.disabled !== blocked) input.disabled = blocked;
if (wrapper) {
const display = blocked ? 'none' : '';
if (wrapper.style.display !== display) wrapper.style.display = display;
}
});
}
function formatMoney(value) {
return new Intl.NumberFormat(MONEY_LOCALE, {
maximumFractionDigits: 2
}).format(roundMoney(value));
}
function interpolate(template) {
return String(template)
.replace(/\{product\}/g, promoItem ? promoItem.name : '')
.replace(/\{price\}/g, formatMoney(PROMO_PRODUCT_PRICE))
.replace(/\{discount\}/g, formatMoney(promoDiscount))
.replace(/\{currency\}/g, CURRENCY_LABEL);
}
function appendNoticeLine(notice, text, className) {
const line = document.createElement('span');
line.className = className || 'promo113-notice__line';
line.textContent = text;
notice.appendChild(line);
}
function renderNotice() {
const cartRoot = document.querySelector(CART_ROOT_SELECTOR);
if (!cartRoot) return;
let notice = cartRoot.querySelector('.promo113-notice');
if (!promoActive || !promoItem || promoDiscount <= 0) {
if (notice) notice.remove();
return;
}
const anchor = cartRoot.querySelector([
'.t706__cartwin-prodamount-wrap',
'.t706__cartwin-totalamount-wrap',
'.t706__orderform'
].join(','));
const parent = anchor && anchor.parentNode
? anchor.parentNode
: cartRoot.querySelector('.t706__cartwin-bottom, .t706__cartwin-content, .t706__cartwin');
if (!parent) return;
if (!notice) {
notice = document.createElement('div');
notice.className = 'promo113-notice';
notice.setAttribute('role', 'status');
notice.setAttribute('aria-live', 'polite');
}
notice.textContent = '';
appendNoticeLine(notice, BANNER_TITLE, 'promo113-notice__title');
appendNoticeLine(notice, interpolate(BANNER_LINE));
appendNoticeLine(notice, interpolate(BANNER_DISCOUNT_LINE));
appendNoticeLine(notice, interpolate(BANNER_FOOTER));
if (!notice.parentNode) {
if (anchor && anchor.parentNode) anchor.parentNode.insertBefore(notice, anchor);
else parent.appendChild(notice);
}
}
function callTilda(name) {
if (typeof window[name] === 'function') {
window[name]();
return true;
}
return false;
}
function saveCart() {
if (typeof originalSaveCart === 'function') {
originalSaveCart.call(window);
return;
}
callTilda('tcart__saveLocalObj');
}
function refreshCart(options) {
const settings = options || {};
callTilda('tcart__updateTotalProductsinCartObj');
if (settings.redrawProducts !== false) callTilda('tcart__reDrawProducts');
callTilda('tcart__reDrawTotal');
if (settings.save !== false) saveCart();
}
function applyPromo(options) {
if (running) return;
const settings = options || {};
const products = getProducts();
running = true;
try {
resetProductAmounts(products);
const item = getPromoItem(collectPromoItems(products));
promoItem = item;
promoDiscount = item ? applyDiscountToAmount(products, item) : 0;
promoActive = Boolean(item && promoDiscount > 0);
setPromocodeState(promoActive);
refreshCart(settings);
} finally {
running = false;
}
if (settings.render !== false) renderNotice();
}
function installSaveHook() {
const currentSave = window.tcart__saveLocalObj;
if (typeof currentSave !== 'function') return false;
if (currentSave.__promo113Wrapped) {
saveHookInstalled = true;
originalSaveCart = currentSave.__promo113Original;
return true;
}
originalSaveCart = currentSave;
function wrappedSaveCart() {
if (!running) {
applyPromo({
redrawProducts: true,
save: false,
render: true
});
}
return originalSaveCart.apply(this, arguments);
}
wrappedSaveCart.__promo113Wrapped = true;
wrappedSaveCart.__promo113Original = originalSaveCart;
window.tcart__saveLocalObj = wrappedSaveCart;
saveHookInstalled = true;
return true;
}
function installCartObserver() {
if (cartObserver) return true;
const cartRoot = document.querySelector(CART_ROOT_SELECTOR);
if (!cartRoot) return false;
cartObserver = new MutationObserver(function () {
if (observerFrame) return;
observerFrame = window.requestAnimationFrame(function () {
observerFrame = 0;
setPromocodeState(promoActive);
const noticeExists = Boolean(cartRoot.querySelector('.promo113-notice'));
if ((promoActive && !noticeExists) || (!promoActive && noticeExists)) {
renderNotice();
}
});
});
cartObserver.observe(cartRoot, { childList: true, subtree: true });
return true;
}
function handleCartControl(event) {
if (!event.target || !event.target.closest(CART_CONTROL_SELECTOR)) return;
// Основной путь - перехват сохранения Тильды. Это резервный синхронный путь.
if (!saveHookInstalled) {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
}
function handleSubmit(event) {
const form = event.target;
if (!form || !form.closest || !form.closest(CART_ROOT_SELECTOR)) return;
// Последняя синхронная проверка непосредственно перед отправкой заказа.
applyPromo({
redrawProducts: false,
save: true,
render: false
});
}
function handleCartOpened() {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
function boot() {
bootAttempt += 1;
const hookReady = installSaveHook();
const observerReady = installCartObserver();
const cartReady = Boolean(window.tcart && Array.isArray(window.tcart.products));
if (cartReady) {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
if ((!hookReady || !observerReady || !cartReady) && bootAttempt < 40) {
window.setTimeout(boot, 250);
return;
}
if (!hookReady) {
console.error('[PROMO113] Не найдена tcart__saveLocalObj. Работает резервный обработчик элементов корзины.');
}
if (!cartReady) {
console.error('[PROMO113] Корзина Тильды не инициализирована.');
}
}
document.addEventListener('click', handleCartControl);
document.addEventListener('focusout', handleCartControl);
document.addEventListener('change', handleCartControl);
document.addEventListener('submit', handleSubmit, true);
document.addEventListener('fullscreenCartOpened', handleCartOpened);
document.addEventListener('DOMContentLoaded', boot);
if (document.readyState !== 'loading') boot();
console.log('[PROMO113] Версия ' + SCRIPT_VERSION + ' загружена.');
})();
</script> <!--
Скрипт от Арсена: акция 1+1=3 по ID товаров.
Вставьте код целиком в Footer или в блок T123 перед </body>.
-->
<style>
.promo113-notice {
box-sizing: border-box;
width: 100%;
margin: 15px 0;
padding: 14px 16px;
color: #1f5132;
background: #eef8f1;
border: 1px solid #b9ddc4;
border-radius: 6px;
font-size: 14px;
line-height: 1.45;
}
.promo113-notice__title {
display: block;
margin-bottom: 4px;
font-size: 15px;
font-weight: 700;
}
.promo113-notice__line {
display: block;
}
</style>
<script>
(function () {
'use strict';
if (window.__promo113V2Loaded) {
console.warn('[PROMO113] Скрипт уже подключён. Удалите его дубликат.');
return;
}
window.__promo113V2Loaded = true;
/* ==================== НАСТРОЙКИ ==================== */
// 1. ВПИШИТЕ ID ТОВАРОВ, УЧАСТВУЮЩИХ В АКЦИИ.
// ID берётся из window.tcart.products: uid, lid или gen_uid.
const PROMO_PRODUCT_IDS = [
'ID-ПЕРВОГО-ТОВАРА',
'ID-ВТОРОГО-ТОВАРА',
'ID-ТРЕТЬЕГО-ТОВАРА'
];
// 2. ЦЕНА третьего товара после применения акции.
const PROMO_PRODUCT_PRICE = 1;
const CURRENCY_LABEL = '₽';
const MONEY_LOCALE = 'ru-RU';
// 3. ТЕКСТ БАННЕРА В КОРЗИНЕ.
// {product}, {price}, {discount} и {currency} скрипт подставит сам.
const BANNER_TITLE = 'Акция 1+1=3 применена';
const BANNER_LINE = 'Третий товар: {product} за {price} {currency}';
const BANNER_DISCOUNT_LINE = 'Ваша скидка: −{discount} {currency}';
const BANNER_FOOTER = 'Акция действует один раз на заказ. Промокоды не суммируются.';
// 4. true - скрывать и сбрасывать промокод, пока акция активна.
const BLOCK_PROMOCODES = true;
/* ==================================================== */
const SCRIPT_VERSION = '2.0.0';
const promoProductIds = new Set(PROMO_PRODUCT_IDS.map(String));
const CART_ROOT_SELECTOR = '.t706';
const CART_CONTROL_SELECTOR = [
'.t706__product-plus',
'.t706__product-minus',
'.t706__product-del',
'.t706__product-deleted__timer__return',
'.t706__product-quantity-inp'
].join(',');
let promoActive = false;
let promoDiscount = 0;
let promoItem = null;
let running = false;
let saveHookInstalled = false;
let originalSaveCart = null;
let cartObserver = null;
let observerFrame = 0;
let bootAttempt = 0;
function parseNumber(value) {
if (typeof value === 'number') return Number.isFinite(value) ? value : 0;
let normalized = String(value == null ? '' : value)
.replace(/[\s\u00a0]/g, '')
.replace(/[^\d,.-]/g, '');
const comma = normalized.lastIndexOf(',');
const dot = normalized.lastIndexOf('.');
if (comma !== -1 && dot !== -1) {
const decimalSeparator = comma > dot ? ',' : '.';
const thousandsSeparator = decimalSeparator === ',' ? /\./g : /,/g;
normalized = normalized.replace(thousandsSeparator, '');
if (decimalSeparator === ',') normalized = normalized.replace(',', '.');
} else if (comma !== -1) {
normalized = /,\d{1,2}$/.test(normalized)
? normalized.replace(',', '.')
: normalized.replace(/,/g, '');
} else if (dot !== -1 && !/\.\d{1,2}$/.test(normalized)) {
normalized = normalized.replace(/\./g, '');
}
const number = Number(normalized);
return Number.isFinite(number) ? number : 0;
}
function roundMoney(value) {
return Math.round((parseNumber(value) + Number.EPSILON) * 100) / 100;
}
function getQuantity(product) {
return Math.max(0, parseNumber(product.quantity || 0));
}
function getUnitPrice(product) {
return Math.max(0, parseNumber(product.price || 0));
}
function isActiveProduct(product) {
return product && product.deleted !== 'yes' && getQuantity(product) > 0;
}
function getProducts() {
return window.tcart && Array.isArray(window.tcart.products)
? window.tcart.products
: [];
}
function getProductIds(product) {
return [
product && product.uid,
product && product.lid,
product && product.gen_uid
].filter(Boolean).map(String);
}
function isPromoProduct(product) {
return getProductIds(product).some(function (id) {
return promoProductIds.has(id);
});
}
function migrateOldVersion(product) {
const oldOriginalPrice = parseNumber(product._promo113OriginalPrice);
if (oldOriginalPrice > 0) {
product.price = oldOriginalPrice;
}
delete product._promo113OriginalPrice;
delete product._promo113OriginalAmount;
}
function resetProductAmounts(products) {
products.forEach(function (product) {
if (!product) return;
migrateOldVersion(product);
if (!isActiveProduct(product)) return;
product.amount = roundMoney(getUnitPrice(product) * getQuantity(product));
});
}
function collectPromoItems(products) {
const items = [];
products.forEach(function (product, productIndex) {
if (!isActiveProduct(product) || !isPromoProduct(product)) return;
const quantity = Math.floor(getQuantity(product));
const price = getUnitPrice(product);
if (price <= PROMO_PRODUCT_PRICE) return;
for (let i = 0; i < quantity; i++) {
items.push({
productIndex: productIndex,
name: String(product.name || 'Товар'),
price: price
});
}
});
return items;
}
function getPromoItem(items) {
if (items.length < 3) return null;
// Акция срабатывает только ОДИН раз: выбираем самый дешёвый товар.
return items.slice().sort(function (a, b) {
return a.price - b.price;
})[0];
}
function applyDiscountToAmount(products, item) {
if (!item || !products[item.productIndex]) return 0;
const product = products[item.productIndex];
const discount = roundMoney(Math.max(0, item.price - PROMO_PRODUCT_PRICE));
const baseAmount = roundMoney(getUnitPrice(product) * getQuantity(product));
// ВАЖНО: меняется только сумма строки. Цена единицы всегда остаётся исходной.
product.amount = roundMoney(Math.max(PROMO_PRODUCT_PRICE, baseAmount - discount));
return discount;
}
function getPromocodeInputs() {
return Array.from(document.querySelectorAll([
'input[name="promocode"]',
'input[name="promo"]',
'input[name*="promocode" i]',
'.t-inputpromocode',
'.t706__cartwin-promocode-input'
].join(',')));
}
function clearAppliedPromocode() {
if (!window.tcart) return;
delete window.tcart.promocode;
delete window.tcart.prodamount_discountsum;
delete window.tcart.prodamount_withdiscount;
if (window.cartCalculator && 'appliedPromocode' in window.cartCalculator) {
window.cartCalculator.appliedPromocode = null;
}
}
function setPromocodeState(blocked) {
if (!BLOCK_PROMOCODES) return;
if (blocked) clearAppliedPromocode();
getPromocodeInputs().forEach(function (input) {
const wrapper = input.closest([
'.t-inputpromocode__wrapper',
'.t-input-group',
'.t-form__promocode',
'.t706__cartwin-promocode',
'.t706__cartwin-promocode-wrapper'
].join(','));
if (blocked && input.value) input.value = '';
if (input.disabled !== blocked) input.disabled = blocked;
if (wrapper) {
const display = blocked ? 'none' : '';
if (wrapper.style.display !== display) wrapper.style.display = display;
}
});
}
function formatMoney(value) {
return new Intl.NumberFormat(MONEY_LOCALE, {
maximumFractionDigits: 2
}).format(roundMoney(value));
}
function interpolate(template) {
return String(template)
.replace(/\{product\}/g, promoItem ? promoItem.name : '')
.replace(/\{price\}/g, formatMoney(PROMO_PRODUCT_PRICE))
.replace(/\{discount\}/g, formatMoney(promoDiscount))
.replace(/\{currency\}/g, CURRENCY_LABEL);
}
function appendNoticeLine(notice, text, className) {
const line = document.createElement('span');
line.className = className || 'promo113-notice__line';
line.textContent = text;
notice.appendChild(line);
}
function renderNotice() {
const cartRoot = document.querySelector(CART_ROOT_SELECTOR);
if (!cartRoot) return;
let notice = cartRoot.querySelector('.promo113-notice');
if (!promoActive || !promoItem || promoDiscount <= 0) {
if (notice) notice.remove();
return;
}
const anchor = cartRoot.querySelector([
'.t706__cartwin-prodamount-wrap',
'.t706__cartwin-totalamount-wrap',
'.t706__orderform'
].join(','));
const parent = anchor && anchor.parentNode
? anchor.parentNode
: cartRoot.querySelector('.t706__cartwin-bottom, .t706__cartwin-content, .t706__cartwin');
if (!parent) return;
if (!notice) {
notice = document.createElement('div');
notice.className = 'promo113-notice';
notice.setAttribute('role', 'status');
notice.setAttribute('aria-live', 'polite');
}
notice.textContent = '';
appendNoticeLine(notice, BANNER_TITLE, 'promo113-notice__title');
appendNoticeLine(notice, interpolate(BANNER_LINE));
appendNoticeLine(notice, interpolate(BANNER_DISCOUNT_LINE));
appendNoticeLine(notice, interpolate(BANNER_FOOTER));
if (!notice.parentNode) {
if (anchor && anchor.parentNode) anchor.parentNode.insertBefore(notice, anchor);
else parent.appendChild(notice);
}
}
function callTilda(name) {
if (typeof window[name] === 'function') {
window[name]();
return true;
}
return false;
}
function saveCart() {
if (typeof originalSaveCart === 'function') {
originalSaveCart.call(window);
return;
}
callTilda('tcart__saveLocalObj');
}
function refreshCart(options) {
const settings = options || {};
callTilda('tcart__updateTotalProductsinCartObj');
if (settings.redrawProducts !== false) callTilda('tcart__reDrawProducts');
callTilda('tcart__reDrawTotal');
if (settings.save !== false) saveCart();
}
function applyPromo(options) {
if (running) return;
const settings = options || {};
const products = getProducts();
running = true;
try {
resetProductAmounts(products);
const item = getPromoItem(collectPromoItems(products));
promoItem = item;
promoDiscount = item ? applyDiscountToAmount(products, item) : 0;
promoActive = Boolean(item && promoDiscount > 0);
setPromocodeState(promoActive);
refreshCart(settings);
} finally {
running = false;
}
if (settings.render !== false) renderNotice();
}
function installSaveHook() {
const currentSave = window.tcart__saveLocalObj;
if (typeof currentSave !== 'function') return false;
if (currentSave.__promo113Wrapped) {
saveHookInstalled = true;
originalSaveCart = currentSave.__promo113Original;
return true;
}
originalSaveCart = currentSave;
function wrappedSaveCart() {
if (!running) {
applyPromo({
redrawProducts: true,
save: false,
render: true
});
}
return originalSaveCart.apply(this, arguments);
}
wrappedSaveCart.__promo113Wrapped = true;
wrappedSaveCart.__promo113Original = originalSaveCart;
window.tcart__saveLocalObj = wrappedSaveCart;
saveHookInstalled = true;
return true;
}
function installCartObserver() {
if (cartObserver) return true;
const cartRoot = document.querySelector(CART_ROOT_SELECTOR);
if (!cartRoot) return false;
cartObserver = new MutationObserver(function () {
if (observerFrame) return;
observerFrame = window.requestAnimationFrame(function () {
observerFrame = 0;
setPromocodeState(promoActive);
const noticeExists = Boolean(cartRoot.querySelector('.promo113-notice'));
if ((promoActive && !noticeExists) || (!promoActive && noticeExists)) {
renderNotice();
}
});
});
cartObserver.observe(cartRoot, { childList: true, subtree: true });
return true;
}
function handleCartControl(event) {
if (!event.target || !event.target.closest(CART_CONTROL_SELECTOR)) return;
// Основной путь - перехват сохранения Тильды. Это резервный синхронный путь.
if (!saveHookInstalled) {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
}
function handleSubmit(event) {
const form = event.target;
if (!form || !form.closest || !form.closest(CART_ROOT_SELECTOR)) return;
// Последняя синхронная проверка непосредственно перед отправкой заказа.
applyPromo({
redrawProducts: false,
save: true,
render: false
});
}
function handleCartOpened() {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
function boot() {
bootAttempt += 1;
const hookReady = installSaveHook();
const observerReady = installCartObserver();
const cartReady = Boolean(window.tcart && Array.isArray(window.tcart.products));
if (cartReady) {
applyPromo({
redrawProducts: true,
save: true,
render: true
});
}
if ((!hookReady || !observerReady || !cartReady) && bootAttempt < 40) {
window.setTimeout(boot, 250);
return;
}
if (!hookReady) {
console.error('[PROMO113] Не найдена tcart__saveLocalObj. Работает резервный обработчик элементов корзины.');
}
if (!cartReady) {
console.error('[PROMO113] Корзина Тильды не инициализирована.');
}
}
document.addEventListener('click', handleCartControl);
document.addEventListener('focusout', handleCartControl);
document.addEventListener('change', handleCartControl);
document.addEventListener('submit', handleSubmit, true);
document.addEventListener('fullscreenCartOpened', handleCartOpened);
document.addEventListener('DOMContentLoaded', boot);
if (document.readyState !== 'loading') boot();
console.log('[PROMO113] Версия ' + SCRIPT_VERSION + ' загружена.');
})();
</script>