/*! * Personal website of Sefa Eyeoglu * Copyright (C) 2018-2022 Sefa Eyeoglu * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import ready from "./_utils"; const mainElem = document.getElementById("main"); document.querySelectorAll(".scrumplex-logo").forEach((elem) => { elem.addEventListener("dblclick", () => { const randomRotation = Math.floor(Math.random() * 360); elem.style.transform = `rotate(${randomRotation}deg)`; }); }); document.querySelectorAll("*[data-scroll]").forEach((elem) => { elem.addEventListener("click", (e) => { e.preventDefault(); const targetSelector = elem.getAttribute("data-scroll"); applyScrollSpecial(targetSelector); }); }); mainElem.addEventListener("animationend", applyScrollInitially); function applyScrollInitially() { mainElem.removeEventListener("animationend", applyScrollInitially); window.addEventListener("scroll", applyScrollConditionally); if (location.hash.startsWith("#")) { const result = applyScrollSpecial(location.hash); if (result) return; } applyScrollConditionally(); } function applyScrollConditionally() { if ( mainElem.getBoundingClientRect().top <= 0 || // offset to top window border mainElem.getBoundingClientRect().height >= window.innerHeight ) applyScroll(); } function applyScrollSpecial(targetSelector) { if (!targetSelector) return false; const targetElem = document.querySelector(targetSelector); if (!targetElem) return false; const offset = applyScroll(targetElem); window.scrollTo({ top: offset, behavior: "smooth" }); history.pushState({ hash: targetSelector }, "", targetSelector); return true; } function applyScroll(scrollTarget = null) { // Black magic ahead! // We sometimes need this method to show all sheets and then scroll to one of them. // To achieve this we need to have a way to get the target position (like pixels) of // the sheet we want to scroll to (in this case it's scrollTarget). // As the bounding box always includes current transforms (so our translateY in the // fade-in animation) we need to somehow get the boundingBox while our sheet is not // being transformed. A hacky way to do this is to modify the behavior of .sheet[hidden] // depending on the state of this method. In this case we are adding .scrolled to body // which will cause all hidden sheets to instead be transparent. // Additionally we will stop any animations that would be playing then. // Now the element should be at it's target position so we just grab the position before // un-hiding the elements and voila! // One caveat: if the content changes after this method returned, the scroll might be a // bit offset. let offset = getElementScrollOffset(scrollTarget); if (document.body.classList.contains("scrolled")) return offset; const hiddenElems = document.querySelectorAll(".sheet[hidden]"), posMain = getElementScrollOffset(mainElem); // offset to top rel. to document document.getElementById("wrapper").style.paddingTop = `${posMain}px`; document.body.classList.add("scrolled"); mainElem.classList.add("sheet-splashed"); mainElem.classList.remove("sheet-splash"); if (scrollTarget) // recalculate, as it probably changed because of body.scrolled offset = getElementScrollOffset(scrollTarget); hiddenElems.forEach((elem) => { elem.removeAttribute("hidden"); }); window.removeEventListener("scroll", applyScrollConditionally); return offset; } function startSpinningChars(fps = 4) { const spinningChars = ["|", "/", "-", "\\"], spinnerElement = document.getElementById("text-spinner"); let currentIndex = 0; setInterval(() => { spinnerElement.innerText = spinningChars[currentIndex]; currentIndex++; if (currentIndex >= spinningChars.length) currentIndex = 0; }, 1000 / fps); spinnerElement.removeAttribute("hidden"); } function getElementScrollOffset(elem) { if (elem) return window.pageYOffset + elem.getBoundingClientRect().top; return -1; } ready().then(() => { startSpinningChars(); });