1(function() { 2 "use strict"; 3 4 /** 5 * Easy selector helper function 6 */ 7 const select = (el, all = false) => { 8 el = el.trim() 9 if (all) { 10 return [...document.querySelectorAll(el)] 11 } else { 12 return document.querySelector(el) 13 } 14 } 15 16 /** 17 * Easy event listener function 18 */ 19 const on = (type, el, listener, all = false) => { 20 let selectEl = select(el, all) 21 if (selectEl) { 22 if (all) { 23 selectEl.forEach(e => e.addEventListener(type, listener)) 24 } else { 25 selectEl.addEventListener(type, listener) 26 } 27 } 28 } 29 30 /** 31 * Easy on scroll event listener 32 */ 33 const onscroll = (el, listener) => { 34 el.addEventListener('scroll', listener) 35 } 36 37 /** 38 * Navbar links active state on scroll 39 */ 40 let navbarlinks = select('#navbar .scrollto', true) 41 const navbarlinksActive = () => { 42 let position = window.scrollY + 200 43 navbarlinks.forEach(navbarlink => { 44 if (!navbarlink.hash) return 45 let section = select(navbarlink.hash) 46 if (!section) return 47 if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) { 48 navbarlink.classList.add('active') 49 } else { 50 navbarlink.classList.remove('active') 51 } 52 }) 53 } 54 window.addEventListener('load', navbarlinksActive) 55 onscroll(document, navbarlinksActive) 56 57 /** 58 * Scrolls to an element with header offset 59 */ 60 const scrollto = (el) => { 61 let header = select('#header') 62 let offset = header.offsetHeight 63 64 if (!header.classList.contains('header-scrolled')) { 65 offset -= 16 66 } 67 68 let elementPos = select(el).offsetTop 69 window.scrollTo({ 70 top: elementPos - offset, 71 behavior: 'smooth' 72 }) 73 } 74 75 /** 76 * Header fixed top on scroll 77 */ 78 let selectHeader = select('#header') 79 if (selectHeader) { 80 let headerOffset = selectHeader.offsetTop 81 let nextElement = selectHeader.nextElementSibling 82 const headerFixed = () => { 83 if ((headerOffset - window.scrollY) <= 0) { 84 selectHeader.classList.add('fixed-top') 85 nextElement.classList.add('scrolled-offset') 86 } else { 87 selectHeader.classList.remove('fixed-top') 88 nextElement.classList.remove('scrolled-offset') 89 } 90 } 91 window.addEventListener('load', headerFixed) 92 onscroll(document, headerFixed) 93 } 94 95 /** 96 * Back to top button 97 */ 98 let backtotop = select('.back-to-top') 99 if (backtotop) { 100 const toggleBacktotop = () => { 101 if (window.scrollY > 100) { 102 backtotop.classList.add('active') 103 } else { 104 backtotop.classList.remove('active') 105 } 106 } 107 window.addEventListener('load', toggleBacktotop) 108 onscroll(document, toggleBacktotop) 109 } 110 111 /** 112 * Mobile nav toggle 113 */ 114 on('click', '.mobile-nav-toggle', function(e) { 115 select('#navbar').classList.toggle('navbar-mobile') 116 this.classList.toggle('bi-list') 117 this.classList.toggle('bi-x') 118 }) 119 120 /** 121 * Mobile nav dropdowns activate 122 */ 123 on('click', '.navbar .dropdown > a', function(e) { 124 if (select('#navbar').classList.contains('navbar-mobile')) { 125 e.preventDefault() 126 this.nextElementSibling.classList.toggle('dropdown-active') 127 } 128 }, true) 129 130 /** 131 * Scrool with ofset on links with a class name .scrollto 132 */ 133 on('click', '.scrollto', function(e) { 134 if (select(this.hash)) { 135 e.preventDefault() 136 137 let navbar = select('#navbar') 138 if (navbar.classList.contains('navbar-mobile')) { 139 navbar.classList.remove('navbar-mobile') 140 let navbarToggle = select('.mobile-nav-toggle') 141 navbarToggle.classList.toggle('bi-list') 142 navbarToggle.classList.toggle('bi-x') 143 } 144 scrollto(this.hash) 145 } 146 }, true) 147 148 /** 149 * Scroll with ofset on page load with hash links in the url 150 */ 151 window.addEventListener('load', () => { 152 if (window.location.hash) { 153 if (select(window.location.hash)) { 154 scrollto(window.location.hash) 155 } 156 } 157 }); 158 159 /** 160 * Preloader 161 */ 162 let preloader = select('#preloader'); 163 if (preloader) { 164 window.addEventListener('load', () => { 165 preloader.remove() 166 }); 167 } 168 169 /** 170 * Initiate glightbox 171 */ 172 const glightbox = GLightbox({ 173 selector: '.glightbox' 174 }); 175 176/** 177 * Porfolio isotope and filter 178 */ 179 window.addEventListener('load', () => { 180 let portfolioContainer = select('.portfolio-container'); 181 if (portfolioContainer) { 182 let portfolioIsotope = new Isotope(portfolioContainer, { 183 itemSelector: '.portfolio-item', 184 originLeft: false 185 }); 186 187 let portfolioFilters = select('#portfolio-flters li', true); 188 189 on('click', '#portfolio-flters li', function(e) { 190 e.preventDefault();
191 portfolioFilters.forEach(function(el) { 192 el.classList.remove('filter-active'); 193 }); 194 this.classList.add('filter-active'); 195 196 portfolioIsotope.arrange({ 197 filter: this.getAttribute('data-filter') 198 }); 199 }, true); 200 201 portfolioFilters[1].click(); 202 203 } 204 205 }); 206 207 /** 208 * Initiate portfolio lightbox 209 */ 210 const portfolioLightbox = GLightbox({ 211 selector: '.portfolio-lightbox' 212 }); 213 214 // Get all the tab buttons and tabs 215 const tabButtons = document.querySelectorAll('.tab-buttons button'); 216 const tabs = document.querySelectorAll('.tab'); 217 218 // Add click event listener to tab buttons 219 tabButtons.forEach((button, index) => { 220 button.addEventListener('click', () => { 221 // Remove active class from all buttons and tabs 222 tabButtons.forEach(btn => btn.classList.remove('active')); 223 tabs.forEach(tab => tab.classList.remove('active')); 224 225 // Add active class to clicked button and corresponding tab 226 button.classList.add('active'); 227 const filter = button.dataset.filter;
228 tabs.forEach(tab => { 229 if (tab.dataset.type === filter) { 230 tab.classList.add('active'); 231 } 232 }); 233 }); 234 }); 235 236$("a.nino-search, #nino-searchForm .nino-close").click(function(){ 237 $("#nino-searchForm").toggleClass("open"); 238 }); 239 240 /** 241 * Initiate Pure Counter 242 */ 243 new PureCounter(); 244 245})()
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.