1(function () { 2 "use strict"; 3 4 const FRAGMENTS = { 5 header: { 6 url: "/painel/layout/header.html", 7 mount: "[data-extremos-header]", 8 required: "#masthead" 9 }, 10 footer: { 11 url: "/painel/layout/footer.html", 12 mount: "[data-extremos-footer]", 13 required: "#colophon" 14 } 15 }; 16 const LAYOUT_STYLES_URL = "/painel/layout/layout.css?v=20260729-1"; 17 const PUBLICIDADE_LOADER_URL = "/painel/publi/loader.js?v=20260812-1"; 18 const COMMENTS_LOADER_URL = "/painel/comentarios/comentarios.js?v=20260728-1"; 19 const MOBILE_MENU_OPTIONS = { 20 duration: 500, 21 closedSymbol: '<i class="fas fa-plus"></i>', 22 openedSymbol: '<i class="fas fa-minus"></i>', 23 prependTo: ".mobile-menu-container", 24 allowParentLinks: true, 25 nestedParentLinks: false, 26 label: "Menu", 27 closeOnClick: true 28 }; 29 30 function parseFragment(html) { 31 const template = document.createElement("template"); 32 template.innerHTML = html.trim(); 33 return template.content; 34 } 35 36 function loadLayoutStyles() { 37 if (document.querySelector('link[data-extremos-layout-styles]')) return; 38 if (document.querySelector(`link[href^="/painel/layout/layout.css"]`)) return; 39 40 const link = document.createElement("link"); 41 link.rel = "stylesheet"; 42 link.href = LAYOUT_STYLES_URL; 43 link.setAttribute("data-extremos-layout-styles", ""); 44 document.head.appendChild(link); 45 } 46 47 function initializeMobileMenu() { 48 if (!window.jQuery || typeof window.jQuery.fn.slicknav !== "function") return; 49 50 const navigation = window.jQuery("#navigation"); 51 if (!navigation.length) return; 52 53 window.jQuery(".mobile-menu-container .slicknav_menu").remove(); 54 navigation.removeData("plugin_slicknav"); 55 navigation.slicknav(MOBILE_MENU_OPTIONS); 56 } 57 58 function initializeSearchFallback() { 59 const openButton = document.querySelector(".header-search-icon .search-icon"); 60 const searchForm = document.querySelector(".header-search-form"); 61 const searchElement = searchForm?.querySelector("form"); 62 const searchInput = searchForm?.querySelector("input"); 63 const closeButton = searchForm?.querySelector(".search-close"); 64 if (!openButton || !searchForm || !closeButton) return; 65 66 openButton.addEventListener("click", (event) => { 67 event.preventDefault(); 68 event.stopPropagation(); 69 searchForm.classList.add("search-in"); 70 searchInput?.focus(); 71 }); 72 73 searchInput?.addEventListener("click", () => { 74 if (searchInput.value === "DIGITE A SUA BUSCA") searchInput.value = ""; 75 }); 76 77 closeButton.addEventListener("click", (event) => { 78 event.preventDefault(); 79 searchForm.classList.remove("search-in"); 80 }); 81 82 document.addEventListener("click", (event) => { 83 if (searchForm.contains(event.target) || openButton.contains(event.target)) return; 84 searchForm.classList.remove("search-in"); 85 }); 86 87 document.addEventListener("keydown", (event) => { 88 if (event.key === "Escape") searchForm.classList.remove("search-in"); 89 }); 90 91 searchElement?.addEventListener("submit", (event) => { 92 event.preventDefault(); 93 const query = searchInput?.value.trim(); 94 if (!query) return; 95 const url = `https://www.google.com/search?q=${encodeURIComponent(`${query} site:extremos.com.br`)}`; 96 window.open(url, "_blank", "noopener"); 97 }); 98 } 99 100 function initializeFixedHeader() { 101 const header = document.querySelector("#masthead"); 102 const topHeader = header?.querySelector(".top-header"); 103 const bottomHeader = header?.querySelector(".bottom-header"); 104 if (!header || !topHeader || !bottomHeader) return; 105 106 const update = () => { 107 const desktop = window.matchMedia("(min-width: 992px)").matches; 108 const threshold = desktop 109 ? topHeader.offsetHeight 110 : topHeader.offsetHeight + bottomHeader.offsetHeight; 111 header.classList.toggle("fixed-header", window.scrollY > threshold); 112 }; 113 114 window.addEventListener("scroll", update, { passive: true });
115 window.addEventListener("resize", update, { passive: true }); 116 update(); 117 } 118 119 function initializeBackToTop() { 120 const button = document.querySelector("#backTotop"); 121 if (!button) return; 122 123 const update = () => { 124 button.style.display = window.scrollY > 300 ? "block" : "none"; 125 }; 126 127 button.addEventListener("click", (event) => { 128 event.preventDefault(); 129 window.scrollTo({ top: 0, behavior: "smooth" }); 130 }); 131 window.addEventListener("scroll", update, { passive: true }); 132 update(); 133 } 134 135 async function fetchFragment({ url, mount: mountSelector, required }) { 136 const mount = document.querySelector(mountSelector); 137 if (!mount) return null; 138 139 try { 140 const response = await window.fetch(url, { 141 credentials: "same-origin", 142 cache: "no-cache" 143 }); 144 if (!response.ok) throw new Error(`HTTP ${response.status}`); 145 146 const fragment = parseFragment(await response.text()); 147 if (!fragment.querySelector(required)) { 148 throw new Error(`Fragmento inválido: ${url}`); 149 } 150 mount.replaceWith(fragment); 151 return true; 152 } catch (error) { 153 mount.removeAttribute("aria-busy"); 154 mount.classList.add("extremos-layout-error"); 155 return false; 156 } 157 } 158 159 function setCurrentYear() { 160 const year = String(new Date().getFullYear()); 161 document.querySelectorAll("[data-current-year]").forEach((element) => { 162 element.textContent = year; 163 }); 164 } 165 166 function loadPublicidade() { 167 if (document.body.hasAttribute("data-layout-no-publicidade")) return; 168 if (document.querySelector('script[data-extremos-publicidade-loader]')) return; 169 const script = document.createElement("script"); 170 script.src = PUBLICIDADE_LOADER_URL; 171 script.async = true; 172 script.setAttribute("data-extremos-publicidade-loader", ""); 173 document.head.appendChild(script); 174 } 175 176 function loadComments() { 177 if (!document.querySelector("[data-extremos-comments]")) return; 178 if (document.querySelector('script[data-extremos-comments-loader]')) return; 179 180 const script = document.createElement("script"); 181 script.src = COMMENTS_LOADER_URL; 182 script.defer = true; 183 script.setAttribute("data-extremos-comments-loader", ""); 184 document.head.appendChild(script); 185 } 186 187 async function loadLayout() { 188 loadLayoutStyles(); 189 loadPublicidade(); 190 loadComments(); 191 192 const [headerLoaded, footerLoaded] = await Promise.all([ 193 fetchFragment(FRAGMENTS.header), 194 fetchFragment(FRAGMENTS.footer) 195 ]); 196 197 const headerReady = Boolean(headerLoaded || document.querySelector("#masthead")); 198 const footerReady = Boolean(footerLoaded || document.querySelector("#colophon")); 199 200 if (headerReady) { 201 const header = document.querySelector("#masthead"); 202 const navigation = document.querySelector("#navigation"); 203 if (header && navigation) { 204 initializeMobileMenu(); 205 initializeSearchFallback(); 206 initializeFixedHeader(); 207 document.body.classList.add("extremos-header-ready"); 208 document.dispatchEvent(new CustomEvent("extremos:header-ready")); 209 } 210 } 211 212 if (footerReady) { 213 setCurrentYear(); 214 initializeBackToTop(); 215 document.body.classList.add("extremos-footer-ready"); 216 document.dispatchEvent(new CustomEvent("extremos:footer-ready")); 217 } 218 219 if (!headerReady) { 220 document.dispatchEvent(new CustomEvent("extremos:header-error")); 221 } 222 if (!footerReady) { 223 document.dispatchEvent(new CustomEvent("extremos:footer-error")); 224 } 225 } 226 227 if (document.readyState === "loading") { 228 document.addEventListener("DOMContentLoaded", loadLayout, { once: true }); 229 } else { 230 loadLayout(); 231 } 232}());
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.