updateweb
This commit is contained in:
79
website/assets/js/navigation.js
Normal file
79
website/assets/js/navigation.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// Dynamic Menu Loader for Sky Art Shop
|
||||
// Include this in all public pages to load menu from database
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Load and render navigation menu from API
|
||||
async function loadNavigationMenu() {
|
||||
try {
|
||||
const response = await fetch("/api/menu");
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success && data.items && data.items.length > 0) {
|
||||
renderDesktopMenu(data.items);
|
||||
renderMobileMenu(data.items);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to load menu:", error);
|
||||
// Keep existing hardcoded menu as fallback
|
||||
}
|
||||
}
|
||||
|
||||
function renderDesktopMenu(items) {
|
||||
const desktopMenuList = document.querySelector(".nav-menu-list");
|
||||
if (!desktopMenuList) return;
|
||||
|
||||
desktopMenuList.innerHTML = items
|
||||
.map(
|
||||
(item) => `
|
||||
<li class="nav-item">
|
||||
<a href="${item.url}" class="nav-link">
|
||||
${item.icon ? `<i class="bi ${item.icon}"></i> ` : ""}${item.label}
|
||||
</a>
|
||||
</li>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
|
||||
// Set active state based on current page
|
||||
const currentPath = window.location.pathname;
|
||||
document.querySelectorAll(".nav-link").forEach((link) => {
|
||||
if (link.getAttribute("href") === currentPath) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function renderMobileMenu(items) {
|
||||
const mobileMenuList = document.querySelector(".mobile-menu-list");
|
||||
if (!mobileMenuList) return;
|
||||
|
||||
mobileMenuList.innerHTML = items
|
||||
.map(
|
||||
(item) => `
|
||||
<li>
|
||||
<a href="${item.url}" class="mobile-link">
|
||||
${item.icon ? `<i class="bi ${item.icon}"></i> ` : ""}${item.label}
|
||||
</a>
|
||||
</li>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
|
||||
// Set active state for mobile menu
|
||||
const currentPath = window.location.pathname;
|
||||
document.querySelectorAll(".mobile-link").forEach((link) => {
|
||||
if (link.getAttribute("href") === currentPath) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load menu when DOM is ready
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", loadNavigationMenu);
|
||||
} else {
|
||||
loadNavigationMenu();
|
||||
}
|
||||
})();
|
||||
143
website/assets/js/page-transitions.js
Normal file
143
website/assets/js/page-transitions.js
Normal file
@@ -0,0 +1,143 @@
|
||||
// Smooth Page Transitions for Sky Art Shop
|
||||
// Provides fade-out/fade-in effects when navigating between pages
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Add page transition styles (less aggressive approach)
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
body {
|
||||
transition: opacity 0.25s ease-in-out;
|
||||
}
|
||||
|
||||
body.page-transitioning {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Fade in page on load (if coming from a transition)
|
||||
function initPageTransition() {
|
||||
// Check if we're coming from a transition
|
||||
const isTransitioning = sessionStorage.getItem("page-transitioning");
|
||||
if (isTransitioning === "true") {
|
||||
document.body.style.opacity = "0";
|
||||
sessionStorage.removeItem("page-transitioning");
|
||||
|
||||
// Wait for content to be ready, then fade in
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
document.body.style.opacity = "1";
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Handle navigation with transitions
|
||||
function setupNavigationTransitions() {
|
||||
// Get all internal links
|
||||
document.addEventListener("click", function (e) {
|
||||
const link = e.target.closest("a");
|
||||
|
||||
if (!link) return;
|
||||
|
||||
const href = link.getAttribute("href");
|
||||
|
||||
// Skip if:
|
||||
// - External link
|
||||
// - Opens in new tab
|
||||
// - Has download attribute
|
||||
// - Is a hash link on same page
|
||||
// - Is a javascript: link
|
||||
// - Is a mailto: or tel: link
|
||||
if (
|
||||
!href ||
|
||||
link.target === "_blank" ||
|
||||
link.hasAttribute("download") ||
|
||||
href.startsWith("javascript:") ||
|
||||
href.startsWith("mailto:") ||
|
||||
href.startsWith("tel:") ||
|
||||
href.startsWith("#") ||
|
||||
(href.includes("://") && !href.includes(window.location.host))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent default navigation
|
||||
e.preventDefault();
|
||||
|
||||
// Start transition
|
||||
document.body.classList.add("page-transitioning");
|
||||
sessionStorage.setItem("page-transitioning", "true");
|
||||
|
||||
// Navigate after fade-out completes
|
||||
setTimeout(() => {
|
||||
window.location.href = href;
|
||||
}, 250); // Match CSS transition duration
|
||||
});
|
||||
}
|
||||
|
||||
// Use View Transitions API if available (Chrome 111+, Safari 18+)
|
||||
function setupViewTransitions() {
|
||||
if (!document.startViewTransition) return;
|
||||
|
||||
document.addEventListener(
|
||||
"click",
|
||||
function (e) {
|
||||
const link = e.target.closest("a");
|
||||
|
||||
if (!link) return;
|
||||
|
||||
const href = link.getAttribute("href");
|
||||
|
||||
// Same checks as above
|
||||
if (
|
||||
!href ||
|
||||
link.target === "_blank" ||
|
||||
link.hasAttribute("download") ||
|
||||
href.startsWith("javascript:") ||
|
||||
href.startsWith("mailto:") ||
|
||||
href.startsWith("tel:") ||
|
||||
href.startsWith("#") ||
|
||||
(href.includes("://") && !href.includes(window.location.host))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Use View Transitions API for smooth cross-page transitions
|
||||
sessionStorage.setItem("page-transitioning", "true");
|
||||
document.startViewTransition(() => {
|
||||
window.location.href = href;
|
||||
});
|
||||
},
|
||||
true
|
||||
); // Use capture to run before other handlers
|
||||
}
|
||||
|
||||
// Initialize
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
initPageTransition();
|
||||
setupNavigationTransitions();
|
||||
});
|
||||
} else {
|
||||
initPageTransition();
|
||||
setupNavigationTransitions();
|
||||
}
|
||||
|
||||
// For browsers that support View Transitions API (progressive enhancement)
|
||||
if ("startViewTransition" in document) {
|
||||
const viewStyle = document.createElement("style");
|
||||
viewStyle.textContent = `
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(viewStyle);
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user