1/** 2 * Mobile Menu Component 3 * Standardized overlay for mobile navigation across all portal products 4 */ 5 6const MobileMenu = { 7 getHomeSectionHref(sectionId) { 8 const safeSectionId = String(sectionId || "").replace(/^#/, ""); 9 if (!safeSectionId) return "https://www.correiodamanha.com.br/"; 10 11 const productRoutes = { 12 "rio-de-janeiro": "https://www.correiodamanha.com.br/cm/rio", 13 "sao-paulo": "https://www.correiodamanha.com.br/cm/sp", 14 "campinas": "https://www.correiodamanha.com.br/cm/campinas", 15 "distrito-federal": "https://www.correiodamanha.com.br/cm/df", 16 "petropolis": "https://www.correiodamanha.com.br/cm/petropolitano", 17 "sul-fluminense": "https://www.correiodamanha.com.br/cm/sul-fluminense", 18 "jornal-da-barra": "https://www.correiodamanha.com.br/cm/barra", 19 "jornal-de-turismo": "https://www.correiodamanha.com.br/cm/turismo", 20 "jornal-servidor": "https://www.correiodamanha.com.br/cm/servidor", 21 }; 22 23 if (productRoutes[safeSectionId]) { 24 return productRoutes[safeSectionId]; 25 } 26 27 const sectionRoutes = { 28 opiniao: "https://www.correiodamanha.com.br/opiniao", 29 magnavita: "https://www.correiodamanha.com.br/colunistas/magnavita", 30 politica: "https://www.correiodamanha.com.br/politica", 31 economia: "https://www.correiodamanha.com.br/economia", 32 justica: "https://www.correiodamanha.com.br/justica", 33 cultura: "https://www.correiodamanha.com.br/cultura", 34 esporte: "https://www.correiodamanha.com.br/esporte/esporte", 35 esportes: "https://www.correiodamanha.com.br/esporte/esporte", 36 mundo: "https://www.correiodamanha.com.br/mundo", 37 }; 38 39 if (sectionRoutes[safeSectionId]) { 40 return sectionRoutes[safeSectionId]; 41 } 42 43 return `#${safeSectionId}`; 44 }, 45 46 getColumnsSubmenuHTML() { 47 const items = (window.CMColumns && window.CMColumns.getCatalog()) || []; 48 return items 49 .map( 50 (item) => ` 51 <li><a href="${item.url}">${item.label}</a></li> 52 `, 53 ) 54 .join(""); 55 }, 56 57 render() { 58 if (document.getElementById("mobile-menu-overlay")) return; 59 const isProductPage = document.body.classList.contains("is-cm-product-page"); 60 61 const overlay = document.createElement("div"); 62 overlay.id = "mobile-menu-overlay"; 63 overlay.className = "mobile-menu-overlay"; 64 overlay.innerHTML = ` 65 <div class="mobile-menu-drawer"> 66 <div class="mobile-menu-header"> 67 <a href="https://www.correiodamanha.com.br/" class="mobile-logo-brand" aria-label="CM - O portal do grupo Correio da Manhã"> 68 <span class="mobile-menu-monogram">CM</span> 69 <span class="mobile-menu-brand-rule" aria-hidden="true"></span> 70 <span class="mobile-logo-text">O portal do grupo Correio da Manhã</span> 71 </a> 72 <button class="mobile-menu-close" id="mobile-menu-close" aria-label="Fechar"> 73 <i class="fas fa-times"></i> 74 </button> 75 </div> 76 77 <div class="mobile-menu-search"> 78 <form class="mobile-search-form" action="/busca.php" method="get" role="search" data-cm-portal-search="true"> 79 <input type="search" placeholder="" name="q" id="mobile-search-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"> 80 <button type="submit"><i class="fas fa-search"></i></button> 81 </form> 82 </div> 83 84 <nav class="mobile-nav-links"> 85 <ul class="mobile-nav-main"> 86 <li><a href="${this.getHomeSectionHref("opiniao")}"><i class="fas fa-comment-alt"></i> Opinião</a></li> 87 <li class="mobile-nav-has-submenu mobile-nav-has-split-link"> 88 <div class="mobile-nav-link-row"> 89 <a href="${this.getHomeSectionHref("magnavita")}" class="mobile-nav-link-primary"> 90 <i class="fas fa-star"></i> Colunistas 91 </a> 92 <button 93 class="mobile-submenu-toggle" 94 aria-expanded="false" 95 aria-haspopup="true" 96 aria-controls="mobile-submenu-colunas" 97 aria-label="Abrir menu de Colunistas" 98 > 99 <i class="fas fa-chevron-down mobile-submenu-arrow"></i> 100 </button> 101 </div> 102 <ul class="mobile-submenu mobile-submenu-columns" id="mobile-submenu-colunas"> 103 ${this.getColumnsSubmenuHTML()} 104 </ul> 105 </li> 106 <li><a href="${this.getHomeSectionHref("politica")}
106"><i class="fas fa-landmark"></i> PolÃtica</a></li> 107 <li><a href="${this.getHomeSectionHref("economia")}"><i class="fas fa-chart-line"></i> Economia</a></li> 108 <li><a href="${this.getHomeSectionHref("justica")}"><i class="fas fa-balance-scale"></i> Justiça</a></li> 109 <li><a href="${this.getHomeSectionHref("cultura")}"><i class="fas fa-palette"></i> Cultura & Artes</a></li> 110 <li><a href="${this.getHomeSectionHref("esporte")}"><i class="fas fa-futbol"></i> Esportes</a></li> 111 <li><a href="${this.getHomeSectionHref("mundo")}"><i class="fas fa-globe"></i> Mundo</a></li> 112 ${isProductPage ? "" : `<li><a href="https://www.youtube.com/@TVCorreiodaManh%C3%A3"><i class="fab fa-youtube"></i> CM News TV</a></li>`} 113 <li class="mobile-nav-has-submenu"> 114 <button class="mobile-submenu-toggle" aria-expanded="false" aria-haspopup="true"> 115 <span><i class="fas fa-newspaper"></i> Nossos Jornais</span> 116 <i class="fas fa-chevron-down mobile-submenu-arrow"></i> 117 </button> 118 <ul class="mobile-submenu" id="mobile-submenu-jornais"> 119 <li><a href="${this.getHomeSectionHref("rio-de-janeiro")}">Correio da Manhã RJ</a></li> 120 <li><a href="${this.getHomeSectionHref("sao-paulo")}">Correio da Manhã SP</a></li> 121 <li><a href="${this.getHomeSectionHref("campinas")}">Correio da Manhã Campinas</a></li> 122 <li><a href="${this.getHomeSectionHref("distrito-federal")}">Correio da Manhã DF</a></li> 123 <li><a href="${this.getHomeSectionHref("petropolis")}">Correio Petropolitano</a></li> 124 <li><a href="${this.getHomeSectionHref("sul-fluminense")}">Correio Sul Fluminense</a></li> 125 <li><a href="${this.getHomeSectionHref("jornal-da-barra")}">Jornal da Barra</a></li> 126 <li><a href="${this.getHomeSectionHref("jornal-de-turismo")}">Jornal de Turismo</a></li> 127 <li><a href="${this.getHomeSectionHref("jornal-servidor")}">Jornal do Servidor</a></li> 128 </ul> 129 </li> 130 </ul> 131 </nav> 132 133 <div class="mobile-menu-footer"> 134 <div class="mobile-socials"> 135 <a href="#" aria-label="Facebook"><i class="fab fa-facebook-f"></i></a> 136 <a href="https://www.instagram.com/correiodamanhabr/" target="_blank" rel="noopener noreferrer" aria-label="Instagram"><i class="fab fa-instagram"></i></a> 137 <a href="#" aria-label="Twitter"><i class="fab fa-twitter"></i></a> 138 <a href="https://www.youtube.com/@TVCorreiodaManhã" target="_blank" rel="noopener noreferrer" aria-label="YouTube"><i class="fab fa-youtube"></i></a> 139 </div> 140 <p class="mobile-copyright">© 2026 Correio da Manhã</p> 141 </div> 142 </div> 143 `; 144 document.body.appendChild(overlay); 145 this.init(); 146 }, 147 148 init() { 149 const closeBtn = document.getElementById("mobile-menu-close"); 150 const overlay = document.getElementById("mobile-menu-overlay"); 151 const searchForm = overlay?.querySelector(".mobile-search-form"); 152 153 if (closeBtn && overlay) { 154 closeBtn.addEventListener("click", () => this.toggle(false)); 155 overlay.addEventListener("click", (e) => { 156 if (e.target === overlay) this.toggle(false); 157 }); 158 } 159 160 if (searchForm) { 161 searchForm.addEventListener("submit", () => { 162 this.toggle(false); 163 }); 164 } 165 166 this.initSubmenus(); 167 168 const links = overlay?.querySelectorAll(".mobile-nav-main a"); 169 links?.forEach((link) => { 170 link.addEventListener("click", (e) => { 171 const href = link.getAttribute("href"); 172 const target = this.resolveInPageTarget(href); 173 174 if (target) { 175 e.preventDefault(); 176 target.scrollIntoView({ behavior: "smooth", block: "start" }); 177 this.toggle(false); 178 } else if (href) { 179 this.toggle(false); 180 } 181 }); 182 }); 183 }, 184 185 resolveInPageTarget(href) { 186 if (!href) return null; 187 188 let hash = ""; 189 if (href.startsWith("#")) { 190 hash = href; 191 } else if (href.includes("#")) { 192 const [base, targetHash] = href.split("#"); 193 const currentPage = 194 window.location.pathname.split("/").pop() || "index.html"; 195 const normalizedBase = base || currentPage; 196 197 if ( 198 normalizedBase === currentPage || 199 (normalizedBase === "index.html" && 200 (currentPage === "index.html" || currentPage === "")) 201 ) { 202 hash = `#${targetHash}`; 203 } 204 } 205 206 if (!hash || hash === "#") return null; 207 return document.querySelector(hash); 208 }, 209 210 initSubmenus() { 211 const toggles = document.querySelectorAll(".mobile-submenu-toggle"); 212
213 toggles.forEach((toggle) => { 214 toggle.addEventListener("click", (e) => { 215 e.preventDefault(); 216 const submenu = toggle.closest(".mobile-nav-has-submenu").querySelector(".mobile-submenu"); 217 const arrow = toggle.querySelector(".mobile-submenu-arrow"); 218 const isExpanded = toggle.getAttribute("aria-expanded") === "true"; 219 220 toggles.forEach((otherToggle) => { 221 if (otherToggle !== toggle) { 222 otherToggle.setAttribute("aria-expanded", "false"); 223 otherToggle.classList.remove("active"); 224 const otherSubmenu = otherToggle.closest(".mobile-nav-has-submenu").querySelector(".mobile-submenu"); 225 const otherArrow = otherToggle.querySelector( 226 ".mobile-submenu-arrow", 227 ); 228 if (otherSubmenu) otherSubmenu.classList.remove("active"); 229 if (otherArrow) otherArrow.classList.remove("active"); 230 } 231 }); 232 233 toggle.setAttribute("aria-expanded", String(!isExpanded)); 234 toggle.classList.toggle("active", !isExpanded); 235 if (submenu) submenu.classList.toggle("active", !isExpanded); 236 if (arrow) arrow.classList.toggle("active", !isExpanded); 237 }); 238 }); 239 }, 240 241 toggle(show) { 242 const overlay = document.getElementById("mobile-menu-overlay"); 243 if (!overlay) { 244 if (show) { 245 this.render(); 246 setTimeout(() => this.toggle(true), 10); 247 } 248 return; 249 } 250 251 if (show) { 252 overlay.classList.add("active"); 253 document.body.classList.add("mobile-menu-open"); 254 document.body.style.overflow = "hidden"; 255 } else { 256 overlay.classList.remove("active"); 257 document.body.classList.remove("mobile-menu-open"); 258 document.body.style.overflow = ""; 259 260 const toggles = document.querySelectorAll(".mobile-submenu-toggle"); 261 toggles.forEach((toggle) => { 262 toggle.setAttribute("aria-expanded", "false"); 263 toggle.classList.remove("active"); 264 const submenu = toggle.closest(".mobile-nav-has-submenu").querySelector(".mobile-submenu"); 265 const arrow = toggle.querySelector(".mobile-submenu-arrow"); 266 if (submenu) submenu.classList.remove("active"); 267 if (arrow) arrow.classList.remove("active"); 268 }); 269 } 270 }, 271}; 272 273window.CMMobileMenu = MobileMenu;
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.