' + '' + ''; lista.insertBefore(li, lista.firstChild); // links "#" do botão não levam a lugar nenhum li.querySelectorAll('.tc-sem-link').forEach(function (a) { a.addEventListener('click', function (ev) { ev.preventDefault(); }); }); } /* ---------------- 2b. TOPO: rótulo do carrinho, destaque e vendedor ---------------- */ function ajustarTopo() { // "Carrinho" embaixo do ícone var carrinho = document.querySelector('header .cart-header'); if (carrinho && !carrinho.querySelector('.tc-rotulo')) { var rot = document.createElement('span'); rot.className = 'tc-rotulo'; rot.textContent = 'Carrinho'; carrinho.appendChild(rot); } var lista = document.querySelector('#nav .list'); if (!lista) return; // item em destaque if (CONFIG.destaqueMenu.texto && !lista.querySelector('.tc-destaque')) { var d = document.createElement('li'); d.className = 'first-level tc-destaque'; d.innerHTML = '
' + CONFIG.destaqueMenu.texto + '
'; lista.appendChild(d); } // "Fale com um vendedor" (WhatsApp) if (!lista.querySelector('.tc-vendedor')) { var numero = (CONFIG.whatsapp || '').replace(/\D/g, ''); if (!numero) { var rodape = document.querySelector('footer'); var achado = rodape && rodape.textContent.match(/\(?\d{2}\)?\s?9\d{4}-?\d{4}/); if (achado) numero = achado[0].replace(/\D/g, ''); } if (numero) { if (numero.length <= 11) numero = '55' + numero; var v = document.createElement('li'); v.className = 'first-level tc-vendedor'; v.innerHTML = '' + '
' + CONFIG.textoVendedor + '
'; lista.appendChild(v); } } } /* ---------------- 2c. RODAPÉ: copyright na faixa final ---------------- */ function ajustarRodape() { var faixa = document.querySelector('footer .copy .container'); if (!faixa || faixa.querySelector('.tc-copyright')) return; var d = document.createElement('div'); d.className = 'tc-copyright'; d.innerHTML = 'Copyright © ' + new Date().getFullYear() + ' ' + CONFIG.textoCopyright; faixa.insertBefore(d, faixa.firstChild); } /* ---------------- 2d. TOPO SEM ESPAÇO SOBRANDO ---------------- O tema reserva uma altura fixa para o topo. Como o nosso topo é mais baixo, sobrava uma faixa cinza entre o menu e o banner. Aqui o espaço é calculado com a altura real do topo. (A posição do menu ao rolar a página fica por conta do CSS.) */ function ajustarAlturaTopo() { var faixa = document.querySelector('.top-bar'); var topo = document.querySelector('header.header'); var app = document.querySelector('.application'); if (!topo || !app || getComputedStyle(topo).position !== 'fixed') return; var temFaixa = app.classList.contains('with-message-line') && faixa && getComputedStyle(faixa).display !== 'none'; var alturaFaixa = temFaixa ? faixa.offsetHeight : 0; app.style.paddingTop = (alturaFaixa + topo.offsetHeight + CONFIG.espacoAbaixoDoMenu) + 'px'; } /* ---------------- 3. MARCAS ROLANDO ---------------- */ function iniciarMarcas() { var secao = document.querySelector('.section-brands'); var lista = document.querySelector('.section-brands .slide-brand .list'); if (!secao || !lista || lista.getAttribute('data-duplicado')) return; lista.querySelectorAll('img[data-src]').forEach(function (img) { img.src = img.getAttribute('data-src'); }); Array.prototype.slice.call(lista.children).forEach(function (item) { var copia = item.cloneNode(true); copia.removeAttribute('id'); copia.setAttribute('aria-hidden', 'true'); lista.appendChild(copia); }); lista.setAttribute('data-duplicado', '1'); // cartão branco com título, igual às vitrines var carrossel = secao.querySelector('.slide-brand'); var cartao = document.createElement('div'); cartao.className = 'container tc-cartao-marcas'; cartao.innerHTML = '

' + CONFIG.tituloMarcas + '

