1document.addEventListener("DOMContentLoaded", function() { 2 const lista = document.getElementById("lista-marcas"); 3 const totalFiltro = document.getElementById("total-filtro-marcas"); 4 const btnCarregar = document.getElementById("btn-carregar-marcas"); 5 const letrasBtns = document.querySelectorAll(".filtro-letra"); 6 const inputBusca = document.getElementById("buscar-marcas"); 7 const btnSearch = document.getElementById("btn-search"); 8 const btnLimpar = document.getElementById("limpar-filtros-marcas"); 9 10 let letraSelecionada = ""; 11 let busca = ""; 12 let pagina = 0; 13 const limite = 20; 14 let totalMarcasBanco = 0; 15 let marcasCarregadas = 0; 16 let projetoRaizSelecionado = ""; // novo: armazena o projetoRaiz selecionado 17 18 // Carregar letras habilitadas 19 fetch("/core/api/carregar-marcas-letras.php") 20 .then(res => res.json()) 21 .then(data => { 22 const letrasDisponiveis = Array.isArray(data.letras) ? data.letras : []; 23 24 // Normaliza para Uppercase e usa Set para lookup rápido 25 const setLetras = new Set(letrasDisponiveis.map(l => String(l).toUpperCase())); 26 27 letrasBtns.forEach(btn => { 28 const letraBtn = String(btn.dataset.letra || "").toUpperCase(); 29 if (!setLetras.has(letraBtn)) { 30 btn.disabled = true; 31 btn.classList.add("desabilitado"); 32 } else { 33 btn.disabled = false; 34 btn.classList.remove("desabilitado"); 35 } 36 }); 37 }) 38 .catch(err => { 39 console.error("Erro ao carregar letras disponÃveis:", err); 40 }); 41 42 // Carregar marcas (aceita projetoRaizParam opcional) 43 function carregarMarcas(reset = false, projetoRaizParam = "") { 44 if (reset) { 45 pagina = 0; 46 marcasCarregadas = 0; 47 lista.innerHTML = ""; 48 } 49 50 const url = `/core/api/buscar-marcas.php?letra=${encodeURIComponent(letraSelecionada)}&busca=${encodeURIComponent(busca)}&pagina=${pagina}&limite=${limite}&projetoRaiz=${encodeURIComponent(projetoRaizParam)}`; 51 52 fetch(url) 53 .then(res => res.json()) 54 .then(data => { 55 totalMarcasBanco = Number(data.totalMarcasBanco) || 0; 56 57 // Guarda extra no front 58 const marcas = (data.marcas || []).filter(m => Number(m.exibicaoMarca) === 1); 59 60 if (reset && marcas.length === 0) { 61 totalFiltro.textContent = "Não existem marcas com esse filtro. Limpe os filtros ativos."; 62 btnCarregar.style.display = "none"; 63 return; 64 } 65 66 // Prioriza projetosRaiz vindos do response; se não existir, usa o parâmetro passado 67 const projetosRaiz = new Set( 68 Array.isArray(data.projetosRaiz) ? 69 data.projetosRaiz.map(Number) : 70 (projetoRaizParam ? [Number(projetoRaizParam)] : []) 71 ); 72 73 marcas.forEach(marca => { 74 const linkCard = document.createElement("a"); 75 // calcula Ãndice baseado no DOM atual (compatÃvel com carregamento incremental) para cards de marcas 76 const i = lista ? lista.querySelectorAll(".card-marca").length : 0; 77 78 // aplicar variação de padding a cada grupo de 3 cards: 79 // primeiro do grupo (i % 3 === 0) => ps-md-0 pe-md-2 80 // terceiro do grupo (i % 3 === 2) => ps-md-2 pe-0 81 const paddingClass = (i % 3 === 0) ? "ps-md-0 pe-md-2" : (i % 3 === 2) ? "ps-md-2 pe-md-0" : ""; 82 linkCard.className = `card-marca col-md-4 col-6 mb-3 d-flex ${paddingClass}`.trim(); 83 84 const idProj = Number(marca.idProjeto); 85 // const baseHref = projetosRaiz.has(idProj) ? "/marca/" : "/produtos/marca/"; 86 const baseHref = "/marca/"; 87 linkCard.href = baseHref + marca.slugMarca; 88 89 let logoCaminho = marca.logoMarca ? 'https://www.hypera.com.br/assets/images/marcas/banners/' : "/assets/images/"; 90 let logoMarca = marca.logoMarca && marca.logoMarca.includes("-negativo") ? marca.logoMarca.replace("-negativo", "") : marca.logoMarca; 91 92 const card = document.createElement("div"); 93 card.className = "card card-marca d-flex justify-content-center align-items-center rounded border border-1 border-neutra-100 py-md-3 p-mobile-3 h-100 w-100"; 94 95 if (logoMarca) { 96 const logo = document.createElement("img"); 97 logo.src = `${logoCaminho}${logoMarca}`; 98 logo.className = "image object-fit-contain"; 99 logo.alt = marca.nomeMarca; 100 logo.height = 48; 101 logo.width = 194; 102 card.appendChild(logo); 103 } else { 104 const nomeMarca = document.createElement("h3"); 105 nomeMarca.className = "text-center mb-0"; 106 nomeMarca.textContent = marca.nomeMarca; 107 card.appendChild(nomeMarca); 108 } 109 110 linkCard.appendChild(card); 111 lista.appendChild(linkCard); 112 }); 113 114 marcasCarregadas += marcas.length; 115 totalFiltro.textContent = `Você visualizou ${marcasCarregadas} de ${totalMarcasBanco} marcas`; 116 117 if (marcasCarregadas >= totalMarcasBanco) { 118 // substituir botão por um texto informativo 119 if (btnCarregar) { 120 if(document.getElementById("msg-todas-marcas-carregadas")) { 121 btnCarregar.remove(); 122 } else { 123 const msg = document.createElement("div"); 124 msg.id = "msg-todas-marcas-carregadas"; 125 msg.textContent = "Todas as marcas foram carregadas"; 126 msg.className = "text-muted text-center fw-bold"; 127 btnCarregar.parentNode.insertBefore(msg, btnCarregar.
127nextSibling); 128 btnCarregar.remove(); 129 } 130 131 if (btnCarregar.parentNode) { 132 btnCarregar.parentNode.insertBefore(msg, btnCarregar.nextSibling); 133 btnCarregar.remove(); 134 } else { 135 const msg = document.createElement("div"); 136 msg.id = "msg-todas-marcas-carregadas"; 137 msg.textContent = "Todas as marcas foram carregadas"; 138 msg.className = "text-muted text-center fw-bold"; 139 btnCarregar.parentNode.insertBefore(msg, btnCarregar.nextSibling); 140 btnCarregar.remove(); 141 } 142 } 143 } else { 144 if (btnCarregar) { 145 btnCarregar.removeAttribute("disabled"); 146 btnCarregar.textContent = "Carregar mais"; 147 btnCarregar.style.display = "block"; 148 } else { 149 // remove o texto "Todas as marcas foram carregadas" se existir 150 const msg = document.getElementById("msg-todas-marcas-carregadas"); 151 if (msg) { 152 // recriar o botão 153 const novoBtn = document.createElement("button"); 154 novoBtn.id = "btn-carregar-marcas"; 155 novoBtn.className = "btn btn-primary mx-auto d-block mt-3"; 156 novoBtn.textContent = "Carregar mais"; 157 novoBtn.addEventListener("click", () => { 158 novoBtn.setAttribute("disabled", "disabled"); 159 novoBtn.textContent = "Carregando..."; 160 pagina++; 161 carregarMarcas(false, projetoRaizSelecionado); 162 }); 163 const parent = msg.parentNode || lista; 164 parent.insertBefore(novoBtn, msg.nextSibling); 165 // garante estado visÃvel e habilitado do botão 166 btnCarregar.removeAttribute("disabled"); 167 btnCarregar.textContent = "Carregar mais"; 168 btnCarregar.style.display = "block"; 169 msg.remove(); 170 } 171 } 172 } 173 }); 174 } 175 176 // Clique na letra 177 letrasBtns.forEach(btn => { 178 btn.addEventListener("click", () => { 179 // resetar estilo de todas 180 letrasBtns.forEach(b => { 181 b.classList.remove("btn-primary", "text-primary-50"); 182 b.classList.add("btn-primary-50", "text-primary"); 183 }); 184 185 // aplicar estilo de ativa 186 btn.classList.remove("btn-primary-50", "text-primary"); 187 btn.classList.add("btn-primary", "text-primary-50"); 188 189 letraSelecionada = btn.dataset.letra; 190 // lê projetoRaiz do data-attribute da letra (por exemplo data-projetoraiz) 191 projetoRaizSelecionado = btn.dataset.projetoraiz || ""; 192 carregarMarcas(true, projetoRaizSelecionado); 193 194 const offcanvasEl = document.getElementById("offcanvasResponsive"); 195 if (offcanvasEl && offcanvasEl.classList.contains("show")) { 196 const offcanvasInstance = bootstrap.Offcanvas.getInstance(offcanvasEl) 197 || new bootstrap.Offcanvas(offcanvasEl); 198 offcanvasInstance.hide(); 199 } 200 }); 201 }); 202 203 // Busca por nome 204 busca = (inputBusca?.value || "").trim(); 205 if (btnSearch) { 206 btnSearch.innerHTML = busca.length > 0 207 ? `<span class="material-symbols-rounded align-middle">delete</span>` 208 : `<span class="material-symbols-rounded align-middle">search</span>`; 209 } 210 211 if (inputBusca) { 212 inputBusca.addEventListener("input", (e) => { 213 busca = e.target.value.trim(); 214 if (btnSearch) { 215 btnSearch.innerHTML = busca.length > 0 216 ? `<span class="material-symbols-rounded align-middle">delete</span>` 217 : `<span class="material-symbols-rounded align-middle">search</span>`; 218 } 219 carregarMarcas(true, projetoRaizSelecionado); 220 }); 221 } 222 223 if (btnSearch) { 224 btnSearch.addEventListener("click", () => { 225 if (busca.length > 0) { 226 inputBusca.value = ""; 227 busca = ""; 228 btnSearch.innerHTML = `<span class="material-symbols-rounded align-middle">search</span>`; 229 carregarMarcas(true, projetoRaizSelecionado); 230 } 231 }); 232 } 233 234 // Limpar filtro 235 btnLimpar.addEventListener("click", e => { 236 e.preventDefault(); 237 letraSelecionada = ""; 238 busca = ""; 239 projetoRaizSelecionado = ""; 240 if (inputBusca) inputBusca.value = ""; 241 242 letrasBtns.forEach(b => { 243 b.classList.remove("btn-primary", "text-primary-50"); 244 b.classList.add("btn-primary-50", "text-primary"); 245 }); 246 247 // remover o texto "Todas as marcas foram carregadas" e restaurar o botão 248 const msg = document.getElementById("msg-todas-marcas-carregadas"); 249 if (msg) { 250 const parent = msg.parentNode || lista; 251 if (btnCarregar) { 252 parent.insertBefore(btnCarregar, msg.nextSibling); 253 // garante estado visÃvel e habilitado do botão 254 btnCarregar.removeAttribute("disabled"); 255 btnCarregar.textContent = "Carregar mais"; 256 btnCarregar.style.display = "block"; 257 } else { 258 const novoBtn = document.createElement("button"); 259 novoBtn.id = "btn-carregar-marcas"; 260 novoBtn.className = "btn btn-primary mx-auto d-block mt-3"; 261 novoBtn.textContent = "Carregar mais"; 262 novoBtn.addEventListener("click", () => { 263 novoBtn.setAttribute("disabled", "disabled"); 264 novoBtn.textContent = "Carregando..."; 265 pagina++;
266 carregarMarcas(false, projetoRaizSelecionado); 267 }); 268 parent.insertBefore(novoBtn, msg.nextSibling); 269 } 270 msg.remove(); 271 } 272 273 carregarMarcas(true, projetoRaizSelecionado); 274 275 const offcanvasEl = document.getElementById("offcanvasResponsive"); 276 if (offcanvasEl && offcanvasEl.classList.contains("show")) { 277 const offcanvasInstance = bootstrap.Offcanvas.getInstance(offcanvasEl) 278 || new bootstrap.Offcanvas(offcanvasEl); 279 offcanvasInstance.hide(); 280 } 281 }); 282 283 // Botão carregar mais 284 btnCarregar.addEventListener("click", () => { 285 btnCarregar.setAttribute("disabled", "disabled"); 286 btnCarregar.textContent = "Carregando..."; 287 pagina++; 288 carregarMarcas(false, projetoRaizSelecionado); 289 }); 290 291 carregarMarcas(true, projetoRaizSelecionado); // inicial 292});
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.