mirror of
https://github.com/asimonson1125/asimonson1125.github.io.git
synced 2026-09-22 11:35:33 -05:00
122 lines
3.8 KiB
JavaScript
Executable File
122 lines
3.8 KiB
JavaScript
Executable File
function toggleMenu(collapse) {
|
|
if (window.innerWidth < 1400) {
|
|
const menu = document.querySelector(".navControl");
|
|
const bar = document.querySelector(".header");
|
|
const btn = document.getElementById("menu");
|
|
const isCollapsed = !menu.style.maxHeight || menu.style.maxHeight === "0px";
|
|
|
|
if (isCollapsed && !collapse) {
|
|
menu.style.maxHeight = `${menu.scrollHeight + 10}px`;
|
|
bar.style.borderBottomWidth = "0px";
|
|
if (btn) btn.setAttribute("aria-expanded", "true");
|
|
} else {
|
|
menu.style.maxHeight = "0px";
|
|
bar.style.borderBottomWidth = "3px";
|
|
if (btn) btn.setAttribute("aria-expanded", "false");
|
|
}
|
|
}
|
|
}
|
|
|
|
async function goto(location, { push = true } = {}) {
|
|
const loadingBar = document.getElementById('loading-bar');
|
|
|
|
if (loadingBar) {
|
|
loadingBar.style.width = ''; // Clear inline style from previous run
|
|
}
|
|
|
|
let loadingTimeout = setTimeout(() => {
|
|
if (loadingBar) {
|
|
loadingBar.classList.remove('finish');
|
|
loadingBar.classList.add('active');
|
|
loadingBar.classList.add('visible');
|
|
}
|
|
}, 150);
|
|
|
|
try {
|
|
const response = await fetch("/api/goto/" + location, {
|
|
credentials: "include",
|
|
method: "GET",
|
|
mode: "cors",
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}`);
|
|
}
|
|
|
|
// Wait for the full body to download - this is usually the slow part
|
|
const [metadata, content] = await response.json();
|
|
|
|
document.dispatchEvent(new Event('beforenavigate'));
|
|
|
|
const root = document.getElementById("root");
|
|
root.innerHTML = content;
|
|
|
|
// Re-execute scripts
|
|
root.querySelectorAll("script").forEach(function(oldScript) {
|
|
const newScript = document.createElement("script");
|
|
Array.from(oldScript.attributes).forEach(function(attr) {
|
|
newScript.setAttribute(attr.name, attr.value);
|
|
});
|
|
newScript.textContent = oldScript.textContent;
|
|
oldScript.parentNode.replaceChild(newScript, oldScript);
|
|
});
|
|
|
|
if (window.location.href.includes("#")) {
|
|
const id = decodeURIComponent(window.location.hash.substring(1));
|
|
const el = document.getElementById(id);
|
|
if (el) el.scrollIntoView();
|
|
} else {
|
|
window.scrollTo({ top: 0, left: 0, behavior: "instant" });
|
|
}
|
|
|
|
toggleMenu(true);
|
|
document.querySelector("title").textContent = metadata["title"];
|
|
if (push) {
|
|
history.pushState(null, null, metadata["canonical"]);
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error("Navigation failed:", err);
|
|
} finally {
|
|
clearTimeout(loadingTimeout);
|
|
if (loadingBar && loadingBar.classList.contains('active')) {
|
|
loadingBar.classList.add('finish');
|
|
loadingBar.classList.remove('active');
|
|
setTimeout(() => {
|
|
if (!loadingBar.classList.contains('active')) {
|
|
loadingBar.style.width = '0%';
|
|
loadingBar.classList.remove('finish');
|
|
loadingBar.classList.remove('visible');
|
|
}
|
|
}, 500);
|
|
}
|
|
}
|
|
}
|
|
|
|
function backButton() {
|
|
const path = window.location.pathname;
|
|
goto(path.substring(1), { push: false });
|
|
}
|
|
|
|
function toggleFeatureProject(header) {
|
|
const panel = header.closest(".feature-project");
|
|
const expanded = panel.classList.toggle("expanded");
|
|
header.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
}
|
|
|
|
function activeSkill(obj) {
|
|
let skill = obj.closest(".skill");
|
|
if (skill.classList.contains("activeSkill")) {
|
|
skill.classList.remove("activeSkill");
|
|
const btn = obj.closest('.skillname') || obj.querySelector?.('.skillname') || obj;
|
|
if (btn && btn.setAttribute) btn.setAttribute("aria-expanded", "false");
|
|
return;
|
|
}
|
|
while (skill) {
|
|
skill.classList.add("activeSkill");
|
|
const nameEl = skill.querySelector?.(':scope > .skillname') || skill.querySelector('.skillname');
|
|
if (nameEl) nameEl.setAttribute("aria-expanded", "true");
|
|
skill = skill.parentElement.closest(".skill");
|
|
}
|
|
}
|