'; carrossel.parentNode.insertBefore(cartao, carrossel); cartao.appendChild(carrossel); // leva a faixa de marcas para logo abaixo do banner var banner = document.querySelector('.section-slideshow'); if (CONFIG.marcasJuntoDoBanner && banner && banner.parentNode) { banner.parentNode.insertBefore(secao, banner.nextSibling); secao.classList.add('tc-marcas-banner'); } } /* ---------------- 4. PÁGINA INICIAL ---------------- */ function ajustarHome() { // esconde seções de banner sem imagem document.querySelectorAll('.section-banners-grid').forEach(function (sec) { if (!sec.querySelector('img')) sec.classList.add('vazia'); }); // vitrines com 5 produtos por linha no computador. // O tema só monta o carrossel quando ele aparece na tela, // então verificamos a cada 0,3s por até 1 minuto. function cincoPorLinha(el) { var sw = el.swiper; if (!sw || !sw.params.breakpoints) return false; sw.params.breakpoints['1024'] = Object.assign({}, sw.params.breakpoints['1024'], { slidesPerView: 5, spaceBetween: 20 }); sw.params.breakpoints['768'] = Object.assign({}, sw.params.breakpoints['768'], { spaceBetween: 16 }); sw.params.breakpoints['0'] = Object.assign({}, sw.params.breakpoints['0'], { spaceBetween: 10 }); sw.currentBreakpoint = null; sw.setBreakpoint(); sw.update(); el.setAttribute('data-cinco', '1'); return true; } var tentativas = 0; var timer = setInterval(function () { tentativas++; var pendentes = 0; document.querySelectorAll('.section-showcase .swiper-container').forEach(function (el) { if (!el.getAttribute('data-cinco') && !cincoPorLinha(el)) pendentes++; }); if (!pendentes || tentativas > 200) clearInterval(timer); }, 300); } /* ---------------- 5. PÁGINA DE PRODUTO ---------------- */ function ajustarProduto() { var info = document.querySelector('.product-form .product-shipping .info'); if (info && !info.getAttribute('data-tc')) { info.innerHTML = CONFIG.tituloFrete + '' + CONFIG.avisoFrete + ''; info.setAttribute('data-tc', '1'); } var zip = document.querySelector('.product-form #zip'); if (zip) zip.setAttribute('placeholder', '00000-000'); var calc = document.querySelector('.product-form .submit-shipping'); if (calc) calc.textContent = 'consultar'; // abas viram seções empilhadas, uma embaixo da outra var abas = document.querySelector('.product-tabs'); if (CONFIG.secoesEmpilhadas && abas && !abas.classList.contains('tc-empilhado')) { abas.querySelectorAll('.tabs-nav .tab-link').forEach(function (a) { var id = (a.getAttribute('href') || '').split('#')[1]; var secao = id && document.getElementById(id); if (!secao) return; var titulo = document.createElement('h2'); titulo.className = 'tc-secao-titulo'; var nome = a.textContent.replace(/\s+/g, ' ').trim(); if (a.classList.contains('description-link-tab') && CONFIG.nomesSecoes['Descrição Geral']) { nome = 'Descrição Geral'; } titulo.textContent = CONFIG.nomesSecoes[nome] || nome; secao.parentNode.insertBefore(titulo, secao); }); abas.classList.add('tc-empilhado'); } } /* ---------------- 5b. PÁGINA DE PRODUTO: extras estilo home center ---------------- - seletor de quantidade (– 1 +) que adiciona ao carrinho pela API da loja - selo "-X% OFF" quando houver preço promocional - aviso abaixo do preço, estrelas com link para as avaliações - descrição curta embaixo das fotos com "veja a descrição completa" */ function rolarAte(el) { if (!el) return; var y = el.getBoundingClientRect().top + window.pageYOffset - 170; window.scrollTo({ top: y, behavior: 'smooth' }); } function lerPreco(texto) { var m = (texto || '').replace(/\./g, '').match(/(\d+),(\d{2})/); return m ? parseFloat(m[1] + '.' + m[2]) : 0; } function extrasProduto() { var form = document.querySelector('.product-form'); if (!form || form.getAttribute('data-tc-extras')) return; form.setAttribute('data-tc-extras', '1'); // selo de desconto var de = lerPreco((document.querySelector('#precoDe') || {}).textContent); var por = lerPreco((document.querySelector('#variacaoPreco') || {}).textContent); var principal = document.querySelector('.product-form .PrecoPrincipal'); if (de > por && por > 0 && principal) { var off = document.createElement('span'); off.className = 'tc-off'; off.textContent = '-' + Math.round((1 - por / de) * 100) + '% OFF'; principal.parentNode.insertBefore(off, principal); } // aviso abaixo do preço var caixaPreco = document.querySelector('.product-form .product-price'); if (CONFIG.avisoPreco && caixaPreco) { var aviso = document.createElement('p'); aviso.className = 'tc-aviso-preco'; aviso.textContent = CONFIG.avisoPreco; caixaPreco.parentNode.insertBefore(aviso, caixaPreco.nextSibling); } // estrelas levam até as avaliações var nota = form.querySelector('.product-rating'); if (nota) { nota.style.cursor = 'pointer'; nota.addEventListener('click', function (ev) { ev.preventDefault(); rolarAte(document.getElementById('coments')); }); } // descrição curta embaixo das fotos var galeria = document.querySelector('.product-gallery'); var descricao = document.getElementById('descricao'); if (galeria && descricao) { var texto = descricao.innerText.replace(/\s+/g, ' ').trim(); if (texto) { var curta = document.createElement('div'); curta.className = 'tc-desc-curta'; curta.innerHTML = '

