1/** 2* Agência New - Soluções para Ãrgãos Públicos 3*/ 4(function() { 5 "use strict"; 6 7 /** 8 * Easy selector helper function 9 */ 10 const select = (el, all = false) => { 11 el = el.trim() 12 if (all) { 13 return [...document.querySelectorAll(el)] 14 } else { 15 return document.querySelector(el) 16 } 17 } 18 19 /** 20 * Easy event listener function 21 */ 22 const on = (type, el, listener, all = false) => { 23 let selectEl = select(el, all) 24 if (selectEl) { 25 if (all) { 26 selectEl.forEach(e => e.addEventListener(type, listener)) 27 } else { 28 selectEl.addEventListener(type, listener) 29 } 30 } 31 } 32 33 // ============================================================= 34// MOBILE NAVIGATION 35// ============================================================= 36 37const mobileNavToggleBtn = document.querySelector('.mobile-nav-toggle'); 38 39/** 40 * Abre / fecha o menu mobile 41 */ 42function mobileNavToggle() { 43 document.body.classList.toggle('mobile-nav-active'); 44 45 if (mobileNavToggleBtn) { 46 mobileNavToggleBtn.classList.toggle('bi-list'); 47 mobileNavToggleBtn.classList.toggle('bi-x'); 48 } 49 50 /* Ao fechar o menu, fecha também todos os submenus */ 51 if (!document.body.classList.contains('mobile-nav-active')) { 52 document.querySelectorAll('.navmenu .dropdown-active').forEach(function(submenu) { 53 submenu.classList.remove('dropdown-active'); 54 }); 55 56 document.querySelectorAll('.navmenu .dropdown > a.active').forEach(function(link) { 57 link.classList.remove('active'); 58 }); 59 } 60} 61 62/** 63 * Botão hambúrguer / fechar 64 */ 65if (mobileNavToggleBtn) { 66 mobileNavToggleBtn.addEventListener('click', function(e) { 67 e.preventDefault(); 68 mobileNavToggle(); 69 }); 70} 71 72/** 73 * Dropdowns do menu mobile 74 * O clique funciona tanto no texto quanto na seta 75 */ 76document.querySelectorAll('.navmenu .dropdown > a').forEach(function(dropdownLink) { 77 78 dropdownLink.addEventListener('click', function(e) { 79 80 // No desktop mantém o comportamento normal 81 if (window.innerWidth >= 1200) return; 82 83 const submenu = this.nextElementSibling; 84 85 // Se possuir submenu, abre/fecha sem fechar o menu principal 86 if (submenu && submenu.tagName === 'UL') { 87 e.preventDefault(); 88 e.stopPropagation(); 89 90 this.classList.toggle('active'); 91 submenu.classList.toggle('dropdown-active'); 92 } 93 }); 94 95}); 96 97/** 98 * Fecha o menu mobile somente ao clicar em um link final, 99 * ou seja, um item que NÃO possui submenu. 100 */ 101document.querySelectorAll('.navmenu a').forEach(function(link) { 102 103 link.addEventListener('click', function() { 104 105 if (window.innerWidth >= 1200) return; 106 107 const submenu = this.nextElementSibling; 108 const hasSubmenu = submenu && submenu.tagName === 'UL'; 109 110 if ( 111 !hasSubmenu && 112 document.body.classList.contains('mobile-nav-active') 113 ) { 114 mobileNavToggle(); 115 } 116 117 }); 118 119}); 120 121 122 123 /** 124 * Easy on scroll event listener 125 */ 126 const onscroll = (el, listener) => { 127 el.addEventListener('scroll', listener) 128 } 129 130 /** 131 * Scrolls to an element with header offset 132 */ 133 const scrollto = (el) => { 134 let header = select('#header') 135 let offset = header.offsetHeight 136 137 if (!header.classList.contains('header-scrolled')) { 138 offset -= 16 139 } 140 141 let elementPos = select(el).offsetTop 142 window.scrollTo({ 143 top: elementPos - offset, 144 behavior: 'smooth' 145 }) 146 } 147 148 /** 149 * Header fixed top on scroll 150 */ 151 let selectHeader = select('#header') 152 if (selectHeader) { 153 let headerOffset = selectHeader.offsetTop 154 let nextElement = selectHeader.nextElementSibling 155 const headerFixed = () => { 156 if ((headerOffset - window.scrollY) <= 0) { 157 selectHeader.classList.add('fixed-top') 158 nextElement.classList.add('scrolled-offset') 159 } else { 160 selectHeader.classList.remove('fixed-top') 161 nextElement.classList.remove('scrolled-offset') 162 } 163 } 164 window.addEventListener('load', headerFixed) 165 onscroll(document, headerFixed) 166 } 167 168 /** 169 * Back to top button 170 */ 171 let backtotop = select('.back-to-top') 172 if (backtotop) { 173 const toggleBacktotop = () => { 174 if (window.scrollY > 100) { 175 backtotop.classList.add('active') 176 } else { 177 backtotop.classList.remove('active') 178 } 179 } 180 window.addEventListener('load', toggleBacktotop) 181 onscroll(document, toggleBacktotop) 182 } 183 184 185 186 /** 187 * Scroll with ofset on page load with hash links in the url 188 */ 189 window.addEventListener('load', () => { 190 if (window.location.hash) { 191 if (select(window.location.hash)) { 192 scrollto(window.location.hash) 193 } 194 } 195 }); 196 197 /** 198 * Preloader 199 */ 200 let preloader = select('#preloader'); 201 if (preloader) { 202 window.addEventListener('load', () => { 203 preloader.remove() 204 });
205 } 206 207 /** 208 * Initiate glightbox 209 */ 210 const glightbox = GLightbox({ 211 selector: '.glightbox' 212 }); 213 214 /** 215 * Skills animation 216 */ 217 let skilsContent = select('.skills-content'); 218 if (skilsContent) { 219 new Waypoint({ 220 element: skilsContent, 221 offset: '80%', 222 handler: function(direction) { 223 let progress = select('.progress .progress-bar', true); 224 progress.forEach((el) => { 225 el.style.width = el.getAttribute('aria-valuenow') + '%' 226 }); 227 } 228 }) 229 } 230 231 /** 232 * Testimonials slider 233 */ 234 new Swiper('.testimonials-slider', { 235 speed: 600, 236 loop: true, 237 autoplay: { 238 delay: 5000, 239 disableOnInteraction: false 240 }, 241 slidesPerView: 'auto', 242 pagination: { 243 el: '.swiper-pagination', 244 type: 'bullets', 245 clickable: true 246 } 247 }); 248 249 /** 250 * Porfolio isotope and filter 251 */ 252 window.addEventListener('load', () => { 253 let portfolioContainer = select('.portfolio-container'); 254 if (portfolioContainer) { 255 let portfolioIsotope = new Isotope(portfolioContainer, { 256 itemSelector: '.portfolio-item' 257 }); 258 259 let portfolioFilters = select('#portfolio-flters li', true); 260 261 on('click', '#portfolio-flters li', function(e) { 262 e.preventDefault(); 263 portfolioFilters.forEach(function(el) { 264 el.classList.remove('filter-active'); 265 }); 266 this.classList.add('filter-active'); 267 268 portfolioIsotope.arrange({ 269 filter: this.getAttribute('data-filter') 270 }); 271 portfolioIsotope.on('arrangeComplete', function() { 272 AOS.refresh() 273 }); 274 }, true); 275 } 276 277 }); 278 279 /** 280 * Initiate portfolio lightbox 281 */ 282 const portfolioLightbox = GLightbox({ 283 selector: '.portfolio-lightbox' 284 }); 285 286 /** 287 * Portfolio details slider 288 */ 289 new Swiper('.portfolio-details-slider', { 290 speed: 400, 291 loop: true, 292 autoplay: { 293 delay: 5000, 294 disableOnInteraction: false 295 }, 296 pagination: { 297 el: '.swiper-pagination', 298 type: 'bullets', 299 clickable: true 300 } 301 }); 302 303 /** 304 * Animation on scroll 305 */ 306 window.addEventListener('load', () => { 307 AOS.init({ 308 duration: 1000, 309 easing: 'ease-in-out', 310 once: true, 311 mirror: false 312 }) 313 }); 314 315 /** 316 * Initiate Pure Counter 317 */ 318 new PureCounter(); 319 320})() 321 322/** 323 * Banner principal - Slideshow 324 */ 325const bannerSlides = document.querySelectorAll('.banner-slide'); 326const bannerIndicadores = document.querySelectorAll('.banner-indicadores button'); 327const bannerAnterior = document.querySelector('.banner-anterior'); 328const bannerProximo = document.querySelector('.banner-proximo'); 329 330if (bannerSlides.length) { 331 let bannerAtual = 0; 332 let bannerIntervalo; 333 334 function mostrarBanner(index) {
335 bannerSlides.forEach(slide => slide.classList.remove('ativo')); 336 bannerIndicadores.forEach(indicador => indicador.classList.remove('ativo')); 337 338 bannerAtual = (index + bannerSlides.length) % bannerSlides.length; 339 340 bannerSlides[bannerAtual].classList.add('ativo'); 341 342 if (bannerIndicadores[bannerAtual]) { 343 bannerIndicadores[bannerAtual].classList.add('ativo'); 344 } 345 } 346 347 function iniciarBanner() { 348 clearInterval(bannerIntervalo); 349 bannerIntervalo = setInterval(() => { 350 mostrarBanner(bannerAtual + 1); 351 }, 5000); 352 } 353 354 bannerProximo?.addEventListener('click', () => { 355 mostrarBanner(bannerAtual + 1); 356 iniciarBanner(); 357 }); 358 359 bannerAnterior?.addEventListener('click', () => { 360 mostrarBanner(bannerAtual - 1); 361 iniciarBanner(); 362 }); 363 364 bannerIndicadores.forEach((indicador, index) => { 365 indicador.addEventListener('click', () => { 366 mostrarBanner(index); 367 iniciarBanner(); 368 }); 369 }); 370 371 mostrarBanner(0); 372 iniciarBanner(); 373}
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.