/** * Template Name: Laura * Updated: Jul 27 2023 with Bootstrap v5.3.1 * Template URL: https://bootstrapmade.com/laura-free-creative-bootstrap-theme/ * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ (function () { "use strict"; /** * Easy selector helper function */ const select = (el, all = false) => { el = el.trim(); if (all) { return [...document.querySelectorAll(el)]; } else { return document.querySelector(el); } }; /** * Easy event listener function */ const on = (type, el, listener, all = false) => { let selectEl = select(el, all); if (selectEl) { if (all) { selectEl.forEach((e) => e.addEventListener(type, listener)); } else { selectEl.addEventListener(type, listener); } } }; /** * Easy on scroll event listener */ const onscroll = (el, listener) => { el.addEventListener("scroll", listener); }; /** * Navbar links active state on scroll */ let navbarlinks = select("#navbar .scrollto", true); const navbarlinksActive = () => { let position = window.scrollY + 200; navbarlinks.forEach((navbarlink) => { if (!navbarlink.hash) return; let section = select(navbarlink.hash); if (!section) return; if ( position >= section.offsetTop && position <= section.offsetTop + section.offsetHeight ) { navbarlink.classList.add("active"); } else { navbarlink.classList.remove("active"); } }); }; window.addEventListener("load", navbarlinksActive); onscroll(document, navbarlinksActive); /** * Scrolls to an element with header offset */ const scrollto = (el) => { let header = select("#header"); let offset = header.offsetHeight; if (!header.classList.contains("header-scrolled")) { offset -= 20; } let elementPos = select(el).offsetTop; window.scrollTo({ top: elementPos - offset, behavior: "smooth", }); }; /** * Toggle .header-scrolled class to #header when page is scrolled */ let selectHeader = select("#header"); if (selectHeader) { const headerScrolled = () => { if (window.scrollY > 100) { selectHeader.classList.add("header-scrolled"); } else { selectHeader.classList.remove("header-scrolled"); } }; window.addEventListener("load", headerScrolled); onscroll(document, headerScrolled); } /** * Back to top button */ let backtotop = select(".back-to-top"); if (backtotop) { const toggleBacktotop = () => { if (window.scrollY > 100) { backtotop.classList.add("active"); } else { backtotop.classList.remove("active"); } }; window.addEventListener("load", toggleBacktotop); onscroll(document, toggleBacktotop); } /** * Mobile nav toggle */ on("click", ".mobile-nav-toggle", function (e) { select("#navbar").classList.toggle("navbar-mobile"); this.classList.toggle("bi-list"); this.classList.toggle("bi-x"); }); /** * Mobile nav dropdowns activate */ on( "click", ".navbar .dropdown > a", function (e) { if (select("#navbar").classList.contains("navbar-mobile")) { e.preventDefault(); this.nextElementSibling.classList.toggle("dropdown-active"); } }, true ); /** * Scrool with ofset on links with a class name .scrollto */ on( "click", ".scrollto", function (e) { if (select(this.hash)) { e.preventDefault(); let navbar = select("#navbar"); if (navbar.classList.contains("navbar-mobile")) { navbar.classList.remove("navbar-mobile"); let navbarToggle = select(".mobile-nav-toggle"); navbarToggle.classList.toggle("bi-list"); navbarToggle.classList.toggle("bi-x"); } scrollto(this.hash); } }, true ); /** * Scroll with ofset on page load with hash links in the url */ window.addEventListener("load", () => { if (window.location.hash) { if (select(window.location.hash)) { scrollto(window.location.hash); } } }); /** * Skills animation */ let skillsContent = select(".progress", true); if (skillsContent) { skillsContent.forEach((skill) => { new Waypoint({ element: skill, offset: "100%", handler: function (direction) { let progress = skill.querySelectorAll(".progress-bar"); progress.forEach((el) => { let percent = 100 * (+el.getAttribute("aria-valuenow") / (+el.getAttribute("aria-valuemax") - +el.getAttribute("aria-valuemin"))); el.style.width = percent + "%"; }); }, }); }); } /** * Testimonials slider */ new Swiper(".testimonials-slider", { speed: 600, loop: true, autoplay: { delay: 10000, disableOnInteraction: false, }, slidesPerView: "auto", pagination: { el: ".swiper-pagination", type: "bullets", clickable: true, }, }); window.addEventListener("load", () => { /** * Skills isotope and filter */ let skillsContainer = select(".skills-container"); if (skillsContainer) { let skillsIsotope = new Isotope(skillsContainer, { itemSelector: ".skill-item", }); let skillsFilters = select("#skills-filters li", true); on( "click", "#skills-filters li", function (e) { e.preventDefault(); skillsFilters.forEach(function (el) { el.classList.remove("filter-active"); }); this.classList.add("filter-active"); skillsIsotope.arrange({ filter: this.getAttribute("data-filter"), }); }, true ); } /** * Porfolio isotope and filter */ let portfolioContainer = select(".portfolio-container"); if (portfolioContainer) { let portfolioIsotope = new Isotope(portfolioContainer, { itemSelector: ".portfolio-item", }); let portfolioFilters = select("#portfolio-flters li", true); on( "click", "#portfolio-flters li", function (e) { e.preventDefault(); portfolioFilters.forEach(function (el) { el.classList.remove("filter-active"); }); this.classList.add("filter-active"); portfolioIsotope.arrange({ filter: this.getAttribute("data-filter"), }); }, true ); } // let horizontal_aoss = document.querySelectorAll("[data-aos~='left'], [data-aos~='right']") if (window.matchMedia("(max-width: 768px)").matches) { let horizontal_aoss = document.querySelectorAll( `[data-aos$="left"], [data-aos$="right"]` ); horizontal_aoss.forEach((el) => el.setAttribute("data-aos", "fade-up")); } AOS.init(); }); /** * Initiate portfolio lightbox */ const portfolioLightbox = GLightbox({ selector: ".portfolio-lightbox", }); /** * Portfolio details slider */ new Swiper(".portfolio-details-slider", { speed: 400, loop: true, autoplay: { delay: 5000, disableOnInteraction: false, }, pagination: { el: ".swiper-pagination", type: "bullets", clickable: true, }, }); if (localStorage.getItem("theme") == "light") { toggleDarkMode(); } // Set age correctly (cuz sbatti farlo ogni // anno, toi meme tu sais) let age_span = document.querySelector("#age"); age_span.textContent = calculateAge("1999-10-15"); })(); function toggleDarkMode() { let dark_indicator = document.querySelector("#navbar i"); dark_indicator.classList.toggle("bi-moon-stars-fill"); dark_indicator.classList.toggle("bi-sun-fill"); document.body.classList.toggle("dark"); let theme = document.body.classList.contains("dark") ? "dark" : "light"; document.documentElement.style.setProperty("color-scheme", theme); localStorage.setItem("theme", theme); } function calculateAge(birthDate) { const today = new Date(); const birth = new Date(birthDate); let age = today.getFullYear() - birth.getFullYear(); const monthDifference = today.getMonth() - birth.getMonth(); // Check if the birthday has not occurred yet this year if (monthDifference < 0 || (monthDifference === 0 && today.getDate() < birth.getDate())) { age--; } return age; }