veja a descrição completa'; curta.querySelector('p').textContent = texto.length > 170 ? texto.slice(0, 170).replace(/\s\S*$/, '') + '…' : texto; curta.querySelector('a').addEventListener('click', function (ev) { ev.preventDefault(); rolarAte(document.querySelector('.tc-secao-titulo') || descricao); }); galeria.appendChild(curta); // fica embaixo das fotos, dentro da coluna da galeria } } // seletor de quantidade var acoes = form.querySelector('.actions'); var botao = form.querySelector('#button-buy'); var acao = (document.querySelector('#form_comprar') || {}).getAttribute && document.querySelector('#form_comprar').getAttribute('action') || ''; var idProduto = (acao.match(/IdProd=(\d+)/) || [])[1]; if (!acoes || !botao || !idProduto) return; var qtd = document.createElement('div'); qtd.className = 'tc-qtd'; qtd.innerHTML = '' + '' + ''; var campo = qtd.querySelector('input'); qtd.querySelector('.tc-menos').addEventListener('click', function () { campo.value = Math.max(1, (parseInt(campo.value, 10) || 1) - 1); }); qtd.querySelector('.tc-mais').addEventListener('click', function () { campo.value = (parseInt(campo.value, 10) || 1) + 1; }); acoes.parentNode.insertBefore(qtd, acoes); var erro = document.createElement('div'); erro.className = 'tc-qtd-erro'; acoes.parentNode.insertBefore(erro, acoes.nextSibling); botao.addEventListener('click', function (ev) { var quantidade = parseInt(campo.value, 10) || 1; if (quantidade <= 1) return; // 1 unidade: o tema faz como sempre // produto com variação ainda não escolhida ou campos extras: deixa o tema validar var variacao = (document.querySelector('#variant_selected') || {}).value || '0'; if ((document.querySelector('.product-variants') && variacao === '0') || document.querySelector('.product-additional-fields')) return; ev.preventDefault(); ev.stopImmediatePropagation(); erro.textContent = ''; botao.disabled = true; var sessao = document.documentElement.getAttribute('data-session'); fetch('/web_api/cart/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ Cart: { session_id: sessao, product_id: idProduto, quantity: String(quantidade), variant_id: variacao } }) }).then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); }).then(function (res) { botao.disabled = false; if (!res.ok) { var c = res.d && res.d.causes; var msg = Array.isArray(c) ? c[0] : 'Não foi possível adicionar. Tente uma quantidade menor.'; erro.textContent = msg; return; } campo.value = 1; var icone = document.querySelector('header .cart-header'); if (icone) icone.click(); // abre o carrinho lateral atualizado }).catch(function () { botao.disabled = false; erro.textContent = 'Não foi possível adicionar agora. Tente novamente.'; }); }, true); } /* ---------------- INICIAR ---------------- */ function iniciar() { try { montarSubmenu(); } catch (e) {} try { criarTodasCategorias(); } catch (e) {} try { ajustarTopo(); } catch (e) {} try { ajustarRodape(); } catch (e) {} try { iniciarMarcas(); } catch (e) {} try { ajustarProduto(); } catch (e) {} if (document.documentElement.classList.contains('page-product')) { try { extrasProduto(); } catch (e) {} } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', iniciar); } else { iniciar(); } // recalcula o espaço do topo ao carregar e ao redimensionar a tela window.addEventListener('resize', ajustarAlturaTopo); window.addEventListener('load', function () { ajustarAlturaTopo(); setTimeout(ajustarAlturaTopo, 600); }); document.addEventListener('DOMContentLoaded', ajustarAlturaTopo); if (document.readyState === 'complete') { ajustarAlturaTopo(); setTimeout(ajustarHome, 300); } else { window.addEventListener('load', function () { setTimeout(ajustarHome, 300); }); } })();