1/* Descubra seu pneu â Caiado Pneus (05/10/2026, v3: base v2 com medida por ano-modelo e versão; motor 1.3.0) 2 v3: a medida só vai na mensagem quando a linha daquele ano tem confiança alta ou média; versão com medida não 3 confirmada vai sem medida (a equipe confirma). Começo da mensagem igual (o CRM identifica pela origem). 4 Pedido do Matheus: a pessoa recebe o pneu Sà no WhatsApp. A página não mostra medida nenhuma: o motor pneu-veiculo 5 1.2.0 monta a escolha do carro (marca, modelo, ano, versão) e a medida de fábrica vai na mensagem pronta do WhatsApp 6 ("A medida vai na mensagem", 02/10/2026), junto com o carro; a equipe confirma e responde com o orçamento. 7 Os nomes de versão do motor podem citar pneu de outra marca: a tela mostra a versão limpa (Goodyear fica). */ 8(function () { 9 'use strict'; 10 var PV = window.PneuVeiculo; 11 var WA = '5518982010519'; // WhatsApp de Presidente Prudente (teste inicial pedido pelo Matheus em 01/10/2026) 12 var ORIGEM = 'Olá! Vim pelo site da Caiado (Descubra seu pneu).'; 13 var POPULARES = ['chevrolet', 'fiat', 'volkswagen', 'toyota', 'hyundai', 'jeep', 'renault', 'honda', 'ford', 14 'nissan', 'byd', 'chery', 'gwm', 'peugeot', 'citroen', 'mitsubishi', 'kia']; 15 16 function $(s) { return document.querySelector(s); } 17 var selMarca = $('#dpMarca'), selModelo = $('#dpModelo'), selAno = $('#dpAno'), selVersao = $('#dpVersao'); 18 var status = $('#dpStatus'), form = $('#dpForm'), botao = $('#dpBotao'), resumo = $('#dpResumo'), dica = $('#dpDica'); 19 20 function wa(texto) { return 'https://wa.me/' + WA + '?text=' + encodeURIComponent(texto); } 21 var MSG_GERAL = ORIGEM + ' Quero ajuda para descobrir o pneu do meu carro.'; 22 23 if (!PV || !selMarca) { 24 if (status) status.innerHTML = 'Não deu para carregar a busca agora. <a href="' + wa(MSG_GERAL) + '" target="_blank" rel="noopener">Fale com a Caiado no WhatsApp</a>.'; 25 if (botao) { botao.href = wa(MSG_GERAL); botao.classList.remove('desligado'); botao.removeAttribute('aria-disabled'); } 26 return; 27 } 28 // versao da base: muda a cada publicacao, para quem ja abriu a pagina receber os dados novos (cache de 4 h) 29 var VERSAO_BASE = '2026100605'; 30 PV.configurar({ caminho: 'dados/', versao: VERSAO_BASE }); // relativo: funciona no site (/descubra-seu-pneu/) e aberto direto do Mac 31 32 function nomeMarca(slug) { 33 var l = PV.marcas(); 34 for (var i = 0; i < l.length; i++) if (l[i].slug === slug) return l[i].nome; 35 return slug; 36 } 37 38 // nome da versão para a tela e para a mensagem: sem trechos que citam pneu de outra marca (Goodyear fica) 39 var OUTRAS = /pirelli|michelin|bridgestone|firestone|dunlop|kumho|yokohama|hankook|\btoyo\b|falken|nexen|westlake|linglong|conti(?:nental)?\s*(?:van|conti|premium|power|sport|eco|cross|contact)|equipamento original|\bpneu\s/i; 40 function limpaVersao(t) { 41 var partes = String(t || '').split(' / '); 42 var boas = partes.filter(function (p) { return !OUTRAS.test(p) || /goodyear/i.test(p); }); 43 return boas.length ? boas.join(' / ') : 'Versão de série'; 44 } 45 // opções de versão: o motor escreve "versão: medida"; aqui fica só a versão (a medida vai pelo WhatsApp) 46 function limpaOpcoesDeVersao() { 47 for (var i = 0; i < selVersao.options.length; i++) { 48 var o = selVersao.options[i]; 49 if (!o.value) { o.textContent = 'Escolha, se souber'; continue; } 50 o.textContent = limpaVersao(o.value); 51 } 52 } 53 function versaoCurta(v) { // a opção pode juntar várias versões com o mesmo pneu: mostra 2 e "e similares" 54 var l = limpaVersao(v).split(' / '); 55 return l.length > 2 ? l.slice(0, 2).join(' / ') + ' e similares' : l.join(' / '); 56 } 57 58 // estado do botão: só liga quando marca, modelo e ano estão escolhidos (versão é opcional) 59 function atualiza() { 60 var pronto = selMarca.value && selModelo.value && selAno.value; 61 form.classList.toggle('pronto', !!pronto); 62 if (!pronto) { 63 botao.href = '#dpForm'; 64 botao.classList.add('desligado'); botao.setAttribute('aria-disabled', 'true'); 65 resumo.textContent = 'Escolha a marca, o modelo e o ano do seu carro.'; 66 dica.hidden = true; 67 return; 68 }
69 var carro = nomeMarca(selMarca.value) + ' ' + selModelo.value + ' ' + selAno.value; 70 var versao = selVersao.value; 71 var msg = ORIGEM + ' Quero o orçamento do pneu do meu carro: ' + carro + 72 (versao ? ', versão ' + versaoCurta(versao) + '.' : ' (não sei a versão).') + textoMedida(versao); 73 botao.href = wa(msg); 74 botao.classList.remove('desligado'); botao.removeAttribute('aria-disabled'); 75 resumo.innerHTML = '<b>' + esc(carro) + '</b>' + (versao ? ' · ' + esc(versaoCurta(versao)) : ''); 76 dica.hidden = !!versao || selVersao.disabled || selVersao.options.length < 2; 77 guardaNaUrl(); 78 } 79 // medida de fábrica: vai Sà na mensagem do WhatsApp (pedido do Matheus, 02/10/2026); a página não mostra. 80 // "195/65R15" -> "195/65 R15"; se a dianteira e a traseira forem diferentes, diz qual é qual. 81 function bonita(m) { return String(m).replace(/^([A-Z]{0,2}\d{3}\/\d{2})\s*(Z?R)\s*(\d)/, '$1 $2$3'); } 82 function textoMedida(versao) { 83 var r; 84 try { r = PV.buscar({ marca: selMarca.value, modelo: selModelo.value, ano: +selAno.value, versao: versao || '' }); } 85 catch (x) { return ''; } 86 if (!r || !r.ok || r.ano == null) return ''; // ano sem medida na base: a equipe confirma 87 // linha de confiança baixa não manda medida: se a versão escolhida tem dúvida, a mensagem vai sem medida 88 var duvida = r.versoes.some(function (v) { return v.confianca === 'baixa'; }); 89 if (versao && duvida) return ''; 90 var vistos = {}, lista = []; 91 r.versoes.forEach(function (v) { 92 if (v.confianca === 'baixa') return; 93 var k = v.medida + '|' + v.eixo; 94 if (!vistos[k]) { vistos[k] = 1; lista.push({ medida: bonita(v.medida), eixo: v.eixo }); } 95 }); 96 if (!lista.length) return ''; 97 // sem versão escolhida: só avisa "a confirmar" se a versão em dúvida tiver medida diferente das confirmadas 98 if (duvida) duvida = r.versoes.some(function (v) { 99 return v.confianca === 'baixa' && !vistos[v.medida + '|' + v.eixo]; 100 }); 101 // do aro menor para o maior (dianteiro antes do traseiro), para a equipe ler fácil 102 function aro(m) { var x = /R\s?(\d{2}(?:\.5)?)/.exec(m.medida); return x ? parseFloat(x[1]) : 0; } 103 lista.sort(function (a, b) { return aro(a) - aro(b) || (a.eixo === 'traseiro') - (b.eixo === 'traseiro') || (a.medida < b.medida ? -1 : 1); }); 104 var porEixo = lista.some(function (m) { return m.eixo !== 'todos'; }); 105 var partes = lista.map(function (m) { return m.medida + (m.eixo !== 'todos' ? ' (' + m.eixo + ')' : ''); }); 106 if (lista.length === 1) return ' Medida de fábrica' + (duvida ? ' (a confirmar)' : '') + ': ' + partes[0] + '.'; 107 if (porEixo && lista.length === 2) return ' Medidas de fábrica: ' + partes.join(' e ') + '.'; 108 return ' Medidas de fábrica possÃveis: ' + partes.join(' ou ') + '.'; 109 } 110 function esc(s) { 111 return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) { 112 return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; 113 }); 114 } 115 116 // endereço compartilhável: /descubra-seu-pneu/?marca=fiat&modelo=Strada&ano=2022 117 function guardaNaUrl() { 118 if (!window.history || !history.replaceState) return; 119 var q = ['marca=' + encodeURIComponent(selMarca.value), 'modelo=' + encodeURIComponent(selModelo.value), 'ano=' + selAno.value]; 120 try { history.replaceState(null, '', location.pathname + '?' + q.join('&')); } catch (x) { /* nada */ } 121 } 122 123 var cascata = PV.ligarCascata({ 124 marca: selMarca, modelo: selModelo, ano: selAno, versao: selVersao, 125 rotulos: { marca: 'Escolha a marca', modelo: 'Escolha o modelo', ano: 'Escolha o ano', versao: 'Escolha, se souber' }, 126 mostrarAnos: true, 127 autoVersao: false, // com uma versão só, não escolhe por ela: o nome pode não ser o do carro da pessoa 128 onEstado: function (s) { 129 form.classList.toggle('carregando', s.carregando); 130 status.textContent = s.carregando ? 'Carregando os modelosâ¦' : ''; 131 }, 132 onErro: function () { 133 form.classList.remove('carregando'); 134 status.innerHTML = 'Não deu para carregar os modelos agora. Tente de novo em instantes ou <a href="' + 135 wa(MSG_GERAL) + '" target="_blank" rel="noopener">fale com a Caiado no WhatsApp</a>.'; 136 }, 137 onResultado: function () { atualiza(); } // nada de medida na tela: só atualiza o botão 138 }); 139 140 // marcas: as mais procuradas primeiro, depois todas em ordem alfabética 141 (function () { 142 var todas = PV.marcas().slice().sort(function (a, b) { return a.nome.localeCompare(b.nome, 'pt-BR'); }); 143 var porSlug = {}; 144 todas.forEach(function (m) { porSlug[m.slug] = m; }); 145 var frag = document.createDocumentFragment(); 146 var vazio = document.createElement('option'); vazio.value = ''; vazio.textContent = 'Escolha a marca'; frag.appendChild(vazio); 147 var g1 = document.createElement('optgroup'); g1.label = 'Mais procuradas'; 148 POPULARES.forEach(function (s) { 149 if (!porSlug[s]) return; 150 var o = document.createElement('option'); o.value = s; o.textContent = porSlug[s].nome; g1.appendChild(o); 151 }); 152 var g2 = document.createElement('optgroup'); g2.label = 'Todas as marcas'; 153 todas.forEach(function (m) { var o = document.createElement('option'); o.value = m.slug; o.textContent = m.nome; g2.appendChild(o); }); 154 frag.appendChild(g1); frag.appendChild(g2); 155 selMarca.innerHTML = ''; selMarca.appendChild(frag); selMarca.disabled = false;
156 })(); 157 158 // os ouvintes do motor vêm antes destes (foram ligados primeiro): aqui as opções já estão preenchidas 159 selMarca.addEventListener('change', atualiza); 160 selModelo.addEventListener('change', atualiza); 161 selAno.addEventListener('change', function () { limpaOpcoesDeVersao(); atualiza(); }); 162 selVersao.addEventListener('change', atualiza); 163 164 // botão desligado: leva para a escolha do carro em vez de abrir o WhatsApp 165 botao.addEventListener('click', function (ev) { 166 if (!botao.classList.contains('desligado')) return; 167 ev.preventDefault(); ev.stopPropagation(); 168 var falta = !selMarca.value ? selMarca : (!selModelo.value ? selModelo : selAno); 169 falta.focus(); 170 form.classList.remove('lembra'); void form.offsetWidth; form.classList.add('lembra'); 171 }, true); 172 173 // veio com o carro no endereço (?marca=...&modelo=...&ano=...) 174 (function () { 175 var q = {}; 176 location.search.replace(/^\?/, '').split('&').forEach(function (p) { 177 if (!p) return; 178 var i = p.indexOf('='); 179 q[decodeURIComponent(p.slice(0, i))] = decodeURIComponent(p.slice(i + 1).replace(/\+/g, ' ')); 180 }); 181 if (!q.marca || nomeMarca(q.marca) === q.marca) return; 182 selMarca.value = q.marca; 183 selMarca.dispatchEvent(new Event('change')); 184 var t0 = Date.now(); 185 (function espera() { 186 if (selModelo.options.length < 2) { if (Date.now() - t0 < 12000) setTimeout(espera, 60); return; } 187 if (!q.modelo) return; 188 selModelo.value = q.modelo; 189 if (selModelo.value !== q.modelo) return; 190 selModelo.dispatchEvent(new Event('change')); 191 if (!q.ano) return; 192 selAno.value = String(q.ano); 193 if (selAno.value !== String(q.ano)) return; 194 selAno.dispatchEvent(new Event('change')); 195 })(); 196 })(); 197 198 atualiza(); 199 void cascata; 200})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.